Implement datetime handling in pytest-bdd

- This was awful and convoluted

Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
Jonathan Wren 2021-05-01 15:57:16 -07:00
parent cda07bf8d9
commit 4aabb73847
16 changed files with 133 additions and 87 deletions

17
tests/unit/test_color.py Normal file
View file

@ -0,0 +1,17 @@
import pytest
from jrnl.color import colorize
from colorama import Fore, Style
@pytest.fixture()
def data_fixture():
string = "Zwei peanuts walked into a bar"
yield string
def test_colorize(data_fixture):
string = data_fixture
colorized_string = colorize(string, "BLUE", True)
assert colorized_string == Style.BRIGHT + Fore.BLUE + string + Style.RESET_ALL

View file

@ -0,0 +1,23 @@
import argparse
import jrnl
import pytest
from unittest import mock
from jrnl.jrnl import _display_search_results
# fmt: off
# see: https://github.com/psf/black/issues/664
@pytest.mark.parametrize("export_format", [ "pretty", "short","markdown"])
#fmt: on
@mock.patch.object(argparse, "Namespace", return_value={"export": "markdown", "filename": "irrele.vant"})
def test_export_format(mock_args, export_format):
test_journal = jrnl.Journal.Journal
mock_args.export = export_format
#fmt: off
# see: https://github.com/psf/black/issues/664
with mock.patch("builtins.print") as mock_spy_print, \
mock.patch('jrnl.Journal.Journal.pprint') as mock_pprint:
_display_search_results(mock_args, test_journal)
mock_spy_print.assert_called_once_with(mock_pprint())
#fmt: on

View file

@ -0,0 +1,19 @@
import textwrap
from jrnl.exception import JrnlError
def test_config_directory_exception_message():
ex = JrnlError(
"ConfigDirectoryIsFile", config_directory_path="/config/directory/path"
)
assert ex.message == textwrap.dedent(
"""
The path to your jrnl configuration directory is a file, not a directory:
/config/directory/path
Removing this file will allow jrnl to save its configuration.
"""
)

28
tests/unit/test_export.py Normal file
View file

@ -0,0 +1,28 @@
from jrnl.exception import JrnlError
from jrnl.plugins.fancy_exporter import check_provided_linewrap_viability
import pytest
@pytest.fixture()
def datestr():
yield "2020-10-20 16:59"
def build_card_header(datestr):
top_left_corner = "┎─╮"
content = top_left_corner + datestr
return content
class TestFancy:
def test_too_small_linewrap(self, datestr):
journal = "test_journal"
content = build_card_header(datestr)
total_linewrap = 12
with pytest.raises(JrnlError) as e:
check_provided_linewrap_viability(total_linewrap, [content], journal)
assert e.value.error_type == "LineWrapTooSmallForDateFormat"

View file

@ -0,0 +1,13 @@
from unittest import mock
import pytest
import sys
@pytest.mark.filterwarnings(
"ignore:.*imp module is deprecated.*"
) # ansiwrap spits out an unrelated warning
def test_initialize_autocomplete_runs_without_readline():
from jrnl import install
with mock.patch.dict(sys.modules, {"readline": None}):
install._initialize_autocomplete() # should not throw exception

View file

