From 1a67fd5decb74414a47a4cb375d3bfaa4561f2aa Mon Sep 17 00:00:00 2001 From: Micah Jerome Ellison Date: Sat, 4 Mar 2023 12:37:06 -0800 Subject: [PATCH] Use pytest-bdd 6 (#1685) * update pytest-bdd to 6.0 * update lock file * fix first test (inject command fixture to request) * fix some more tests * fix cli_run fixture * fix password fixture * Remove unused import * Fix greedy should_or_should_not parsing problems while also consolidating its parse/transformation-to-bool code * Prevent greedy matching in "we run" by using regular expression lookahead * Add missing "Outline" in scenario outlines with examples * Split "we use the config" and "we use no config" so pytest won't try to consume config_file as a fixture * Fix missing ShouldOrShouldNot * Formatting * fix get_fixture function * change output of failing test to be a little more useful * update lock file * update type builder to for should/should not to be in it's own file, rename some vars for readability * add parse-type new dev/testing dependency * update lock file --------- Co-authored-by: Jonathan Wren --- jrnl/journals/Journal.py | 4 +- poetry.lock | 50 +++++------ pyproject.toml | 6 +- tests/bdd/features/change_time.feature | 9 +- tests/bdd/features/search.feature | 6 +- tests/lib/fixtures.py | 16 +++- tests/lib/given_steps.py | 17 ++-- tests/lib/helpers.py | 19 +---- tests/lib/then_steps.py | 113 ++++++++++++------------- tests/lib/type_builders.py | 11 +++ tests/lib/when_steps.py | 12 ++- 11 files changed, 136 insertions(+), 127 deletions(-) create mode 100644 tests/lib/type_builders.py diff --git a/jrnl/journals/Journal.py b/jrnl/journals/Journal.py index 4b99565a..ab5ec4de 100644 --- a/jrnl/journals/Journal.py +++ b/jrnl/journals/Journal.py @@ -263,7 +263,9 @@ class Journal: start_date = time.parse(start_date) # If strict mode is on, all tags have to be present in entry - has_tags = self.search_tags.issubset if strict else self.search_tags.intersection + has_tags = ( + self.search_tags.issubset if strict else self.search_tags.intersection + ) def excluded(tags): return 0 < len([tag for tag in tags if tag in excluded_tags]) diff --git a/poetry.lock b/poetry.lock index 871b3c80..e10bd254 100644 --- a/poetry.lock +++ b/poetry.lock @@ -345,14 +345,6 @@ python-dateutil = ">=2.8.1" [package.extras] dev = ["flake8", "markdown", "twine", "wheel"] -[[package]] -name = "glob2" -version = "0.7" -description = "Version of the glob module that can capture patterns and supports recursive wildcards" -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "idna" version = "3.4" @@ -819,14 +811,6 @@ python-versions = "*" [package.extras] tests = ["pytest"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - [[package]] name = "pycodestyle" version = "2.8.0" @@ -900,19 +884,18 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. [[package]] name = "pytest-bdd" -version = "5.0.0" +version = "6.1.1" description = "BDD for pytest" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7,<4.0" [package.dependencies] -glob2 = "*" Mako = "*" parse = "*" parse-type = "*" -py = "*" -pytest = ">=4.3" +pytest = ">=6.2.0" +typing-extensions = "*" [[package]] name = "pytest-clarity" @@ -1153,6 +1136,14 @@ python-versions = ">=3.7" docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "dev" +optional = false +python-versions = ">=3.7" + [[package]] name = "tzdata" version = "2022.7" @@ -1249,7 +1240,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = ">=3.10.0, <3.13" -content-hash = "ef292b09387c666923e871b66f975c2d44f646ae478dbaf62e295fbb84d7aca1" +content-hash = "dfc32ee61025dae6033987a8ff8290d4c2a34197502b8030cef02db58b86baf1" [metadata.files] ansiwrap = [ @@ -1564,9 +1555,6 @@ ghp-import = [ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, ] -glob2 = [ - {file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"}, -] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, @@ -1766,10 +1754,6 @@ pure-eval = [ {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, ] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] pycodestyle = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, @@ -1795,8 +1779,8 @@ pytest = [ {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"}, ] pytest-bdd = [ - {file = "pytest-bdd-5.0.0.tar.gz", hash = "sha256:fab7093ed3d5e51ee0c68de093c90e4f40de345bd9a54a188b2991ce2a2a39cf"}, - {file = "pytest_bdd-5.0.0-py3-none-any.whl", hash = "sha256:c7cf12209606421f61f36b5dc63beccd0c82d29446c0592cf68af2dad0a9761d"}, + {file = "pytest_bdd-6.1.1-py3-none-any.whl", hash = "sha256:57eba5878d77036f356a85fb1d108cb061d8af4fb4d032b1a424fa9abe9e498b"}, + {file = "pytest_bdd-6.1.1.tar.gz", hash = "sha256:138af3592bcce5d4684b0d690777cf199b39ce45d423ca28086047ffe6111010"}, ] pytest-clarity = [ {file = "pytest-clarity-1.0.1.tar.gz", hash = "sha256:505fe345fad4fe11c6a4187fe683f2c7c52c077caa1e135f3e483fe112db7772"}, @@ -1947,6 +1931,10 @@ traitlets = [ {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, ] +typing-extensions = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] tzdata = [ {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"}, {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"}, diff --git a/pyproject.toml b/pyproject.toml index 6d21ef0a..2c4d0f23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,9 +52,10 @@ flake8-simplify = ">=0.19" ipdb = "*" isort = ">=5.10" mkdocs = ">=1.4" +parse-type = ">=0.6.0" poethepoet = "*" pytest = ">=6.2" -pytest-bdd = ">=4.0.1,<6.0" +pytest-bdd = ">=6.0" pytest-clarity = "*" pytest-xdist = ">=2.5.0" requests = "*" @@ -174,8 +175,9 @@ isolated_build = True [testenv] deps = pytest >= 6.2 - pytest-bdd >=4.0.1,<6.0 + pytest-bdd >=6.0 pytest-xdist >=2.5.0 + parse-type >=0.6.0 toml >=0.10 commands = pytest {posargs} diff --git a/tests/bdd/features/change_time.feature b/tests/bdd/features/change_time.feature index 603dfd44..2b1ca397 100644 --- a/tests/bdd/features/change_time.feature +++ b/tests/bdd/features/change_time.feature @@ -25,13 +25,16 @@ Feature: Change entry times in journal Scenario Outline: Change flag changes prompted entries Given we use the config "" And we use the password "test" if prompted - When we run "jrnl -1" - Then the output should contain "2020-09-24 09:14 The third entry finally" + When we run "jrnl --short" + Then the output should be + 2020-08-29 11:11 Entry the first. + 2020-08-31 14:32 A second entry in what I hope to be a long series. + 2020-09-24 09:14 The third entry finally after weeks without writing. When we run "jrnl --change-time '2022-04-23 10:30'" and enter Y N Y - When we run "jrnl -99 --short" + When we run "jrnl --short" Then the output should be 2020-08-31 14:32 A second entry in what I hope to be a long series. 2022-04-23 10:30 Entry the first. diff --git a/tests/bdd/features/search.feature b/tests/bdd/features/search.feature index 138c0285..531c2a3c 100644 --- a/tests/bdd/features/search.feature +++ b/tests/bdd/features/search.feature @@ -125,7 +125,7 @@ Feature: Searching in a journal | basic_dayone.yaml | - Scenario: Searching for unstarred entries + Scenario Outline: Searching for unstarred entries Given we use the config "" And we use the password "test" if prompted When we run "jrnl -not -starred" @@ -138,7 +138,7 @@ Feature: Searching in a journal | basic_folder.yaml | | basic_dayone.yaml | - Scenario: Searching for tagged entries + Scenario Outline: Searching for tagged entries Given we use the config "" And we use the password "test" if prompted When we run "jrnl -tagged" @@ -151,7 +151,7 @@ Feature: Searching in a journal | basic_folder.yaml | | basic_dayone.yaml | - Scenario: Searching for untagged entries + Scenario Outline: Searching for untagged entries Given we use the config "empty_folder.yaml" When we run "jrnl Tagged entry. This one has a @tag." Then we should get no error diff --git a/tests/lib/fixtures.py b/tests/lib/fixtures.py index 3f012e96..22c11d54 100644 --- a/tests/lib/fixtures.py +++ b/tests/lib/fixtures.py @@ -201,6 +201,16 @@ def input_method(): return "" +@fixture +def all_input(): + return "" + + +@fixture +def command(): + return "" + + @fixture def cache_dir(): return {"exists": False, "path": ""} @@ -221,13 +231,15 @@ def mock_user_input(request, password_input, stdin_input): def _mock_user_input(): # user_input needs to be here because we don't know it until cli_run starts user_input = get_fixture(request, "all_input", None) + if user_input is None: user_input = Exception("Unexpected call for user input") else: user_input = iter(user_input.splitlines()) def mock_console_input(**kwargs): - if kwargs["password"] and not isinstance(password_input, Exception): + pw = kwargs.get("password", False) + if pw and not isinstance(password_input, Exception): return password_input if isinstance(user_input, Iterable): @@ -236,7 +248,7 @@ def mock_user_input(request, password_input, stdin_input): return "" if input_line == r"\n" else input_line # exceptions - return user_input if not kwargs["password"] else password_input + return user_input if not pw else password_input mock_console = Mock(wraps=Console(stderr=True)) mock_console.input = Mock(side_effect=mock_console_input) diff --git a/tests/lib/given_steps.py b/tests/lib/given_steps.py index 808739fc..c5fd62a1 100644 --- a/tests/lib/given_steps.py +++ b/tests/lib/given_steps.py @@ -19,7 +19,6 @@ from jrnl.time import __get_pdt_calendar from tests.lib.fixtures import FailedKeyring from tests.lib.fixtures import NoKeyring from tests.lib.fixtures import TestKeyring -from tests.lib.helpers import get_fixture @given(parse("we {editor_method} to the editor if opened\n{editor_input}")) @@ -84,16 +83,16 @@ def we_have_type_of_keyring(keyring_type): return TestKeyring() -@given(parse('we use the config "{config_file}"'), target_fixture="config_path") @given(parse("we use no config"), target_fixture="config_path") -def we_use_the_config(request, temp_dir, working_dir): - config_file = get_fixture(request, "config_file") +def we_use_no_config(temp_dir): + os.chdir(temp_dir.name) # @todo move this step to a more universal place + return os.path.join(temp_dir.name, "non_existing_config.yaml") + +@given(parse('we use the config "{config_file}"'), target_fixture="config_path") +def we_use_the_config(request, temp_dir, working_dir, config_file): # Move into temp dir as cwd - os.chdir(temp_dir.name) - - if not config_file: - return os.path.join(temp_dir.name, "non_existing_config.yaml") + os.chdir(temp_dir.name) # @todo move this step to a more universal place # Copy the config file over config_source = os.path.join(working_dir, "data", "configs", config_file) @@ -133,7 +132,7 @@ def config_exists(config_file, temp_dir, working_dir): shutil.copy2(config_source, config_dest) -@given(parse('we use the password "{password}" if prompted')) +@given(parse('we use the password "{password}" if prompted'), target_fixture="password") def use_password_forever(password): return password diff --git a/tests/lib/helpers.py b/tests/lib/helpers.py index b50edd9f..a6ec5cb9 100644 --- a/tests/lib/helpers.py +++ b/tests/lib/helpers.py @@ -32,17 +32,6 @@ def does_directory_contain_n_files(directory_path, number): return int(number) == count -def parse_should_or_should_not(should_or_should_not): - if should_or_should_not == "should": - return True - elif should_or_should_not == "should not": - return False - else: - raise Exception( - "should_or_should_not valid values are 'should' or 'should not'" - ) - - def assert_equal_tags_ignoring_order( actual_line, expected_line, actual_content, expected_content ): @@ -81,7 +70,7 @@ def spy_wrapper(wrapped_function): def get_fixture(request, name, default=None): - result = default - if name in request.node.fixturenames: - result = request.getfixturevalue(name) - return result + try: + return request.getfixturevalue(name) + except LookupError: + return default diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index 5502787d..fd697dfb 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -15,7 +15,9 @@ from tests.lib.helpers import assert_equal_tags_ignoring_order from tests.lib.helpers import does_directory_contain_files from tests.lib.helpers import does_directory_contain_n_files from tests.lib.helpers import get_nested_val -from tests.lib.helpers import parse_should_or_should_not +from tests.lib.type_builders import should_choice + +SHOULD_DICT = {"Should": should_choice} @then("we should get no error") @@ -31,40 +33,38 @@ def output_should_match(regex, cli_run): assert matches, f"\nRegex didn't match:\n{regex}\n{str(out)}\n{str(matches)}" -@then(parse("the output {should_or_should_not} contain\n{expected_output}")) -@then(parse('the output {should_or_should_not} contain "{expected_output}"')) +@then(parse("the output {it_should:Should} contain\n{expected_output}", SHOULD_DICT)) +@then(parse('the output {it_should:Should} contain "{expected_output}"', SHOULD_DICT)) @then( parse( - "the {which_output_stream} output {should_or_should_not} contain\n{expected_output}" + "the {which_output_stream} output {it_should:Should} contain\n{expected_output}", + SHOULD_DICT, ) ) @then( parse( - 'the {which_output_stream} output {should_or_should_not} contain "{expected_output}"' + 'the {which_output_stream} output {it_should:Should} contain "{expected_output}"', + SHOULD_DICT, ) ) -def output_should_contain( - expected_output, which_output_stream, cli_run, should_or_should_not -): - we_should = parse_should_or_should_not(should_or_should_not) - +def output_should_contain(expected_output, which_output_stream, cli_run, it_should): output_str = f"\nEXPECTED:\n{expected_output}\n\nACTUAL STDOUT:\n{cli_run['stdout']}\n\nACTUAL STDERR:\n{cli_run['stderr']}" assert expected_output if which_output_stream is None: - assert ((expected_output in cli_run["stdout"]) == we_should) or ( - (expected_output in cli_run["stderr"]) == we_should + assert ((expected_output in cli_run["stdout"]) == it_should) or ( + (expected_output in cli_run["stderr"]) == it_should ), output_str elif which_output_stream == "standard": - assert (expected_output in cli_run["stdout"]) == we_should, output_str + assert (expected_output in cli_run["stdout"]) == it_should, output_str elif which_output_stream == "error": - assert (expected_output in cli_run["stderr"]) == we_should, output_str + assert (expected_output in cli_run["stderr"]) == it_should, output_str else: assert ( expected_output in cli_run[which_output_stream] - ) == we_should, output_str + ) == it_should, output_str @then(parse("the output should not contain\n{expected_output}")) @@ -78,7 +78,7 @@ def output_should_not_contain(expected_output, cli_run): def output_should_be(expected_output, cli_run): actual = cli_run["stdout"].strip() expected = expected_output.strip() - assert expected == actual + assert actual == expected @then("the output should be empty") @@ -130,19 +130,19 @@ def default_journal_location(journal_file, journal_dir, config_on_disk, temp_dir @then( parse( - 'the config for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"' + 'the config for journal "{journal_name}" {it_should:Should} contain "{some_yaml}"', + SHOULD_DICT, ) ) @then( parse( - 'the config for journal "{journal_name}" {should_or_should_not} contain\n{some_yaml}' + 'the config for journal "{journal_name}" {it_should:Should} contain\n{some_yaml}', + SHOULD_DICT, ) ) -@then(parse('the config {should_or_should_not} contain "{some_yaml}"')) -@then(parse("the config {should_or_should_not} contain\n{some_yaml}")) -def config_var_on_disk(config_on_disk, journal_name, should_or_should_not, some_yaml): - we_should = parse_should_or_should_not(should_or_should_not) - +@then(parse('the config {it_should:Should} contain "{some_yaml}"', SHOULD_DICT)) +@then(parse("the config {it_should:Should} contain\n{some_yaml}", SHOULD_DICT)) +def config_var_on_disk(config_on_disk, journal_name, it_should, some_yaml): actual = config_on_disk if journal_name: actual = actual["journals"][journal_name] @@ -154,26 +154,28 @@ def config_var_on_disk(config_on_disk, journal_name, should_or_should_not, some_ # `expected` objects formatted in yaml only compare one level deep actual_slice = {key: actual.get(key, None) for key in expected.keys()} - assert (expected == actual_slice) == we_should + assert (expected == actual_slice) == it_should @then( parse( - 'the config in memory for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"' + 'the config in memory for journal "{journal_name}" {it_should:Should} contain "{some_yaml}"', + SHOULD_DICT, ) ) @then( parse( - 'the config in memory for journal "{journal_name}" {should_or_should_not} contain\n{some_yaml}' + 'the config in memory for journal "{journal_name}" {it_should:Should} contain\n{some_yaml}', + SHOULD_DICT, ) ) -@then(parse('the config in memory {should_or_should_not} contain "{some_yaml}"')) -@then(parse("the config in memory {should_or_should_not} contain\n{some_yaml}")) -def config_var_in_memory( - config_in_memory, journal_name, should_or_should_not, some_yaml -): - we_should = parse_should_or_should_not(should_or_should_not) - +@then( + parse('the config in memory {it_should:Should} contain "{some_yaml}"', SHOULD_DICT) +) +@then( + parse("the config in memory {it_should:Should} contain\n{some_yaml}", SHOULD_DICT) +) +def config_var_in_memory(config_in_memory, journal_name, it_should, some_yaml): actual = config_in_memory["overrides"] if journal_name: actual = actual["journals"][journal_name] @@ -185,7 +187,7 @@ def config_var_in_memory( # `expected` objects formatted in yaml only compare one level deep actual_slice = {key: get_nested_val(actual, key) for key in expected.keys()} - assert (expected == actual_slice) == we_should + assert (expected == actual_slice) == it_should @then("we should be prompted for a password") @@ -224,31 +226,27 @@ def journal_directory_should_not_exist(config_on_disk, journal_name): ), f'Journal "{journal_name}" does exist' -@then(parse("the journal {should_or_should_not} exist")) -def journal_should_not_exist(config_on_disk, should_or_should_not): +@then(parse("the journal {it_should:Should} exist", SHOULD_DICT)) +def journal_should_not_exist(config_on_disk, it_should): scoped_config = scope_config(config_on_disk, "default") expected_path = scoped_config["journal"] contains_files = does_directory_contain_files(expected_path, ".") - if should_or_should_not == "should": - assert contains_files - elif should_or_should_not == "should not": - assert not contains_files - else: - raise Exception( - "should_or_should_not valid values are 'should' or 'should not'" - ) + assert contains_files == it_should -@then(parse('the journal "{journal_name}" directory {should_or_should_not} exist')) -def directory_should_not_exist(config_on_disk, should_or_should_not, journal_name): +@then( + parse( + 'the journal "{journal_name}" directory {it_should:Should} exist', SHOULD_DICT + ) +) +def directory_should_not_exist(config_on_disk, it_should, journal_name): scoped_config = scope_config(config_on_disk, journal_name) expected_path = scoped_config["journal"] - we_should = parse_should_or_should_not(should_or_should_not) dir_exists = os.path.isdir(expected_path) - assert dir_exists == we_should + assert dir_exists == it_should @then(parse('the content of file "{file_path}" in the cache should be\n{file_content}')) @@ -383,26 +381,23 @@ def count_elements(number, item, cli_run): assert len(xml_tree.findall(".//" + item)) == number -@then(parse("the editor {should_or_should_not} have been called")) +@then(parse("the editor {it_should:Should} have been called", SHOULD_DICT)) @then( parse( - "the editor {should_or_should_not} have been called with {num_args} arguments" + "the editor {it_should:Should} have been called with {num_args} arguments", + SHOULD_DICT, ) ) -def count_editor_args(num_args, cli_run, editor_state, should_or_should_not): - we_should = parse_should_or_should_not(should_or_should_not) - - assert cli_run["mocks"]["editor"].called == we_should +def count_editor_args(num_args, cli_run, editor_state, it_should): + assert cli_run["mocks"]["editor"].called == it_should if isinstance(num_args, int): assert len(editor_state["command"]) == int(num_args) -@then(parse("the stdin prompt {should_or_should_not} have been called")) -def stdin_prompt_called(cli_run, should_or_should_not): - we_should = parse_should_or_should_not(should_or_should_not) - - assert cli_run["mocks"]["stdin_input"].called == we_should +@then(parse("the stdin prompt {it_should:Should} have been called", SHOULD_DICT)) +def stdin_prompt_called(cli_run, it_should): + assert cli_run["mocks"]["stdin_input"].called == it_should @then(parse('the editor filename should end with "{suffix}"')) diff --git a/tests/lib/type_builders.py b/tests/lib/type_builders.py new file mode 100644 index 00000000..16171ef0 --- /dev/null +++ b/tests/lib/type_builders.py @@ -0,0 +1,11 @@ +# Copyright © 2012-2023 jrnl contributors +# License: https://www.gnu.org/licenses/gpl-3.0.html + +from parse_type import TypeBuilder + +should_choice = TypeBuilder.make_enum( + { + "should": True, + "should not": False, + } +) diff --git a/tests/lib/when_steps.py b/tests/lib/when_steps.py index 38ea4ab1..71252f86 100644 --- a/tests/lib/when_steps.py +++ b/tests/lib/when_steps.py @@ -7,6 +7,7 @@ from contextlib import ExitStack from pytest_bdd import when from pytest_bdd.parsers import parse from pytest_bdd.parsers import re +from pytest_bdd.steps import inject_fixture from jrnl.main import run @@ -29,13 +30,20 @@ all_input = '("(?P[^"]*)")' @when(parse('we run "jrnl {command}" and {input_method}\n{all_input}')) @when(re(f'we run "jrnl ?{command}" and {input_method} {all_input}')) -@when(parse('we run "jrnl {command}"')) +@when(re(f'we run "jrnl {command}"(?! and)')) @when('we run "jrnl"') -def we_run_jrnl(cli_run, capsys, keyring): +def we_run_jrnl(capsys, keyring, request, command, input_method, all_input): from keyring import set_keyring set_keyring(keyring) + # fixture injection (pytest-bdd >=6.0) + inject_fixture(request, "command", command) + inject_fixture(request, "input_method", input_method) + inject_fixture(request, "all_input", all_input) + + cli_run = request.getfixturevalue("cli_run") + with ExitStack() as stack: mocks = cli_run["mocks"] factories = cli_run["mock_factories"]