Marco Ricci commited on 2025-02-05 14:40:56
Zeige 1 geänderte Dateien mit 109 Einfügungen und 14 Löschungen.
Have the existing or the new notes be generated data (whichever is appropriate). Also handle the previously untested case of aborting the notes edit when there are no stored notes yet. *This* test does not use hypothesis.
... | ... |
@@ -29,7 +29,11 @@ from typing_extensions import Any, NamedTuple |
29 | 29 |
|
30 | 30 |
import tests |
31 | 31 |
from derivepassphrase import _types, cli, ssh_agent, vault |
32 |
-from derivepassphrase._internals import cli_helpers, cli_machinery |
|
32 |
+from derivepassphrase._internals import ( |
|
33 |
+ cli_helpers, |
|
34 |
+ cli_machinery, |
|
35 |
+ cli_messages, |
|
36 |
+) |
|
33 | 37 |
|
34 | 38 |
if TYPE_CHECKING: |
35 | 39 |
from collections.abc import Callable, Iterable, Iterator, Sequence |
... | ... |
@@ -2464,14 +2468,24 @@ class TestCLI: |
2464 | 2468 |
'expected error exit and known error message' |
2465 | 2469 |
) |
2466 | 2470 |
|
2471 |
+ @hypothesis.given( |
|
2472 |
+ notes=strategies.text( |
|
2473 |
+ strategies.characters( |
|
2474 |
+ min_codepoint=32, max_codepoint=126, include_characters='\n' |
|
2475 |
+ ), |
|
2476 |
+ min_size=1, |
|
2477 |
+ max_size=512, |
|
2478 |
+ ).filter(str.strip), |
|
2479 |
+ ) |
|
2467 | 2480 |
def test_220_edit_notes_successfully( |
2468 | 2481 |
self, |
2482 |
+ notes: str, |
|
2469 | 2483 |
) -> None: |
2470 | 2484 |
"""Editing notes works.""" |
2471 |
- edit_result = """ |
|
2485 |
+ edit_result = f""" |
|
2472 | 2486 |
|
2473 | 2487 |
# - - - - - >8 - - - - - >8 - - - - - >8 - - - - - >8 - - - - - |
2474 |
-insert witty notes here |
|
2488 |
+{notes} |
|
2475 | 2489 |
""" |
2476 | 2490 |
runner = click.testing.CliRunner(mix_stderr=False) |
2477 | 2491 |
# TODO(the-13th-letter): Rewrite using parenthesized |
... | ... |
@@ -2503,13 +2517,34 @@ insert witty notes here |
2503 | 2517 |
config = json.load(infile) |
2504 | 2518 |
assert config == { |
2505 | 2519 |
'global': {'phrase': 'abc'}, |
2506 |
- 'services': {'sv': {'notes': 'insert witty notes here'}}, |
|
2520 |
+ 'services': {'sv': {'notes': notes.strip()}}, |
|
2507 | 2521 |
} |
2508 | 2522 |
|
2523 |
+ @pytest.mark.parametrize('edit_func_name', ['empty', 'space']) |
|
2524 |
+ @hypothesis.given( |
|
2525 |
+ notes=strategies.text( |
|
2526 |
+ strategies.characters( |
|
2527 |
+ min_codepoint=32, max_codepoint=126, include_characters='\n' |
|
2528 |
+ ), |
|
2529 |
+ min_size=1, |
|
2530 |
+ max_size=512, |
|
2531 |
+ ).filter(str.strip), |
|
2532 |
+ ) |
|
2509 | 2533 |
def test_221_edit_notes_noop( |
2510 | 2534 |
self, |
2535 |
+ edit_func_name: Literal['empty', 'space'], |
|
2536 |
+ notes: str, |
|
2511 | 2537 |
) -> None: |
2512 | 2538 |
"""Abandoning edited notes works.""" |
2539 |
+ |
|
2540 |
+ def empty(text: str, *_args: Any, **_kwargs: Any) -> None: |
|
2541 |
+ del text |
|
2542 |
+ |
|
2543 |
+ def space(text: str, *_args: Any, **_kwargs: Any) -> str: |
|
2544 |
+ del text |
|
2545 |
+ return ' ' + notes + '\n\n\n\n\n\n' |
|
2546 |
+ |
|
2547 |
+ edit_funcs = {'empty': empty, 'space': space} |
|
2513 | 2548 |
runner = click.testing.CliRunner(mix_stderr=False) |
2514 | 2549 |
# TODO(the-13th-letter): Rewrite using parenthesized |
2515 | 2550 |
# with-statements. |
... | ... |
@@ -2522,15 +2557,12 @@ insert witty notes here |
2522 | 2557 |
runner=runner, |
2523 | 2558 |
vault_config={ |
2524 | 2559 |
'global': {'phrase': 'abc'}, |
2525 |
- 'services': {'sv': {'notes': 'Contents go here'}}, |
|
2560 |
+ 'services': {'sv': {'notes': notes}}, |
|
2526 | 2561 |
}, |
2527 | 2562 |
) |
2528 | 2563 |
) |
2529 | 2564 |
|
2530 |
- def space(text: str, *_args: Any, **_kwargs: Any) -> str: |
|
2531 |
- return ' ' + text + '\n\n\n\n\n\n' |
|
2532 |
- |
|
2533 |
- monkeypatch.setattr(click, 'edit', space) |
|
2565 |
+ monkeypatch.setattr(click, 'edit', edit_funcs[edit_func_name]) |
|
2534 | 2566 |
result_ = runner.invoke( |
2535 | 2567 |
cli.derivepassphrase_vault, |
2536 | 2568 |
['--config', '--notes', '--', 'sv'], |
... | ... |
@@ -2544,19 +2576,33 @@ insert witty notes here |
2544 | 2576 |
config = json.load(infile) |
2545 | 2577 |
assert config == { |
2546 | 2578 |
'global': {'phrase': 'abc'}, |
2547 |
- 'services': {'sv': {'notes': 'Contents go here'}}, |
|
2579 |
+ 'services': {'sv': {'notes': notes}}, |
|
2548 | 2580 |
} |
2549 | 2581 |
|
2550 | 2582 |
# TODO(the-13th-letter): Keep this behavior or not, with or without |
2551 | 2583 |
# warning? |
2584 |
+ @hypothesis.given( |
|
2585 |
+ notes=strategies.text( |
|
2586 |
+ strategies.characters( |
|
2587 |
+ min_codepoint=32, max_codepoint=126, include_characters='\n' |
|
2588 |
+ ), |
|
2589 |
+ min_size=1, |
|
2590 |
+ max_size=512, |
|
2591 |
+ ).filter(str.strip), |
|
2592 |
+ ) |
|
2552 | 2593 |
def test_222_edit_notes_marker_removed( |
2553 | 2594 |
self, |
2595 |
+ notes: str, |
|
2554 | 2596 |
) -> None: |
2555 | 2597 |
"""Removing the notes marker still saves the notes. |
2556 | 2598 |
|
2557 | 2599 |
TODO: Keep this behavior or not, with or without warning? |
2558 | 2600 |
|
2559 | 2601 |
""" |
2602 |
+ notes_marker = cli_messages.TranslatedString( |
|
2603 |
+ cli_messages.Label.DERIVEPASSPHRASE_VAULT_NOTES_MARKER |
|
2604 |
+ ) |
|
2605 |
+ hypothesis.assume(str(notes_marker) not in notes.strip()) |
|
2560 | 2606 |
runner = click.testing.CliRunner(mix_stderr=False) |
2561 | 2607 |
# TODO(the-13th-letter): Rewrite using parenthesized |
2562 | 2608 |
# with-statements. |
... | ... |
@@ -2573,7 +2619,7 @@ insert witty notes here |
2573 | 2619 |
}, |
2574 | 2620 |
) |
2575 | 2621 |
) |
2576 |
- monkeypatch.setattr(click, 'edit', lambda *_a, **_kw: 'long\ntext') |
|
2622 |
+ monkeypatch.setattr(click, 'edit', lambda *_a, **_kw: notes) |
|
2577 | 2623 |
result_ = runner.invoke( |
2578 | 2624 |
cli.derivepassphrase_vault, |
2579 | 2625 |
['--config', '--notes', '--', 'sv'], |
... | ... |
@@ -2587,11 +2633,21 @@ insert witty notes here |
2587 | 2633 |
config = json.load(infile) |
2588 | 2634 |
assert config == { |
2589 | 2635 |
'global': {'phrase': 'abc'}, |
2590 |
- 'services': {'sv': {'notes': 'long\ntext'}}, |
|
2636 |
+ 'services': {'sv': {'notes': notes.strip()}}, |
|
2591 | 2637 |
} |
2592 | 2638 |
|
2639 |
+ @hypothesis.given( |
|
2640 |
+ notes=strategies.text( |
|
2641 |
+ strategies.characters( |
|
2642 |
+ min_codepoint=32, max_codepoint=126, include_characters='\n' |
|
2643 |
+ ), |
|
2644 |
+ min_size=1, |
|
2645 |
+ max_size=512, |
|
2646 |
+ ).filter(str.strip), |
|
2647 |
+ ) |
|
2593 | 2648 |
def test_223_edit_notes_abort( |
2594 | 2649 |
self, |
2650 |
+ notes: str, |
|
2595 | 2651 |
) -> None: |
2596 | 2652 |
"""Aborting editing notes works.""" |
2597 | 2653 |
runner = click.testing.CliRunner(mix_stderr=False) |
... | ... |
@@ -2606,7 +2662,7 @@ insert witty notes here |
2606 | 2662 |
runner=runner, |
2607 | 2663 |
vault_config={ |
2608 | 2664 |
'global': {'phrase': 'abc'}, |
2609 |
- 'services': {'sv': {'notes': 'Contents go here'}}, |
|
2665 |
+ 'services': {'sv': {'notes': notes.strip()}}, |
|
2610 | 2666 |
}, |
2611 | 2667 |
) |
2612 | 2668 |
) |
... | ... |
@@ -2626,7 +2682,46 @@ insert witty notes here |
2626 | 2682 |
config = json.load(infile) |
2627 | 2683 |
assert config == { |
2628 | 2684 |
'global': {'phrase': 'abc'}, |
2629 |
- 'services': {'sv': {'notes': 'Contents go here'}}, |
|
2685 |
+ 'services': {'sv': {'notes': notes.strip()}}, |
|
2686 |
+ } |
|
2687 |
+ |
|
2688 |
+ def test_223a_edit_empty_notes_abort( |
|
2689 |
+ self, |
|
2690 |
+ ) -> None: |
|
2691 |
+ """Aborting editing notes works even if no notes are stored yet.""" |
|
2692 |
+ runner = click.testing.CliRunner(mix_stderr=False) |
|
2693 |
+ # TODO(the-13th-letter): Rewrite using parenthesized |
|
2694 |
+ # with-statements. |
|
2695 |
+ # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9 |
|
2696 |
+ with contextlib.ExitStack() as stack: |
|
2697 |
+ monkeypatch = stack.enter_context(pytest.MonkeyPatch.context()) |
|
2698 |
+ stack.enter_context( |
|
2699 |
+ tests.isolated_vault_config( |
|
2700 |
+ monkeypatch=monkeypatch, |
|
2701 |
+ runner=runner, |
|
2702 |
+ vault_config={ |
|
2703 |
+ 'global': {'phrase': 'abc'}, |
|
2704 |
+ 'services': {}, |
|
2705 |
+ }, |
|
2706 |
+ ) |
|
2707 |
+ ) |
|
2708 |
+ monkeypatch.setattr(click, 'edit', lambda *_a, **_kw: '') |
|
2709 |
+ result_ = runner.invoke( |
|
2710 |
+ cli.derivepassphrase_vault, |
|
2711 |
+ ['--config', '--notes', '--', 'sv'], |
|
2712 |
+ catch_exceptions=False, |
|
2713 |
+ ) |
|
2714 |
+ result = tests.ReadableResult.parse(result_) |
|
2715 |
+ assert result.error_exit(error='the user aborted the request'), ( |
|
2716 |
+ 'expected known error message' |
|
2717 |
+ ) |
|
2718 |
+ with cli_helpers.config_filename(subsystem='vault').open( |
|
2719 |
+ encoding='UTF-8' |
|
2720 |
+ ) as infile: |
|
2721 |
+ config = json.load(infile) |
|
2722 |
+ assert config == { |
|
2723 |
+ 'global': {'phrase': 'abc'}, |
|
2724 |
+ 'services': {}, |
|
2630 | 2725 |
} |
2631 | 2726 |
|
2632 | 2727 |
@Parametrize.CONFIG_EDITING_VIA_CONFIG_FLAG |
2633 | 2728 |