@ -0,0 +1,87 @@
from unittest import mock
import pytest
from jrnl.os_compat import on_windows
from jrnl.os_compat import on_posix
from jrnl.os_compat import split_args
@pytest.mark.parametrize(
"systems",
[
["linux", False],
["win32", True],
["cygwin", False],
["msys", False],
["darwin", False],
["os2", False],
["os2emx", False],
["riscos", False],
["atheos", False],
["freebsd7", False],
["freebsd8", False],
["freebsdN", False],
["openbsd6", False],
],
)
def test_on_windows(systems):
osname, expected_on_windows = systems[0], systems[1]
with mock.patch("jrnl.os_compat.platform", osname):
assert on_windows() == expected_on_windows
@pytest.mark.parametrize(
"systems",
[
["linux", True],
["win32", False],
["cygwin", True],
["msys", True],
["darwin", True],
["os2", True],
["os2emx", True],
["riscos", True],
["atheos", True],
["freebsd7", True],
["freebsd8", True],
["freebsdN", True],
["openbsd6", True],
],
)
def test_on_posix(systems):
osname, expected_on_posix = systems[0], systems[1]
with mock.patch("jrnl.os_compat.platform", osname):
assert on_posix() == expected_on_posix
@pytest.mark.parametrize(
"args",
[
["notepad", ["notepad"]],
["subl -w", ["subl", "-w"]],
[
'"C:\\Program Files\\Sublime Text 3\\subl.exe" -w',
['"C:\\Program Files\\Sublime Text 3\\subl.exe"', "-w"],
],
],
)
def test_split_args_on_windows(args):
input_arguments, expected_split_args = args[0], args[1]
with mock.patch("jrnl.os_compat.on_windows", lambda: True):
assert split_args(input_arguments) == expected_split_args
@pytest.mark.parametrize(
"args",
[
["vim", ["vim"]],
[
'vim -f +Goyo +Limelight "+set spell linebreak"',
["vim", "-f", "+Goyo", "+Limelight", '"+set spell linebreak"'],
],
],
)
def test_split_args_on_not_windows(args):
input_arguments, expected_split_args = args[0], args[1]
with mock.patch("jrnl.os_compat.on_windows", lambda: True):
assert split_args(input_arguments) == expected_split_args

View file

@ -0,0 +1,79 @@
import pytest
from jrnl.override import (
apply_overrides,
_recursively_apply,
_get_config_node,
_get_key_and_value_from_pair,
_convert_dots_to_list,
)
@pytest.fixture()
def minimal_config():
cfg = {
"colors": {"body": "red", "date": "green"},
"default": "/tmp/journal.jrnl",
"editor": "vim",
"journals": {"default": "/tmp/journals/journal.jrnl"},
}
return cfg
def test_apply_override(minimal_config):
overrides = [["editor", "nano"]]
apply_overrides(overrides, minimal_config)
assert minimal_config["editor"] == "nano"
def test_override_dot_notation(minimal_config):
overrides = [["colors.body", "blue"]]
cfg = apply_overrides(overrides=overrides, base_config=minimal_config)
assert cfg["colors"] == {"body": "blue", "date": "green"}
def test_multiple_overrides(minimal_config):
overrides = [
["colors.title", "magenta"],
["editor", "nano"],
["journals.burner", "/tmp/journals/burner.jrnl"],
] # as returned by parse_args, saved in parser.config_override
cfg = apply_overrides(overrides, minimal_config)
assert cfg["editor"] == "nano"
assert cfg["colors"]["title"] == "magenta"
assert "burner" in cfg["journals"]
assert cfg["journals"]["burner"] == "/tmp/journals/burner.jrnl"
def test_recursively_apply():
cfg = {"colors": {"body": "red", "title": "green"}}
cfg = _recursively_apply(cfg, ["colors", "body"], "blue")
assert cfg["colors"]["body"] == "blue"
def test_get_config_node(minimal_config):
assert len(minimal_config.keys()) == 4
assert _get_config_node(minimal_config, "editor") == "vim"
assert _get_config_node(minimal_config, "display_format") == None
def test_get_kv_from_pair():
pair = {"ab.cde": "fgh"}
k, v = _get_key_and_value_from_pair(pair)
assert k == "ab.cde"
assert v == "fgh"
class TestDotNotationToList:
def test_unpack_dots_to_list(self):
keys = "a.b.c.d.e.f"
keys_list = _convert_dots_to_list(keys)
assert len(keys_list) == 6
def test_sequential_delimiters(self):
k = "g.r..h.v"
k_l = _convert_dots_to_list(k)
assert len(k_l) == 4

View file

