Implement editor-related steps in pytest-bdd

- Implement mock editor fixture
- Add fixture to keep track of editor state
- Implement various steps to check editor state

Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
Jonathan Wren 2021-04-24 14:47:52 -07:00
parent ce64d7973b
commit 3ddfb4d594
6 changed files with 475 additions and 133 deletions

View file

@ -26,7 +26,7 @@ def get_text_from_editor(config, template=""):
try: try:
subprocess.call(split_args(config["editor"]) + [tmpfile]) subprocess.call(split_args(config["editor"]) + [tmpfile])
except Exception as e: except FileNotFoundError as e:
error_msg = f""" error_msg = f"""
{ERROR_COLOR}{str(e)}{RESET_COLOR} {ERROR_COLOR}{str(e)}{RESET_COLOR}

287
poetry.lock generated
View file

@ -17,6 +17,14 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "appnope"
version = "0.1.2"
description = "Disable App Nap on macOS >= 10.9"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "argcomplete" name = "argcomplete"
version = "1.12.3" version = "1.12.3"
@ -61,6 +69,14 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
[[package]]
name = "backcall"
version = "0.2.0"
description = "Specifications for callback functions passed in to an API"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "behave" name = "behave"
version = "1.2.6" version = "1.2.6"
@ -152,6 +168,14 @@ sdist = ["setuptools-rust (>=0.11.4)"]
ssh = ["bcrypt (>=3.1.5)"] ssh = ["bcrypt (>=3.1.5)"]
test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"]
[[package]]
name = "decorator"
version = "5.0.9"
description = "Decorators for Humans"
category = "dev"
optional = false
python-versions = ">=3.5"
[[package]] [[package]]
name = "ghp-import" name = "ghp-import"
version = "2.0.1" version = "2.0.1"
@ -174,14 +198,6 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "icdiff"
version = "1.9.1"
description = "improved colored diff"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "4.5.0" version = "4.5.0"
@ -206,6 +222,74 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "ipdb"
version = "0.13.9"
description = "IPython-enabled pdb"
category = "dev"
optional = false
python-versions = ">=2.7"
[package.dependencies]
decorator = {version = "*", markers = "python_version > \"3.6\""}
ipython = {version = ">=7.17.0", markers = "python_version > \"3.6\""}
toml = {version = ">=0.10.2", markers = "python_version > \"3.6\""}
[[package]]
name = "ipython"
version = "7.24.1"
description = "IPython: Productive Interactive Computing"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
appnope = {version = "*", markers = "sys_platform == \"darwin\""}
backcall = "*"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
decorator = "*"
jedi = ">=0.16"
matplotlib-inline = "*"
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
pickleshare = "*"
prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0"
pygments = "*"
traitlets = ">=4.2"
[package.extras]
all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"]
doc = ["Sphinx (>=1.3)"]
kernel = ["ipykernel"]
nbconvert = ["nbconvert"]
nbformat = ["nbformat"]
notebook = ["notebook", "ipywidgets"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"]
[[package]]
name = "ipython-genutils"
version = "0.2.0"
description = "Vestigial utilities from IPython"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "jedi"
version = "0.18.0"
description = "An autocompletion tool for Python that can be used for text editors."
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
parso = ">=0.8.0,<0.9.0"
[package.extras]
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"]
[[package]] [[package]]
name = "jeepney" name = "jeepney"
version = "0.6.0" version = "0.6.0"
@ -286,6 +370,17 @@ category = "dev"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "matplotlib-inline"
version = "0.1.2"
description = "Inline Matplotlib backend for Jupyter"
category = "dev"
optional = false
python-versions = ">=3.5"
[package.dependencies]
traitlets = "*"
[[package]] [[package]]
name = "mergedeep" name = "mergedeep"
version = "1.3.4" version = "1.3.4"
@ -368,6 +463,18 @@ category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "parso"
version = "0.8.2"
description = "A Python Parser"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.extras]
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["docopt", "pytest (<6.0.0)"]
[[package]] [[package]]
name = "pathspec" name = "pathspec"
version = "0.8.1" version = "0.8.1"
@ -376,6 +483,25 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "pexpect"
version = "4.8.0"
description = "Pexpect allows easy control of interactive console applications."
category = "dev"
optional = false
python-versions = "*"
[package.dependencies]
ptyprocess = ">=0.5"
[[package]]
name = "pickleshare"
version = "0.7.5"
description = "Tiny 'shelve'-like database with concurrency support"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "pluggy" name = "pluggy"
version = "0.13.1" version = "0.13.1"
@ -391,9 +517,20 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
dev = ["pre-commit", "tox"] dev = ["pre-commit", "tox"]
[[package]] [[package]]
name = "pprintpp" name = "prompt-toolkit"
version = "0.4.0" version = "3.0.19"
description = "A drop-in replacement for pprint that's actually pretty" description = "Library for building powerful interactive command lines in Python"
category = "dev"
optional = false
python-versions = ">=3.6.1"
[package.dependencies]
wcwidth = "*"
[[package]]
name = "ptyprocess"
version = "0.7.0"
description = "Run a subprocess in a pseudo terminal"
category = "dev" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -422,6 +559,14 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pygments"
version = "2.9.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
python-versions = ">=3.5"
[[package]] [[package]]
name = "pyparsing" name = "pyparsing"
version = "2.4.7" version = "2.4.7"
@ -470,17 +615,16 @@ pytest = ">=4.3"
six = ">=1.9.0" six = ">=1.9.0"
[[package]] [[package]]
name = "pytest-icdiff" name = "pytest-clarity"
version = "0.5" version = "0.3.0a0"
description = "use icdiff for better error messages in pytest assertions" description = "A plugin providing an alternative, colourful diff output for failing assertions."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.dependencies] [package.dependencies]
icdiff = "*" pytest = ">=3.5.0"
pprintpp = "*" termcolor = "1.1.0"
pytest = "*"
[[package]] [[package]]
name = "python-dateutil" name = "python-dateutil"
@ -564,6 +708,14 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "termcolor"
version = "1.1.0"
description = "ANSII Color formatting for output in terminal."
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "textwrap3" name = "textwrap3"
version = "0.9.2" version = "0.9.2"
@ -580,6 +732,20 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "traitlets"
version = "5.0.5"
description = "Traitlets Python configuration system"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
ipython-genutils = "*"
[package.extras]
test = ["pytest"]
[[package]] [[package]]
name = "typed-ast" name = "typed-ast"
version = "1.4.3" version = "1.4.3"
@ -618,6 +784,14 @@ python-versions = ">=3.6"
[package.extras] [package.extras]
watchmedo = ["PyYAML (>=3.10)", "argh (>=0.24.1)"] watchmedo = ["PyYAML (>=3.10)", "argh (>=0.24.1)"]
[[package]]
name = "wcwidth"
version = "0.2.5"
description = "Measures the displayed width of unicode strings in a terminal"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "xmltodict" name = "xmltodict"
version = "0.12.0" version = "0.12.0"
@ -658,7 +832,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.7.0, <3.10" python-versions = ">=3.7.0, <3.10"
content-hash = "a0d3f3e30dbe80528547b49ae7bb39c6c1a911e2552d8b10d409daf81cdb28d1" content-hash = "d9a47064f2050860c955a0871b2bd8899c2f24aaf6482f6a742316fd1fd95ba3"
[metadata.files] [metadata.files]
ansiwrap = [ ansiwrap = [
@ -669,6 +843,10 @@ appdirs = [
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
] ]
appnope = [
{file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
{file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"},
]
argcomplete = [ argcomplete = [
{file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"},
{file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"},
@ -684,6 +862,10 @@ attrs = [
{file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
{file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
] ]
backcall = [
{file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
]
behave = [ behave = [
{file = "behave-1.2.6-py2.py3-none-any.whl", hash = "sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"}, {file = "behave-1.2.6-py2.py3-none-any.whl", hash = "sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"},
{file = "behave-1.2.6.tar.gz", hash = "sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86"}, {file = "behave-1.2.6.tar.gz", hash = "sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86"},
@ -753,15 +935,16 @@ cryptography = [
{file = "cryptography-3.4.7-pp37-pypy37_pp73-manylinux2014_x86_64.whl", hash = "sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9"}, {file = "cryptography-3.4.7-pp37-pypy37_pp73-manylinux2014_x86_64.whl", hash = "sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9"},
{file = "cryptography-3.4.7.tar.gz", hash = "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713"}, {file = "cryptography-3.4.7.tar.gz", hash = "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713"},
] ]
decorator = [
{file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"},
{file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"},
]
ghp-import = [ ghp-import = [
{file = "ghp-import-2.0.1.tar.gz", hash = "sha256:753de2eace6e0f7d4edfb3cce5e3c3b98cd52aadb80163303d1d036bda7b4483"}, {file = "ghp-import-2.0.1.tar.gz", hash = "sha256:753de2eace6e0f7d4edfb3cce5e3c3b98cd52aadb80163303d1d036bda7b4483"},
] ]
glob2 = [ glob2 = [
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"}, {file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
] ]
icdiff = [
{file = "icdiff-1.9.1.tar.gz", hash = "sha256:66972dd03318da55280991db375d3ef6b66d948c67af96c1ebdb21587e86655e"},
]
importlib-metadata = [ importlib-metadata = [
{file = "importlib_metadata-4.5.0-py3-none-any.whl", hash = "sha256:833b26fb89d5de469b24a390e9df088d4e52e4ba33b01dc5e0e4f41b81a16c00"}, {file = "importlib_metadata-4.5.0-py3-none-any.whl", hash = "sha256:833b26fb89d5de469b24a390e9df088d4e52e4ba33b01dc5e0e4f41b81a16c00"},
{file = "importlib_metadata-4.5.0.tar.gz", hash = "sha256:b142cc1dd1342f31ff04bb7d022492b09920cb64fed867cd3ea6f80fe3ebd139"}, {file = "importlib_metadata-4.5.0.tar.gz", hash = "sha256:b142cc1dd1342f31ff04bb7d022492b09920cb64fed867cd3ea6f80fe3ebd139"},
@ -770,6 +953,21 @@ iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
] ]
ipdb = [
{file = "ipdb-0.13.9.tar.gz", hash = "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"},
]
ipython = [
{file = "ipython-7.24.1-py3-none-any.whl", hash = "sha256:d513e93327cf8657d6467c81f1f894adc125334ffe0e4ddd1abbb1c78d828703"},
{file = "ipython-7.24.1.tar.gz", hash = "sha256:9bc24a99f5d19721fb8a2d1408908e9c0520a17fff2233ffe82620847f17f1b6"},
]
ipython-genutils = [
{file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"},
{file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"},
]
jedi = [
{file = "jedi-0.18.0-py2.py3-none-any.whl", hash = "sha256:18456d83f65f400ab0c2d3319e48520420ef43b23a086fdc05dff34132f0fb93"},
{file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"},
]
jeepney = [ jeepney = [
{file = "jeepney-0.6.0-py3-none-any.whl", hash = "sha256:aec56c0eb1691a841795111e184e13cad504f7703b9a64f63020816afa79a8ae"}, {file = "jeepney-0.6.0-py3-none-any.whl", hash = "sha256:aec56c0eb1691a841795111e184e13cad504f7703b9a64f63020816afa79a8ae"},
{file = "jeepney-0.6.0.tar.gz", hash = "sha256:7d59b6622675ca9e993a6bd38de845051d315f8b0c72cca3aef733a20b648657"}, {file = "jeepney-0.6.0.tar.gz", hash = "sha256:7d59b6622675ca9e993a6bd38de845051d315f8b0c72cca3aef733a20b648657"},
@ -825,6 +1023,10 @@ markupsafe = [
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
] ]
matplotlib-inline = [
{file = "matplotlib-inline-0.1.2.tar.gz", hash = "sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"},
{file = "matplotlib_inline-0.1.2-py3-none-any.whl", hash = "sha256:5cf1176f554abb4fa98cb362aa2b55c500147e4bdbb07e3fda359143e1da0811"},
]
mergedeep = [ mergedeep = [
{file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
@ -852,17 +1054,33 @@ parsedatetime = [
{file = "parsedatetime-2.6-py3-none-any.whl", hash = "sha256:cb96edd7016872f58479e35879294258c71437195760746faffedb692aef000b"}, {file = "parsedatetime-2.6-py3-none-any.whl", hash = "sha256:cb96edd7016872f58479e35879294258c71437195760746faffedb692aef000b"},
{file = "parsedatetime-2.6.tar.gz", hash = "sha256:4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455"}, {file = "parsedatetime-2.6.tar.gz", hash = "sha256:4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455"},
] ]
parso = [
{file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"},
{file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"},
]
pathspec = [ pathspec = [
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},
{file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"},
] ]
pexpect = [
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
{file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
]
pickleshare = [
{file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
]
pluggy = [ pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
] ]
pprintpp = [ prompt-toolkit = [
{file = "pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d"}, {file = "prompt_toolkit-3.0.19-py3-none-any.whl", hash = "sha256:7089d8d2938043508aa9420ec18ce0922885304cddae87fb96eebca942299f88"},
{file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"}, {file = "prompt_toolkit-3.0.19.tar.gz", hash = "sha256:08360ee3a3148bdb5163621709ee322ec34fc4375099afa4bbf751e9b7b7fa4f"},
]
ptyprocess = [
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
] ]
py = [ py = [
{file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
@ -876,6 +1094,10 @@ pyflakes = [
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
] ]
pygments = [
{file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"},
{file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"},
]
pyparsing = [ pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
@ -888,8 +1110,8 @@ pytest-bdd = [
{file = "pytest-bdd-4.0.2.tar.gz", hash = "sha256:982489f2f036c7561affe4eeb5b392a37e1ace2a9f260cad747b1c8119e63cfd"}, {file = "pytest-bdd-4.0.2.tar.gz", hash = "sha256:982489f2f036c7561affe4eeb5b392a37e1ace2a9f260cad747b1c8119e63cfd"},
{file = "pytest_bdd-4.0.2-py2.py3-none-any.whl", hash = "sha256:74ea5a147ea558c99ae83d838e6acbe5c9e6843884a958f8231615d96838733d"}, {file = "pytest_bdd-4.0.2-py2.py3-none-any.whl", hash = "sha256:74ea5a147ea558c99ae83d838e6acbe5c9e6843884a958f8231615d96838733d"},
] ]
pytest-icdiff = [ pytest-clarity = [
{file = "pytest-icdiff-0.5.tar.gz", hash = "sha256:3a14097f4385665cb04330e6ae09a3dd430375f717e94482af6944470ad5f100"}, {file = "pytest-clarity-0.3.0a0.tar.gz", hash = "sha256:5cc99e3d9b7969dfe17e5f6072d45a917c59d363b679686d3c958a1ded2e4dcf"},
] ]
python-dateutil = [ python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
@ -985,6 +1207,9 @@ six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
] ]
termcolor = [
{file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"},
]
textwrap3 = [ textwrap3 = [
{file = "textwrap3-0.9.2-py2.py3-none-any.whl", hash = "sha256:bf5f4c40faf2a9ff00a9e0791fed5da7415481054cef45bb4a3cfb1f69044ae0"}, {file = "textwrap3-0.9.2-py2.py3-none-any.whl", hash = "sha256:bf5f4c40faf2a9ff00a9e0791fed5da7415481054cef45bb4a3cfb1f69044ae0"},
{file = "textwrap3-0.9.2.zip", hash = "sha256:5008eeebdb236f6303dcd68f18b856d355f6197511d952ba74bc75e40e0c3414"}, {file = "textwrap3-0.9.2.zip", hash = "sha256:5008eeebdb236f6303dcd68f18b856d355f6197511d952ba74bc75e40e0c3414"},
@ -993,6 +1218,10 @@ toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
] ]
traitlets = [
{file = "traitlets-5.0.5-py3-none-any.whl", hash = "sha256:69ff3f9d5351f31a7ad80443c2674b7099df13cc41fc5fa6e2f6d3b0330b0426"},
{file = "traitlets-5.0.5.tar.gz", hash = "sha256:178f4ce988f69189f7e523337a3e11d91c786ded9360174a3d9ca83e79bc5396"},
]
typed-ast = [ typed-ast = [
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
@ -1053,6 +1282,10 @@ watchdog = [
{file = "watchdog-2.1.2-py3-none-win_ia64.whl", hash = "sha256:104266a778906ae0e971368d368a65c4cd032a490a9fca5ba0b78c6c7ae11720"}, {file = "watchdog-2.1.2-py3-none-win_ia64.whl", hash = "sha256:104266a778906ae0e971368d368a65c4cd032a490a9fca5ba0b78c6c7ae11720"},
{file = "watchdog-2.1.2.tar.gz", hash = "sha256:0237db4d9024859bea27d0efb59fe75eef290833fd988b8ead7a879b0308c2db"}, {file = "watchdog-2.1.2.tar.gz", hash = "sha256:0237db4d9024859bea27d0efb59fe75eef290833fd988b8ead7a879b0308c2db"},
] ]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
xmltodict = [ xmltodict = [
{file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"}, {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"},
{file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"}, {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"},

View file

@ -51,8 +51,9 @@ toml = ">=0.10"
pyflakes = ">=2.2.0" pyflakes = ">=2.2.0"
pytest = ">=6.2" pytest = ">=6.2"
pytest-bdd = "^4.0.1" pytest-bdd = "^4.0.1"
pytest-icdiff = "^0.5"
yq = ">=2.11" yq = ">=2.11"
ipdb = ">=0.13"
pytest-clarity = "^0.3.0-alpha.0"
[tool.poetry.scripts] [tool.poetry.scripts]
jrnl = 'jrnl.cli:cli' jrnl = 'jrnl.cli:cli'
@ -66,9 +67,15 @@ force_sort_within_sections = true
[tool.pytest.ini_options] [tool.pytest.ini_options]
minversion = "6.0" minversion = "6.0"
required_plugins = [
"pytest-bdd"
]
markers = [ markers = [
"todo", "todo",
] ]
addopts = [
"--pdbcls=IPython.terminal.debugger:Pdb"
]
filterwarnings = [ filterwarnings = [
"ignore::DeprecationWarning", "ignore::DeprecationWarning",

View file

@ -1,49 +1,49 @@
Feature: Writing new entries. Feature: Writing new entries.
Scenario Outline: Multiline entry with punctuation should keep title punctuation Scenario Outline: Multiline entry with punctuation should keep title punctuation
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl This is. the title\\n This is the second line" When we run "jrnl This is. the title\\n This is the second line"
And we run "jrnl -n 1" And we run "jrnl -n 1"
Then the output should contain "This is. the title" Then the output should contain "This is. the title"
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | simple.yaml |
| empty_folder | | empty_folder.yaml |
| dayone | | dayone.yaml |
| encrypted | | encrypted.yaml |
Scenario Outline: Single line entry with period should be split at period Scenario Outline: Single line entry with period should be split at period
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "test" if prompted And we use the password "test" if prompted
When we run "jrnl This is. the title" When we run "jrnl This is. the title"
And we run "jrnl -1" And we run "jrnl -1"
Then the output should contain "| the title" Then the output should contain "| the title"
Examples: configs Examples: configs
| config_file | | config_file |
| basic_onefile | | basic_onefile.yaml |
| basic_encrypted | | basic_encrypted.yaml |
| basic_folder | | basic_folder.yaml |
| basic_dayone | | basic_dayone.yaml |
Scenario Outline: CJK entry should be split at fullwidth period without following space. Scenario Outline: CJK entry should be split at fullwidth period without following space.
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "test" if prompted And we use the password "test" if prompted
When we run "jrnl " When we run "jrnl "
And we run "jrnl -1" And we run "jrnl -1"
Then the output should contain "| " Then the output should contain "| "
Examples: configs Examples: configs
| config_file | | config_file |
| basic_onefile | | basic_onefile.yaml |
| basic_encrypted | | basic_encrypted.yaml |
| basic_folder | | basic_folder.yaml |
| basic_dayone | | basic_dayone.yaml |
Scenario Outline: Writing an entry from command line should store the entry Scenario Outline: Writing an entry from command line should store the entry
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
Then we should see the message "Entry added" Then we should see the message "Entry added"
@ -51,49 +51,47 @@ Feature: Writing new entries.
Then the output should contain "2013-07-23 09:00 A cold and stormy day." Then the output should contain "2013-07-23 09:00 A cold and stormy day."
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | simple.yaml |
| empty_folder | | empty_folder.yaml |
| dayone | | dayone.yaml |
| encrypted | | encrypted.yaml |
Scenario Outline: Writing a partial entry from command line with edit flag should go to the editor Scenario Outline: Writing a partial entry from command line with edit flag should go to the editor
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "test" if prompted And we use the password "test" if prompted
When we run "jrnl this is a partial --edit" When we run "jrnl this is a partial --edit"
Then we should see the message "Entry added" Then we should see the message "Entry added"
Then the editor should have been called Then the editor should have been called
And the editor file content should be And the editor file content should be
""" this is a partial
this is a partial
"""
When we run "jrnl -n 1"
Then the output should contain "this is a partial"
Examples: configs Examples: configs
| config_file | | config_file |
| basic_onefile | | basic_onefile.yaml |
| basic_encrypted | | basic_encrypted.yaml |
| basic_dayone | | basic_dayone.yaml |
| basic_folder | | basic_folder.yaml |
Scenario Outline: Writing an empty entry from the editor should yield "Nothing saved to file" message Scenario Outline: Writing an empty entry from the editor should yield "Nothing saved to file" message
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we write nothing to the editor if opened
And we use the password "test" if prompted And we use the password "test" if prompted
When we open the editor and enter nothing When we run "jrnl --edit"
Then the error output should contain "[Nothing saved to file]" Then the error output should contain "[Nothing saved to file]"
And the editor should have been called
Examples: configs Examples: configs
| config_file | | config_file |
| editor | | editor.yaml |
| editor_empty_folder | | editor_empty_folder.yaml |
| dayone | | dayone.yaml |
| basic_encrypted | | basic_encrypted.yaml |
| basic_onefile | | basic_onefile.yaml |
@skip @skip
Scenario Outline: Writing an empty entry from the command line with no editor should yield nothing Scenario Outline: Writing an empty entry from the command line with no editor should yield nothing
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl" and enter nothing When we run "jrnl" and enter nothing
Then the output should be empty Then the output should be empty
@ -101,15 +99,15 @@ Feature: Writing new entries.
And the editor should not have been called And the editor should not have been called
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | config_simple.yaml |
| empty_folder | | empty_folder.yaml |
| encrypted | | encrypted.yaml |
# | dayone | @todo # | dayone | @todo
Scenario Outline: Writing an entry does not print the entire journal Scenario Outline: Writing an entry does not print the entire journal
# https://github.com/jrnl-org/jrnl/issues/87 # https://github.com/jrnl-org/jrnl/issues/87
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
Then we should see the message "Entry added" Then we should see the message "Entry added"
@ -117,33 +115,31 @@ Feature: Writing new entries.
Then the output should not contain "Life is good" Then the output should not contain "Life is good"
Examples: configs Examples: configs
| config_file | | config_file |
| editor | | editor.yaml |
| editor_empty_folder | | editor_empty_folder.yaml |
| dayone | | dayone.yaml |
| encrypted | | encrypted.yaml |
Scenario Outline: Embedded period stays in title Scenario Outline: Embedded period stays in title
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic." When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic."
Then we should see the message "Entry added" Then we should see the message "Entry added"
When we run "jrnl -1" When we run "jrnl -1"
Then the output should be Then the output should be
""" 2014-04-24 09:00 Created a new website - empty.com.
2014-04-24 09:00 Created a new website - empty.com. | Hope to get a lot of traffic.
| Hope to get a lot of traffic.
"""
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | simple.yaml |
| empty_folder | | empty_folder.yaml |
| dayone | | dayone.yaml |
| encrypted | | encrypted.yaml |
Scenario Outline: Write and read emoji support Scenario Outline: Write and read emoji support
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘" When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘"
Then we should see the message "Entry added" Then we should see the message "Entry added"
@ -152,14 +148,14 @@ Feature: Writing new entries.
And the output should contain "🐘" And the output should contain "🐘"
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | simple.yaml |
| empty_folder | | empty_folder.yaml |
| dayone | | dayone.yaml |
| encrypted | | encrypted.yaml |
Scenario Outline: Writing an entry at the prompt (no editor) should store the entry Scenario Outline: Writing an entry at the prompt (no editor) should store the entry
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>"
And we use the password "bad doggie no biscuit" if prompted And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive." When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive."
Then we should get no error Then we should get no error
@ -168,10 +164,10 @@ Feature: Writing new entries.
And the output should contain "| He's alive." And the output should contain "| He's alive."
Examples: configs Examples: configs
| config_file | | config_file |
| simple | | simple.yaml |
| empty_folder | | empty_folder.yaml |
| encrypted | | encrypted.yaml |
@todo @todo
Scenario: Writing an entry at the prompt (no editor) in DayOne journal Scenario: Writing an entry at the prompt (no editor) in DayOne journal
@ -187,26 +183,29 @@ Feature: Writing new entries.
Given we use the config "dayone.yaml" Given we use the config "dayone.yaml"
When we run "jrnl 01 may 1979: Being born hurts." When we run "jrnl 01 may 1979: Being born hurts."
And we run "jrnl --export json" And we run "jrnl --export json"
Then "entries" in the json output should have 5 elements Then we should get no error
And the json output should contain entries.0.creator.software_agent And the output should be valid JSON
And the json output should contain entries.0.creator.os_agent Given we parse the output as JSON
And the json output should contain entries.0.creator.host_name Then "entries" in the parsed output should have 5 elements
And the json output should contain entries.0.creator.generation_date And "entries.0.creator" in the parsed output should be
And the json output should contain entries.0.creator.device_agent software_agent
And "entries.0.creator.software_agent" in the json output should contain "jrnl" os_agent
host_name
generation_date
device_agent
And "entries.0.creator.software_agent" in the parsed output should contain
jrnl
# fails when system time is UTC (as on Travis-CI) # fails when system time is UTC (as on Travis-CI)
@skip # @skip
Scenario: Title with an embedded period on DayOne journal Scenario: Title with an embedded period on DayOne journal
Given we use the config "dayone.yaml" Given we use the config "dayone.yaml"
When we run "jrnl 04-24-2014: "Ran 6.2 miles today in 1:02:03. I'm feeling sore because I forgot to stretch."" When we run "jrnl 04-24-2014: "Ran 6.2 miles today in 1:02:03. I'm feeling sore because I forgot to stretch.""
Then we should see the message "Entry added" Then we should see the message "Entry added"
When we run "jrnl -1" When we run "jrnl -1"
Then the output should be Then the output should be
""" 2014-04-24 09:00 Ran 6.2 miles today in 1:02:03.
2014-04-24 09:00 Ran 6.2 miles today in 1:02:03. | I'm feeling sore because I forgot to stretch.
| I'm feeling sore because I forgot to stretch.
"""
Scenario: Opening an folder that's not a DayOne folder should treat as folder journal Scenario: Opening an folder that's not a DayOne folder should treat as folder journal
Given we use the config "empty_folder.yaml" Given we use the config "empty_folder.yaml"

View file

@ -8,6 +8,7 @@ from collections import defaultdict
from keyring import backend from keyring import backend
from keyring import set_keyring from keyring import set_keyring
from keyring import errors from keyring import errors
from pathlib import Path
import random import random
import string import string
import re import re
@ -191,12 +192,88 @@ def which_output_stream():
return None return None
@fixture
def editor_input():
return None
@fixture
def num_args():
return None
@fixture @fixture
def parsed_output(): def parsed_output():
return {"lang": None, "obj": None} return {"lang": None, "obj": None}
@fixture
def editor_state():
return {
"command": "",
"intent": {"method": "r", "input": None},
"tmpfile": {"name": None, "content": None},
}
@fixture
def editor(editor_state):
def _mock_editor(editor_command):
tmpfile = editor_command[-1]
editor_state["command"] = editor_command
editor_state["tmpfile"]["name"] = tmpfile
Path(tmpfile).touch()
with open(tmpfile, editor_state["intent"]["method"]) as f:
# Touch the file so jrnl knows it was edited
if editor_state["intent"]["input"] != None:
f.write(editor_state["intent"]["input"])
file_content = f.read()
editor_state["tmpfile"]["content"] = file_content
return _mock_editor
# ----- STEPS ----- # # ----- STEPS ----- #
@given(parse("we {editor_method} to the editor if opened\n{editor_input}"))
@given(parse("we {editor_method} nothing to the editor if opened"))
def we_enter_editor(editor_method, editor_input, editor_state):
file_method = editor_state["intent"]["method"]
if editor_method == "write":
file_method = "w+"
elif editor_method == "append":
file_method = "a+"
else:
assert False, f"Method '{editor_method}' not supported"
editor_state["intent"] = {"method": file_method, "input": editor_input}
@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
if isinstance(num_args, int):
assert len(editor_state["command"]) == int(num_args)
@then(parse('the editor file content should {comparison} "{str_value}"'))
@then(parse("the editor file content should {comparison} empty"))
@then(parse("the editor file content should {comparison}\n{str_value}"))
def contains_editor_file(comparison, str_value, editor_state):
content = editor_state["tmpfile"]["content"]
# content = f'\n"""\n{content}\n"""\n'
if comparison == "be":
assert content == str_value
elif comparison == "contain":
assert str_value in content
else:
assert False, f"Comparison '{comparison}' not supported"
@given("we have a keyring", target_fixture="keyring") @given("we have a keyring", target_fixture="keyring")
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring") @given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
def we_have_type_of_keyring(keyring_type): def we_have_type_of_keyring(keyring_type):
@ -245,7 +322,15 @@ def use_password_forever(pw):
@when('we run "jrnl <command>"') @when('we run "jrnl <command>"')
@when('we run "jrnl"') @when('we run "jrnl"')
def we_run( def we_run(
command, config_path, user_input, cli_run, capsys, password, keyring, cache_dir command,
config_path,
user_input,
cli_run,
capsys,
password,
keyring,
cache_dir,
editor,
): ):
if cache_dir["exists"]: if cache_dir["exists"]:
command = command.format(cache_dir=cache_dir["path"]) command = command.format(cache_dir=cache_dir["path"])
@ -270,7 +355,8 @@ def we_run(
patch("builtins.input", side_effect=user_input) as mock_input, \ patch("builtins.input", side_effect=user_input) as mock_input, \
patch("getpass.getpass", side_effect=password) as mock_getpass, \ patch("getpass.getpass", side_effect=password) as mock_getpass, \
patch("jrnl.install.get_config_path", return_value=config_path), \ patch("jrnl.install.get_config_path", return_value=config_path), \
patch("jrnl.config.get_config_path", return_value=config_path) \ patch("jrnl.config.get_config_path", return_value=config_path), \
patch("subprocess.call", side_effect=editor) as mock_editor \
: # @TODO: single point of truth for get_config_path (move from all calls from install to config) : # @TODO: single point of truth for get_config_path (move from all calls from install to config)
try: try:
cli(args) cli(args)
@ -290,6 +376,7 @@ def we_run(
"stdin": mock_stdin, "stdin": mock_stdin,
"input": mock_input, "input": mock_input,
"getpass": mock_getpass, "getpass": mock_getpass,
"editor": mock_editor,
} }
@ -526,11 +613,15 @@ def assert_parsed_output_item_count(node_name, number, parsed_output):
assert False, f"Language name {lang} not recognized" assert False, f"Language name {lang} not recognized"
@then(parse('"{field_name}" in the parsed output should be\n{expected_keys}')) @then(parse('"{field_name}" in the parsed output should {comparison}\n{expected_keys}'))
def assert_output_field_content(field_name, expected_keys, cli_run, parsed_output): def assert_output_field_content(
field_name, comparison, expected_keys, cli_run, parsed_output
):
lang = parsed_output["lang"] lang = parsed_output["lang"]
obj = parsed_output["obj"] obj = parsed_output["obj"]
expected_keys = expected_keys.split("\n") expected_keys = expected_keys.split("\n")
if len(expected_keys) == 1:
expected_keys = expected_keys[0]
if lang == "XML": if lang == "XML":
xml_node_names = (node.tag for node in obj) xml_node_names = (node.tag for node in obj)
@ -555,10 +646,22 @@ def assert_output_field_content(field_name, expected_keys, cli_run, parsed_outpu
assert node in my_obj, [my_obj.keys(), node] assert node in my_obj, [my_obj.keys(), node]
my_obj = my_obj[node] my_obj = my_obj[node]
if type(my_obj) is str: if comparison == "be":
my_obj = [my_obj] if type(my_obj) is str:
assert expected_keys == my_obj, [my_obj, expected_keys]
assert set(expected_keys) == set(my_obj), [set(my_obj), set(expected_keys)] else:
assert set(expected_keys) == set(my_obj), [
set(my_obj),
set(expected_keys),
]
elif comparison == "contain":
if type(my_obj) is str:
assert expected_keys in my_obj, [my_obj, expected_keys]
else:
assert all(elem in my_obj for elem in expected_keys), [
my_obj,
expected_keys,
]
else: else:
assert False, f"Language name {lang} not recognized" assert False, f"Language name {lang} not recognized"

View file

@ -5,13 +5,13 @@ scenarios("../features/core.feature")
scenarios("../features/datetime.feature") scenarios("../features/datetime.feature")
scenarios("../features/delete.feature") scenarios("../features/delete.feature")
scenarios("../features/encrypt.feature") scenarios("../features/encrypt.feature")
# scenarios("../features/file_storage.feature") scenarios("../features/file_storage.feature")
scenarios("../features/format.feature") scenarios("../features/format.feature")
# scenarios("../features/import.feature") scenarios("../features/import.feature")
# scenarios("../features/multiple_journals.feature") scenarios("../features/multiple_journals.feature")
scenarios("../features/password.feature") scenarios("../features/password.feature")
# scenarios("../features/search.feature") scenarios("../features/search.feature")
# scenarios("../features/star.feature") scenarios("../features/star.feature")
# scenarios("../features/tag.feature") scenarios("../features/tag.feature")
# scenarios("../features/upgrade.feature") scenarios("../features/upgrade.feature")
# scenarios("../features/write.feature") scenarios("../features/write.feature")