Merge branch 'develop' into #1170-alternate-config-file

This commit is contained in:
Micah Jerome Ellison 2021-10-09 13:12:45 -07:00
commit 70aa5989ea
133 changed files with 706 additions and 4869 deletions

View file

@ -143,10 +143,15 @@ def user_input():
@fixture
def config_data(config_path):
def config_on_disk(config_path):
return load_config(config_path)
@fixture
def config_in_memory():
return dict()
@fixture
def journal_name():
return None

View file

@ -1,6 +1,7 @@
# Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html
import functools
import os
@ -38,3 +39,13 @@ def assert_equal_tags_ignoring_order(
[actual_tags, expected_tags],
[expected_content, actual_content],
]
# @see: https://stackoverflow.com/a/65782539/569146
def get_nested_val(dictionary, path, *default):
try:
return functools.reduce(lambda x, y: x[y], path.split("."), dictionary)
except KeyError:
if default:
return default[0]
raise

View file

@ -15,6 +15,7 @@ from jrnl.config import scope_config
from .helpers import assert_equal_tags_ignoring_order
from .helpers import does_directory_contain_files
from .helpers import parse_should_or_should_not
from .helpers import get_nested_val
@then("we should get no error")
@ -84,6 +85,14 @@ def output_should_contain_version(cli_run, toml_version):
assert toml_version in out, toml_version
@then(parse("the output should be {width:d} columns wide"))
def output_should_be_columns_wide(cli_run, width):
out = cli_run["stdout"]
out_lines = out.splitlines()
for line in out_lines:
assert len(line) <= width
@then(parse('we should see the message "{text}"'))
def should_see_the_message(text, cli_run):
out = cli_run["stderr"]
@ -102,17 +111,18 @@ def should_see_the_message(text, cli_run):
)
@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(config_data, journal_name, should_or_should_not, 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)
actual = config_data
actual = config_on_disk
if journal_name:
actual = actual["journals"][journal_name]
expected = yaml.load(some_yaml, Loader=yaml.FullLoader)
expected = yaml.load(some_yaml, Loader=yaml.SafeLoader)
actual_slice = actual
if type(actual) is dict:
# `expected` objects formatted in yaml only compare one level deep
actual_slice = {key: actual.get(key, None) for key in expected.keys()}
if we_should:
@ -121,6 +131,40 @@ def config_var(config_data, journal_name, should_or_should_not, some_yaml):
assert expected != actual_slice
@then(
parse(
'the config in memory for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"'
)
)
@then(
parse(
'the config in memory for journal "{journal_name}" {should_or_should_not} contain\n{some_yaml}'
)
)
@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)
actual = config_in_memory["overrides"]
if journal_name:
actual = actual["journals"][journal_name]
expected = yaml.load(some_yaml, Loader=yaml.SafeLoader)
actual_slice = actual
if type(actual) is dict:
# `expected` objects formatted in yaml only compare one level deep
actual_slice = {key: get_nested_val(actual, key) for key in expected.keys()}
if we_should:
assert expected == actual_slice
else:
assert expected != actual_slice
@then("we should be prompted for a password")
def password_was_called(cli_run):
assert cli_run["mocks"]["getpass"].called
@ -137,15 +181,15 @@ def assert_dir_contains_files(file_list, cache_dir):
@then(parse("the journal directory should contain\n{file_list}"))
def journal_directory_should_contain(config_data, file_list):
scoped_config = scope_config(config_data, "default")
def journal_directory_should_contain(config_on_disk, file_list):
scoped_config = scope_config(config_on_disk, "default")
assert does_directory_contain_files(file_list, scoped_config["journal"])
@then(parse('journal "{journal_name}" should not exist'))
def journal_directory_should_not_exist(config_data, journal_name):
scoped_config = scope_config(config_data, journal_name)
def journal_directory_should_not_exist(config_on_disk, journal_name):
scoped_config = scope_config(config_on_disk, journal_name)
assert not does_directory_contain_files(
scoped_config["journal"], "."
@ -153,8 +197,8 @@ def journal_directory_should_not_exist(config_data, journal_name):
@then(parse("the journal {should_or_should_not} exist"))
def journal_should_not_exist(config_data, should_or_should_not):
scoped_config = scope_config(config_data, "default")
def journal_should_not_exist(config_on_disk, should_or_should_not):
scoped_config = scope_config(config_on_disk, "default")
expected_path = scoped_config["journal"]
contains_files = does_directory_contain_files(expected_path, ".")
@ -301,15 +345,34 @@ def count_elements(number, item, cli_run):
assert len(xml_tree.findall(".//" + item)) == number
@then(parse("the editor should have been called"))
@then(parse("the editor should have been called with {num_args} arguments"))
def count_editor_args(num_args, cli_run, editor_state):
assert cli_run["mocks"]["editor"].called
@then(parse("the editor {should_or_should_not} have been called"))
@then(
parse(
"the editor {should_or_should_not} have been called with {num_args} arguments"
)
)
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)
if we_should:
assert cli_run["mocks"]["editor"].called
else:
assert not cli_run["mocks"]["editor"].called
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)
if we_should:
assert cli_run["mocks"]["stdin"].called
else:
assert not cli_run["mocks"]["stdin"].called
@then(parse('the editor filename should end with "{suffix}"'))
def editor_filename_suffix(suffix, editor_state):
editor_filename = editor_state["tmpfile"]["name"]

View file

@ -34,6 +34,7 @@ def when_we_change_directory(directory_name):
def we_run(
command,
config_path,
config_in_memory,
user_input,
cli_run,
capsys,
@ -63,7 +64,19 @@ def we_run(
password = user_input
with ExitStack() as stack:
# Always mock
from jrnl.override import apply_overrides
def my_overrides(*args, **kwargs):
result = apply_overrides(*args, **kwargs)
config_in_memory["overrides"] = result
return result
stack.enter_context(
patch("jrnl.jrnl.apply_overrides", side_effect=my_overrides)
)
# Conditionally mock
stack.enter_context(patch("sys.argv", ["jrnl"] + args))
mock_stdin = stack.enter_context(