@ -0,0 +1,292 @@
import shlex
import pytest
from jrnl.args import parse_args
from jrnl.config import make_yaml_valid_dict
def cli_as_dict(str):
cli = shlex.split(str)
args = parse_args(cli)
return vars(args)
def expected_args(**kwargs):
default_args = {
"contains": None,
"debug": False,
"delete": False,
"edit": False,
"end_date": None,
"today_in_history": False,
"month": None,
"day": None,
"year": None,
"excluded": [],
"export": False,
"filename": None,
"limit": None,
"on_date": None,
"preconfig_cmd": None,
"postconfig_cmd": None,
"short": False,
"starred": False,
"start_date": None,
"strict": False,
"tags": False,
"text": [],
"config_override": [],
}
return {**default_args, **kwargs}
def test_empty():
assert cli_as_dict("") == expected_args()
def test_contains_alone():
assert cli_as_dict("-contains whatever") == expected_args(contains="whatever")
def test_debug_alone():
assert cli_as_dict("--debug") == expected_args(debug=True)
def test_delete_alone():
assert cli_as_dict("--delete") == expected_args(delete=True)
def test_diagnostic_alone():
from jrnl.commands import preconfig_diagnostic
assert cli_as_dict("--diagnostic") == expected_args(
preconfig_cmd=preconfig_diagnostic
)
def test_edit_alone():
assert cli_as_dict("--edit") == expected_args(edit=True)
def test_encrypt_alone():
from jrnl.commands import postconfig_encrypt
assert cli_as_dict("--encrypt") == expected_args(postconfig_cmd=postconfig_encrypt)
def test_decrypt_alone():
from jrnl.commands import postconfig_decrypt
assert cli_as_dict("--decrypt") == expected_args(postconfig_cmd=postconfig_decrypt)
def test_end_date_alone():
expected = expected_args(end_date="2020-01-01")
assert expected == cli_as_dict("-until 2020-01-01")
assert expected == cli_as_dict("-to 2020-01-01")
def test_not_alone():
assert cli_as_dict("-not test") == expected_args(excluded=["test"])
def test_not_multiple_alone():
assert cli_as_dict("-not one -not two") == expected_args(excluded=["one", "two"])
assert cli_as_dict("-not one -not two -not three") == expected_args(
excluded=["one", "two", "three"]
)
@pytest.mark.parametrize(
"cli",
[
"two -not one -not three",
"-not one two -not three",
"-not one -not three two",
],
)
def test_not_mixed(cli):
result = expected_args(excluded=["one", "three"], text=["two"])
assert cli_as_dict(cli) == result
def test_not_interspersed():
result = expected_args(excluded=["one", "three"], text=["two", "two", "two"])
assert cli_as_dict("two -not one two -not three two") == result
def test_export_alone():
assert cli_as_dict("--export json") == expected_args(export="json")
def test_import_alone():
from jrnl.commands import postconfig_import
assert cli_as_dict("--import") == expected_args(postconfig_cmd=postconfig_import)
def test_file_flag_alone():
assert cli_as_dict("--file test.txt") == expected_args(filename="test.txt")
assert cli_as_dict("--file 'lorem ipsum.txt'") == expected_args(
filename="lorem ipsum.txt"
)
def test_limit_alone():
assert cli_as_dict("-n 5") == expected_args(limit=5)
assert cli_as_dict("-n 999") == expected_args(limit=999)
def test_limit_shorthand_alone():
assert cli_as_dict("-5") == expected_args(limit=5)
assert cli_as_dict("-999") == expected_args(limit=999)
def test_list_alone():
from jrnl.commands import postconfig_list
assert cli_as_dict("--ls") == expected_args(postconfig_cmd=postconfig_list)
def test_on_date_alone():
assert cli_as_dict("-on 'saturday'") == expected_args(on_date="saturday")
def test_month_alone():
assert cli_as_dict("-month 1") == expected_args(month="1")
assert cli_as_dict("-month 01") == expected_args(month="01")
assert cli_as_dict("-month January") == expected_args(month="January")
assert cli_as_dict("-month Jan") == expected_args(month="Jan")
def test_day_alone():
assert cli_as_dict("-day 1") == expected_args(day="1")
assert cli_as_dict("-day 01") == expected_args(day="01")
def test_year_alone():
assert cli_as_dict("-year 2021") == expected_args(year="2021")
assert cli_as_dict("-year 21") == expected_args(year="21")
def test_today_in_history_alone():
assert cli_as_dict("-today-in-history") == expected_args(today_in_history=True)
def test_short_alone():
assert cli_as_dict("--short") == expected_args(short=True)
def test_starred_alone():
assert cli_as_dict("-starred") == expected_args(starred=True)
def test_start_date_alone():
assert cli_as_dict("-from 2020-01-01") == expected_args(start_date="2020-01-01")
assert cli_as_dict("-from 'January 1st'") == expected_args(start_date="January 1st")
def test_and_alone():
assert cli_as_dict("-and") == expected_args(strict=True)
def test_tags_alone():
assert cli_as_dict("--tags") == expected_args(tags=True)
def test_text_alone():
assert cli_as_dict("lorem ipsum dolor sit amet") == expected_args(
text=["lorem", "ipsum", "dolor", "sit", "amet"]
)
def test_version_alone():
from jrnl.commands import preconfig_version
assert cli_as_dict("--version") == expected_args(preconfig_cmd=preconfig_version)
def test_editor_override():
parsed_args = cli_as_dict('--config-override editor "nano"')
assert parsed_args == expected_args(config_override=[["editor", "nano"]])
def test_color_override():
assert cli_as_dict("--config-override colors.body blue") == expected_args(
config_override=[["colors.body", "blue"]]
)
def test_multiple_overrides():
parsed_args = cli_as_dict(
'--config-override colors.title green --config-override editor "nano" --config-override journal.scratchpad "/tmp/scratchpad"'
)
assert parsed_args == expected_args(
config_override=[
["colors.title", "green"],
["editor", "nano"],
["journal.scratchpad", "/tmp/scratchpad"],
]
)
# @see https://github.com/jrnl-org/jrnl/issues/520
@pytest.mark.parametrize(
"cli",
[
"-and second @oldtag @newtag",
"second @oldtag @newtag -and",
"second -and @oldtag @newtag",
"second @oldtag -and @newtag",
],
)
def test_and_ordering(cli):
result = expected_args(strict=True, text=["second", "@oldtag", "@newtag"])
assert cli_as_dict(cli) == result
# @see https://github.com/jrnl-org/jrnl/issues/520
@pytest.mark.parametrize(
"cli",
[
"--edit second @oldtag @newtag",
"second @oldtag @newtag --edit",
"second --edit @oldtag @newtag",
"second @oldtag --edit @newtag",
],
)
def test_edit_ordering(cli):
result = expected_args(edit=True, text=["second", "@oldtag", "@newtag"])
assert cli_as_dict(cli) == result
class TestDeserialization:
@pytest.mark.parametrize(
"input_str",
[
["editor", "nano"],
["colors.title", "blue"],
["default", "/tmp/egg.txt"],
],
)
def test_deserialize_multiword_strings(self, input_str):
runtime_config = make_yaml_valid_dict(input_str)
assert runtime_config.__class__ == dict
assert input_str[0] in runtime_config.keys()
assert runtime_config[input_str[0]] == input_str[1]
def test_deserialize_multiple_datatypes(self):
cfg = make_yaml_valid_dict(["linewrap", "23"])
assert cfg["linewrap"] == 23
cfg = make_yaml_valid_dict(["encrypt", "false"])
assert cfg["encrypt"] == False
cfg = make_yaml_valid_dict(["editor", "vi -c startinsert"])
assert cfg["editor"] == "vi -c startinsert"
cfg = make_yaml_valid_dict(["highlight", "true"])
assert cfg["highlight"] == True

22
tests/unit/test_time.py Normal file
View file

@ -0,0 +1,22 @@
import datetime
from jrnl import time
def test_default_hour_is_added():
assert time.parse(
"2020-06-20", inclusive=False, default_hour=9, default_minute=0, bracketed=False
) == datetime.datetime(2020, 6, 20, 9)
def test_default_minute_is_added():
assert (
time.parse(
"2020-06-20",
inclusive=False,
default_hour=0,
default_minute=30,
bracketed=False,
)
== datetime.datetime(2020, 6, 20, 0, 30)
)