mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 16:48:31 +02:00
move some files around because pytest is being weird
This commit is contained in:
parent
cdad0d6289
commit
f99411f2f9
26 changed files with 81 additions and 907 deletions
10
Makefile
10
Makefile
|
@ -24,13 +24,13 @@ lint: ## Check style with various tools
|
||||||
unit: # unit tests
|
unit: # unit tests
|
||||||
poetry run pytest tests/unit
|
poetry run pytest tests/unit
|
||||||
|
|
||||||
e2e: # end-to-end tests
|
bdd: # bdd tests
|
||||||
poetry run pytest tests/step_defs --gherkin-terminal-reporter --tb=native --diff-type=unified
|
poetry run pytest tests/bdd --gherkin-terminal-reporter --tb=native --diff-type=unified
|
||||||
|
|
||||||
e2e-debug: # end-to-end tests
|
bdd-debug: # bdd tests
|
||||||
poetry run pytest tests/step_defs --gherkin-terminal-reporter --tb=native --diff-type=unified -x -vv
|
poetry run pytest tests/bdd --gherkin-terminal-reporter --tb=native --diff-type=unified -x -vv
|
||||||
|
|
||||||
test: lint unit e2e ## Run unit tests and behave tests
|
test: lint unit bdd ## Run unit tests and behave tests
|
||||||
|
|
||||||
build:
|
build:
|
||||||
poetry build
|
poetry build
|
||||||
|
|
114
poetry.lock
generated
114
poetry.lock
generated
|
@ -214,7 +214,7 @@ python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "4.5.0"
|
version = "4.6.0"
|
||||||
description = "Read metadata from Python packages"
|
description = "Read metadata from Python packages"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -226,7 +226,8 @@ zipp = ">=0.5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
||||||
testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
|
perf = ["ipython"]
|
||||||
|
testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
|
@ -444,11 +445,11 @@ python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "20.9"
|
version = "21.0"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyparsing = ">=2.0.2"
|
pyparsing = ">=2.0.2"
|
||||||
|
@ -641,11 +642,11 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-bdd"
|
name = "pytest-bdd"
|
||||||
version = "4.0.2"
|
version = "4.1.0"
|
||||||
description = "BDD for pytest"
|
description = "BDD for pytest"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
glob2 = "*"
|
glob2 = "*"
|
||||||
|
@ -654,7 +655,6 @@ parse = "*"
|
||||||
parse-type = "*"
|
parse-type = "*"
|
||||||
py = "*"
|
py = "*"
|
||||||
pytest = ">=4.3"
|
pytest = ">=4.3"
|
||||||
six = ">=1.9.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-clarity"
|
name = "pytest-clarity"
|
||||||
|
@ -724,7 +724,7 @@ pyyaml = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "2021.4.4"
|
version = "2021.7.1"
|
||||||
description = "Alternative regular expression module, to replace re."
|
description = "Alternative regular expression module, to replace re."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -861,7 +861,7 @@ test = ["coverage", "flake8", "wheel"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "zipp"
|
||||||
version = "3.4.1"
|
version = "3.5.0"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -869,7 +869,7 @@ python-versions = ">=3.6"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
||||||
testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
|
@ -992,8 +992,8 @@ glob2 = [
|
||||||
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
|
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
|
||||||
]
|
]
|
||||||
importlib-metadata = [
|
importlib-metadata = [
|
||||||
{file = "importlib_metadata-4.5.0-py3-none-any.whl", hash = "sha256:833b26fb89d5de469b24a390e9df088d4e52e4ba33b01dc5e0e4f41b81a16c00"},
|
{file = "importlib_metadata-4.6.0-py3-none-any.whl", hash = "sha256:c6513572926a96458f8c8f725bf0e00108fba0c9583ade9bd15b869c9d726e33"},
|
||||||
{file = "importlib_metadata-4.5.0.tar.gz", hash = "sha256:b142cc1dd1342f31ff04bb7d022492b09920cb64fed867cd3ea6f80fe3ebd139"},
|
{file = "importlib_metadata-4.6.0.tar.gz", hash = "sha256:4a5611fea3768d3d967c447ab4e93f567d95db92225b43b7b238dbfb855d70bb"},
|
||||||
]
|
]
|
||||||
iniconfig = [
|
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"},
|
||||||
|
@ -1090,8 +1090,8 @@ mypy-extensions = [
|
||||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||||
]
|
]
|
||||||
packaging = [
|
packaging = [
|
||||||
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
|
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
|
||||||
{file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
|
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
|
||||||
]
|
]
|
||||||
parse = [
|
parse = [
|
||||||
{file = "parse-1.19.0.tar.gz", hash = "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"},
|
{file = "parse-1.19.0.tar.gz", hash = "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"},
|
||||||
|
@ -1165,8 +1165,8 @@ pytest = [
|
||||||
{file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
|
{file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
|
||||||
]
|
]
|
||||||
pytest-bdd = [
|
pytest-bdd = [
|
||||||
{file = "pytest-bdd-4.0.2.tar.gz", hash = "sha256:982489f2f036c7561affe4eeb5b392a37e1ace2a9f260cad747b1c8119e63cfd"},
|
{file = "pytest-bdd-4.1.0.tar.gz", hash = "sha256:304cd2b09923b838d0c2f08331d1f4236a14ef3594efa94e3bdae0f384d3fa5d"},
|
||||||
{file = "pytest_bdd-4.0.2-py2.py3-none-any.whl", hash = "sha256:74ea5a147ea558c99ae83d838e6acbe5c9e6843884a958f8231615d96838733d"},
|
{file = "pytest_bdd-4.1.0-py3-none-any.whl", hash = "sha256:7c5221680cec9a97630e1fae6132f4a97c2f86a90914206ee06a55ae1a409fe5"},
|
||||||
]
|
]
|
||||||
pytest-clarity = [
|
pytest-clarity = [
|
||||||
{file = "pytest-clarity-0.3.0a0.tar.gz", hash = "sha256:5cc99e3d9b7969dfe17e5f6072d45a917c59d363b679686d3c958a1ded2e4dcf"},
|
{file = "pytest-clarity-0.3.0a0.tar.gz", hash = "sha256:5cc99e3d9b7969dfe17e5f6072d45a917c59d363b679686d3c958a1ded2e4dcf"},
|
||||||
|
@ -1215,47 +1215,43 @@ pyyaml-env-tag = [
|
||||||
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
||||||
]
|
]
|
||||||
regex = [
|
regex = [
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000"},
|
{file = "regex-2021.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:494d0172774dc0beeea984b94c95389143db029575f7ca908edd74469321ea99"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:8cf6728f89b071bd3ab37cb8a0e306f4de897553a0ed07442015ee65fbf53d62"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1806370b2bef4d4193eebe8ee59a9fd7547836a34917b7badbe6561a8594d9cb"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d0cf2651a8804f6325747c7e55e3be0f90ee2848e25d6b817aa2728d263f9abb"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:268fe9dd1deb4a30c8593cabd63f7a241dfdc5bd9dd0233906c718db22cdd49a"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:7743798dfb573d006f1143d745bf17efad39775a5190b347da5d83079646be56"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a"},
|
{file = "regex-2021.7.1-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:0e46c1191b2eb293a6912269ed08b4512e7e241bbf591f97e527492e04c77e93"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7"},
|
{file = "regex-2021.7.1-cp36-cp36m-win32.whl", hash = "sha256:b1dbeef938281f240347d50f28ae53c4b046a23389cd1fc4acec5ea0eae646a1"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29"},
|
{file = "regex-2021.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6c72ebb72e64e9bd195cb35a9b9bbfb955fd953b295255b8ae3e4ad4a146b615"},
|
||||||
{file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79"},
|
{file = "regex-2021.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf819c5b77ff44accc9a24e31f1f7ceaaf6c960816913ed3ef8443b9d20d81b6"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e80d2851109e56420b71f9702ad1646e2f0364528adbf6af85527bc61e49f394"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a1b6a3f600d6aff97e3f28c34192c9ed93fee293bd96ef327b64adb51a74b2f6"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ed77b97896312bc2deafe137ca2626e8b63808f5bedb944f73665c68093688a7"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a548bb51c4476332ce4139df8e637386730f79a92652a907d12c696b6252b64d"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:210c359e6ee5b83f7d8c529ba3c75ba405481d50f35a420609b0db827e2e3bb5"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765"},
|
{file = "regex-2021.7.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:1d386402ae7f3c9b107ae5863f7ecccb0167762c82a687ae6526b040feaa5ac6"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e"},
|
{file = "regex-2021.7.1-cp37-cp37m-win32.whl", hash = "sha256:5049d00dbb78f9d166d1c704e93934d42cce0570842bb1a61695123d6b01de09"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439"},
|
{file = "regex-2021.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:361be4d311ac995a8c7ad577025a3ae3a538531b1f2cf32efd8b7e5d33a13e5a"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d"},
|
{file = "regex-2021.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f32f47fb22c988c0b35756024b61d156e5c4011cb8004aa53d93b03323c45657"},
|
||||||
{file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:b024ee43ee6b310fad5acaee23e6485b21468718cb792a9d1693eecacc3f0b7e"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b092754c06852e8a8b022004aff56c24b06310189186805800d09313c37ce1f8"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a8a5826d8a1b64e2ff9af488cc179e1a4d0f144d11ce486a9f34ea38ccedf4ef"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:444723ebaeb7fa8125f29c01a31101a3854ac3de293e317944022ae5effa53a4"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:fdad3122b69cdabdb3da4c2a4107875913ac78dab0117fc73f988ad589c66b66"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093"},
|
{file = "regex-2021.7.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4b1999ef60c45357598935c12508abf56edbbb9c380df6f336de38a6c3a294ae"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10"},
|
{file = "regex-2021.7.1-cp38-cp38-win32.whl", hash = "sha256:e07e92935040c67f49571779d115ecb3e727016d42fb36ee0d8757db4ca12ee0"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f"},
|
{file = "regex-2021.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:6b8b629f93246e507287ee07e26744beaffb4c56ed520576deac8b615bd76012"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87"},
|
{file = "regex-2021.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56bef6b414949e2c9acf96cb5d78de8b529c7b99752619494e78dc76f99fd005"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:78a2a885345a2d60b5e68099e877757d5ed12e46ba1e87507175f14f80892af3"},
|
||||||
{file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3f7a92e60930f8fca2623d9e326c173b7cf2c8b7e4fdcf984b75a1d2fb08114d"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4fc86b729ab88fe8ac3ec92287df253c64aa71560d76da5acd8a2e245839c629"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:59845101de68fd5d3a1145df9ea022e85ecd1b49300ea68307ad4302320f6f61"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:ce269e903b00d1ab4746793e9c50a57eec5d5388681abef074d7b9a65748fca5"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7"},
|
{file = "regex-2021.7.1-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:c11f2fca544b5e30a0e813023196a63b1cb9869106ef9a26e9dae28bce3e4e26"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8"},
|
{file = "regex-2021.7.1-cp39-cp39-win32.whl", hash = "sha256:1ccbd41dbee3a31e18938096510b7d4ee53aa9fce2ee3dcc8ec82ae264f6acfd"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed"},
|
{file = "regex-2021.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:18040755606b0c21281493ec309214bd61e41a170509e5014f41d6a5a586e161"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c"},
|
{file = "regex-2021.7.1.tar.gz", hash = "sha256:849802379a660206277675aa5a5c327f5c910c690649535863ddf329b0ba8c87"},
|
||||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"},
|
|
||||||
{file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6"},
|
|
||||||
{file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07"},
|
|
||||||
{file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"},
|
|
||||||
]
|
]
|
||||||
secretstorage = [
|
secretstorage = [
|
||||||
{file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"},
|
{file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"},
|
||||||
|
@ -1357,6 +1353,6 @@ yq = [
|
||||||
{file = "yq-2.12.2.tar.gz", hash = "sha256:2f156d0724b61487ac8752ed4eaa702a5737b804d5afa46fa55866951cd106d2"},
|
{file = "yq-2.12.2.tar.gz", hash = "sha256:2f156d0724b61487ac8752ed4eaa702a5737b804d5afa46fa55866951cd106d2"},
|
||||||
]
|
]
|
||||||
zipp = [
|
zipp = [
|
||||||
{file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},
|
{file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"},
|
||||||
{file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"},
|
{file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"},
|
||||||
]
|
]
|
||||||
|
|
17
tests/bdd/test_features.py
Normal file
17
tests/bdd/test_features.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from pytest_bdd import scenarios
|
||||||
|
|
||||||
|
scenarios("features/build.feature")
|
||||||
|
scenarios("features/core.feature")
|
||||||
|
scenarios("features/datetime.feature")
|
||||||
|
scenarios("features/delete.feature")
|
||||||
|
scenarios("features/encrypt.feature")
|
||||||
|
scenarios("features/file_storage.feature")
|
||||||
|
scenarios("features/format.feature")
|
||||||
|
scenarios("features/import.feature")
|
||||||
|
scenarios("features/multiple_journals.feature")
|
||||||
|
scenarios("features/password.feature")
|
||||||
|
scenarios("features/search.feature")
|
||||||
|
scenarios("features/star.feature")
|
||||||
|
scenarios("features/tag.feature")
|
||||||
|
scenarios("features/upgrade.feature")
|
||||||
|
scenarios("features/write.feature")
|
|
@ -7,10 +7,10 @@ from jrnl.os_compat import on_windows
|
||||||
|
|
||||||
|
|
||||||
pytest_plugins = [
|
pytest_plugins = [
|
||||||
"tests.step_defs.fixtures",
|
"tests.lib.fixtures",
|
||||||
"tests.step_defs.given_steps",
|
"tests.lib.given_steps",
|
||||||
"tests.step_defs.when_steps",
|
"tests.lib.when_steps",
|
||||||
"tests.step_defs.then_steps",
|
"tests.lib.then_steps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append("..")
|
|
|
@ -1,201 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from keyring import backend
|
|
||||||
from keyring import errors
|
|
||||||
from keyring import set_keyring
|
|
||||||
from pytest import fixture
|
|
||||||
import toml
|
|
||||||
|
|
||||||
from jrnl.config import load_config
|
|
||||||
|
|
||||||
|
|
||||||
# --- Keyring --- #
|
|
||||||
@fixture
|
|
||||||
def keyring():
|
|
||||||
set_keyring(NoKeyring())
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def keyring_type():
|
|
||||||
return "default"
|
|
||||||
|
|
||||||
|
|
||||||
class TestKeyring(backend.KeyringBackend):
|
|
||||||
"""A test keyring that just stores its values in a hash"""
|
|
||||||
|
|
||||||
priority = 1
|
|
||||||
keys = defaultdict(dict)
|
|
||||||
|
|
||||||
def set_password(self, servicename, username, password):
|
|
||||||
self.keys[servicename][username] = password
|
|
||||||
|
|
||||||
def get_password(self, servicename, username):
|
|
||||||
return self.keys[servicename].get(username)
|
|
||||||
|
|
||||||
def delete_password(self, servicename, username):
|
|
||||||
self.keys[servicename][username] = None
|
|
||||||
|
|
||||||
|
|
||||||
class NoKeyring(backend.KeyringBackend):
|
|
||||||
"""A keyring that simulated an environment with no keyring backend."""
|
|
||||||
|
|
||||||
priority = 2
|
|
||||||
keys = defaultdict(dict)
|
|
||||||
|
|
||||||
def set_password(self, servicename, username, password):
|
|
||||||
raise errors.NoKeyringError
|
|
||||||
|
|
||||||
def get_password(self, servicename, username):
|
|
||||||
raise errors.NoKeyringError
|
|
||||||
|
|
||||||
def delete_password(self, servicename, username):
|
|
||||||
raise errors.NoKeyringError
|
|
||||||
|
|
||||||
|
|
||||||
class FailedKeyring(backend.KeyringBackend):
|
|
||||||
"""A keyring that cannot be retrieved."""
|
|
||||||
|
|
||||||
priority = 2
|
|
||||||
|
|
||||||
def set_password(self, servicename, username, password):
|
|
||||||
raise errors.KeyringError
|
|
||||||
|
|
||||||
def get_password(self, servicename, username):
|
|
||||||
raise errors.KeyringError
|
|
||||||
|
|
||||||
def delete_password(self, servicename, username):
|
|
||||||
raise errors.KeyringError
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Misc ----- #
|
|
||||||
@fixture
|
|
||||||
def cli_run():
|
|
||||||
return {"status": 0, "stdout": None, "stderr": None}
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def mocks():
|
|
||||||
return dict()
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def temp_dir():
|
|
||||||
return tempfile.TemporaryDirectory()
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def working_dir(request):
|
|
||||||
return os.path.join(request.config.rootpath, "tests")
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def config_path(temp_dir):
|
|
||||||
os.chdir(temp_dir.name)
|
|
||||||
return temp_dir.name + "/jrnl.yaml"
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def toml_version(working_dir):
|
|
||||||
pyproject = os.path.join(working_dir, "..", "pyproject.toml")
|
|
||||||
pyproject_contents = toml.load(pyproject)
|
|
||||||
return pyproject_contents["tool"]["poetry"]["version"]
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def password():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def input_method():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def cache_dir():
|
|
||||||
return {"exists": False, "path": ""}
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def str_value():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def command():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def should_not():
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def user_input():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def config_data(config_path):
|
|
||||||
return load_config(config_path)
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def journal_name():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def which_output_stream():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def editor_input():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def num_args():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def parsed_output():
|
|
||||||
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"] is not None:
|
|
||||||
f.write(editor_state["intent"]["input"])
|
|
||||||
|
|
||||||
file_content = f.read()
|
|
||||||
editor_state["tmpfile"]["content"] = file_content
|
|
||||||
|
|
||||||
return _mock_editor
|
|
|
@ -1,134 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import shutil
|
|
||||||
import string
|
|
||||||
from unittest.mock import MagicMock
|
|
||||||
from unittest.mock import patch
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
|
|
||||||
from keyring import set_keyring
|
|
||||||
from pytest_bdd import given
|
|
||||||
from pytest_bdd.parsers import parse
|
|
||||||
|
|
||||||
from jrnl import __version__
|
|
||||||
from jrnl.time import __get_pdt_calendar
|
|
||||||
|
|
||||||
from .fixtures import FailedKeyring
|
|
||||||
from .fixtures import TestKeyring
|
|
||||||
|
|
||||||
|
|
||||||
@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}
|
|
||||||
|
|
||||||
|
|
||||||
@given(parse('now is "<date_str>"'))
|
|
||||||
@given(parse('now is "{date_str}"'))
|
|
||||||
def now_is_str(date_str, mocks):
|
|
||||||
class DatetimeMagicMock(MagicMock):
|
|
||||||
# needed because jrnl does some reflection on datetime
|
|
||||||
def __instancecheck__(self, subclass):
|
|
||||||
return isinstance(subclass, datetime)
|
|
||||||
|
|
||||||
def mocked_now(tz=None):
|
|
||||||
now = datetime.strptime(date_str, "%Y-%m-%d %I:%M:%S %p")
|
|
||||||
|
|
||||||
if tz:
|
|
||||||
time_zone = datetime.utcnow().astimezone().tzinfo
|
|
||||||
now = now.replace(tzinfo=time_zone)
|
|
||||||
|
|
||||||
return now
|
|
||||||
|
|
||||||
# jrnl uses two different classes to parse dates, so both must be mocked
|
|
||||||
datetime_mock = DatetimeMagicMock(wraps=datetime)
|
|
||||||
datetime_mock.now.side_effect = mocked_now
|
|
||||||
|
|
||||||
pdt = __get_pdt_calendar()
|
|
||||||
calendar_mock = MagicMock(wraps=pdt)
|
|
||||||
calendar_mock.parse.side_effect = lambda date_str_input: pdt.parse(
|
|
||||||
date_str_input, mocked_now()
|
|
||||||
)
|
|
||||||
|
|
||||||
mocks["datetime"] = patch("datetime.datetime", new=datetime_mock)
|
|
||||||
mocks["calendar_parse"] = patch(
|
|
||||||
"jrnl.time.__get_pdt_calendar", return_value=calendar_mock
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@given("we have a keyring", target_fixture="keyring")
|
|
||||||
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
|
|
||||||
def we_have_type_of_keyring(keyring_type):
|
|
||||||
if keyring_type == "failed":
|
|
||||||
set_keyring(FailedKeyring())
|
|
||||||
else:
|
|
||||||
set_keyring(TestKeyring())
|
|
||||||
|
|
||||||
|
|
||||||
@given(parse('we use the config "{config_file}"'), target_fixture="config_path")
|
|
||||||
@given('we use the config "<config_file>"', target_fixture="config_path")
|
|
||||||
def we_use_the_config(config_file, temp_dir, working_dir):
|
|
||||||
# Move into temp dir as cwd
|
|
||||||
os.chdir(temp_dir.name)
|
|
||||||
|
|
||||||
# Copy the config file over
|
|
||||||
config_source = os.path.join(working_dir, "data", "configs", config_file)
|
|
||||||
config_dest = os.path.join(temp_dir.name, config_file)
|
|
||||||
shutil.copy2(config_source, config_dest)
|
|
||||||
|
|
||||||
# @todo make this only copy some journals over
|
|
||||||
# Copy all of the journals over
|
|
||||||
journal_source = os.path.join(working_dir, "data", "journals")
|
|
||||||
journal_dest = os.path.join(temp_dir.name, "features", "journals")
|
|
||||||
shutil.copytree(journal_source, journal_dest)
|
|
||||||
|
|
||||||
# @todo get rid of this by using default config values
|
|
||||||
# merge in version number
|
|
||||||
if config_file.endswith("yaml") and os.path.exists(config_dest):
|
|
||||||
# Add jrnl version to file for 2.x journals
|
|
||||||
with open(config_dest, "a") as cf:
|
|
||||||
cf.write("version: {}".format(__version__))
|
|
||||||
|
|
||||||
return config_dest
|
|
||||||
|
|
||||||
|
|
||||||
@given(parse('we use the password "{pw}" if prompted'), target_fixture="password")
|
|
||||||
def use_password_forever(pw):
|
|
||||||
return pw
|
|
||||||
|
|
||||||
|
|
||||||
@given("we create a cache directory", target_fixture="cache_dir")
|
|
||||||
def create_cache_dir(temp_dir):
|
|
||||||
random_str = "".join(random.choices(string.ascii_uppercase + string.digits, k=20))
|
|
||||||
|
|
||||||
dir_path = os.path.join(temp_dir.name, "cache_" + random_str)
|
|
||||||
os.mkdir(dir_path)
|
|
||||||
return {"exists": True, "path": dir_path}
|
|
||||||
|
|
||||||
|
|
||||||
@given(parse("we parse the output as {language_name}"), target_fixture="parsed_output")
|
|
||||||
def parse_output_as_language(cli_run, language_name):
|
|
||||||
language_name = language_name.upper()
|
|
||||||
actual_output = cli_run["stdout"]
|
|
||||||
|
|
||||||
if language_name == "XML":
|
|
||||||
parsed_output = ElementTree.fromstring(actual_output)
|
|
||||||
elif language_name == "JSON":
|
|
||||||
parsed_output = json.loads(actual_output)
|
|
||||||
else:
|
|
||||||
assert False, f"Language name {language_name} not recognized"
|
|
||||||
|
|
||||||
return {"lang": language_name, "obj": parsed_output}
|
|
|
@ -1,40 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def does_directory_contain_files(file_list, directory_path):
|
|
||||||
if not os.path.isdir(directory_path):
|
|
||||||
return False
|
|
||||||
|
|
||||||
for file in file_list.split("\n"):
|
|
||||||
fullpath = directory_path + "/" + file
|
|
||||||
if not os.path.isfile(fullpath):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
):
|
|
||||||
actual_tags = set(tag.strip() for tag in actual_line[len("tags: ") :].split(","))
|
|
||||||
expected_tags = set(
|
|
||||||
tag.strip() for tag in expected_line[len("tags: ") :].split(",")
|
|
||||||
)
|
|
||||||
assert actual_tags == expected_tags, [
|
|
||||||
[actual_tags, expected_tags],
|
|
||||||
[expected_content, actual_content],
|
|
||||||
]
|
|
|
@ -1,17 +0,0 @@
|
||||||
from pytest_bdd import scenarios
|
|
||||||
|
|
||||||
scenarios("../features/build.feature")
|
|
||||||
scenarios("../features/core.feature")
|
|
||||||
scenarios("../features/datetime.feature")
|
|
||||||
scenarios("../features/delete.feature")
|
|
||||||
scenarios("../features/encrypt.feature")
|
|
||||||
scenarios("../features/file_storage.feature")
|
|
||||||
scenarios("../features/format.feature")
|
|
||||||
scenarios("../features/import.feature")
|
|
||||||
scenarios("../features/multiple_journals.feature")
|
|
||||||
scenarios("../features/password.feature")
|
|
||||||
scenarios("../features/search.feature")
|
|
||||||
scenarios("../features/star.feature")
|
|
||||||
scenarios("../features/tag.feature")
|
|
||||||
scenarios("../features/upgrade.feature")
|
|
||||||
scenarios("../features/write.feature")
|
|
|
@ -1,331 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
|
|
||||||
from pytest_bdd import then
|
|
||||||
from pytest_bdd.parsers import parse
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should get no error")
|
|
||||||
def should_get_no_error(cli_run):
|
|
||||||
assert cli_run["status"] == 0, cli_run["status"]
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the output should match "{regex}"'))
|
|
||||||
def output_should_match(regex, cli_run):
|
|
||||||
out = cli_run["stdout"]
|
|
||||||
matches = re.findall(regex, out)
|
|
||||||
assert matches, f"\nRegex didn't match:\n{regex}\n{str(out)}\n{str(matches)}"
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should contain\n{expected_output}"))
|
|
||||||
@then(parse('the output should contain "{expected_output}"'))
|
|
||||||
@then('the output should contain "<expected_output>"')
|
|
||||||
@then(parse("the {which_output_stream} output should contain\n{expected_output}"))
|
|
||||||
@then(parse('the {which_output_stream} output should contain "{expected_output}"'))
|
|
||||||
def output_should_contain(expected_output, which_output_stream, cli_run):
|
|
||||||
assert expected_output
|
|
||||||
if which_output_stream is None:
|
|
||||||
assert (expected_output in cli_run["stdout"]) or (
|
|
||||||
expected_output in cli_run["stderr"]
|
|
||||||
)
|
|
||||||
|
|
||||||
elif which_output_stream == "standard":
|
|
||||||
assert expected_output in cli_run["stdout"]
|
|
||||||
|
|
||||||
elif which_output_stream == "error":
|
|
||||||
assert expected_output in cli_run["stderr"]
|
|
||||||
|
|
||||||
else:
|
|
||||||
assert expected_output in cli_run[which_output_stream]
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should not contain\n{expected_output}"))
|
|
||||||
@then(parse('the output should not contain "{expected_output}"'))
|
|
||||||
@then('the output should not contain "<expected_output>"')
|
|
||||||
def output_should_not_contain(expected_output, cli_run):
|
|
||||||
assert expected_output not in cli_run["stdout"]
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should be\n{expected_output}"))
|
|
||||||
@then(parse('the output should be "{expected_output}"'))
|
|
||||||
@then('the output should be "<expected_output>"')
|
|
||||||
def output_should_be(expected_output, cli_run):
|
|
||||||
actual = cli_run["stdout"].strip()
|
|
||||||
expected = expected_output.strip()
|
|
||||||
assert expected == actual
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should be empty")
|
|
||||||
def output_should_be_empty(cli_run):
|
|
||||||
actual = cli_run["stdout"].strip()
|
|
||||||
assert actual == ""
|
|
||||||
|
|
||||||
|
|
||||||
@then('the output should contain the date "<date>"')
|
|
||||||
def output_should_contain_date(date, cli_run):
|
|
||||||
assert date and date in cli_run["stdout"]
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should contain pyproject.toml version")
|
|
||||||
def output_should_contain_version(cli_run, toml_version):
|
|
||||||
out = cli_run["stdout"]
|
|
||||||
assert toml_version in out, toml_version
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('we should see the message "{text}"'))
|
|
||||||
def should_see_the_message(text, cli_run):
|
|
||||||
out = cli_run["stderr"]
|
|
||||||
assert text in out, [text, out]
|
|
||||||
|
|
||||||
|
|
||||||
@then(
|
|
||||||
parse(
|
|
||||||
'the config for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@then(
|
|
||||||
parse(
|
|
||||||
'the config for journal "{journal_name}" {should_or_should_not} contain\n{some_yaml}'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@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):
|
|
||||||
we_should = parse_should_or_should_not(should_or_should_not)
|
|
||||||
|
|
||||||
actual = config_data
|
|
||||||
if journal_name:
|
|
||||||
actual = actual["journals"][journal_name]
|
|
||||||
|
|
||||||
expected = yaml.load(some_yaml, Loader=yaml.FullLoader)
|
|
||||||
|
|
||||||
actual_slice = actual
|
|
||||||
if type(actual) is dict:
|
|
||||||
actual_slice = {key: actual.get(key, None) 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
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should not be prompted for a password")
|
|
||||||
def password_was_not_called(cli_run):
|
|
||||||
assert not cli_run["mocks"]["getpass"].called
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the cache directory should contain the files\n{file_list}"))
|
|
||||||
def assert_dir_contains_files(file_list, cache_dir):
|
|
||||||
assert does_directory_contain_files(file_list, cache_dir["path"])
|
|
||||||
|
|
||||||
|
|
||||||
@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")
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
assert not does_directory_contain_files(
|
|
||||||
scoped_config["journal"], "."
|
|
||||||
), f'Journal "{journal_name}" does exist'
|
|
||||||
|
|
||||||
|
|
||||||
@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")
|
|
||||||
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'"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the content of file "{file_path}" in the cache should be\n{file_content}'))
|
|
||||||
def content_of_file_should_be(file_path, file_content, cache_dir):
|
|
||||||
assert cache_dir["exists"]
|
|
||||||
expected_content = file_content.strip().splitlines()
|
|
||||||
|
|
||||||
with open(os.path.join(cache_dir["path"], file_path), "r") as f:
|
|
||||||
actual_content = f.read().strip().splitlines()
|
|
||||||
|
|
||||||
for actual_line, expected_line in zip(actual_content, expected_content):
|
|
||||||
if actual_line.startswith("tags: ") and expected_line.startswith("tags: "):
|
|
||||||
assert_equal_tags_ignoring_order(
|
|
||||||
actual_line, expected_line, actual_content, expected_content
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
assert actual_line.strip() == expected_line.strip(), [
|
|
||||||
[actual_line.strip(), expected_line.strip()],
|
|
||||||
[actual_content, expected_content],
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the cache should contain the files\n{file_list}"))
|
|
||||||
def cache_dir_contains_files(file_list, cache_dir):
|
|
||||||
assert cache_dir["exists"]
|
|
||||||
|
|
||||||
actual_files = os.listdir(cache_dir["path"])
|
|
||||||
expected_files = file_list.split("\n")
|
|
||||||
|
|
||||||
# sort to deal with inconsistent default file ordering on different OS's
|
|
||||||
actual_files.sort()
|
|
||||||
expected_files.sort()
|
|
||||||
|
|
||||||
assert actual_files == expected_files, [actual_files, expected_files]
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should be valid {language_name}"))
|
|
||||||
def assert_output_is_valid_language(cli_run, language_name):
|
|
||||||
language_name = language_name.upper()
|
|
||||||
if language_name == "XML":
|
|
||||||
xml_tree = ElementTree.fromstring(cli_run["stdout"])
|
|
||||||
assert xml_tree, "Invalid XML"
|
|
||||||
elif language_name == "JSON":
|
|
||||||
assert json.loads(cli_run["stdout"]), "Invalid JSON"
|
|
||||||
else:
|
|
||||||
assert False, f"Language name {language_name} not recognized"
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('"{node_name}" in the parsed output should have {number:d} elements'))
|
|
||||||
def assert_parsed_output_item_count(node_name, number, parsed_output):
|
|
||||||
lang = parsed_output["lang"]
|
|
||||||
obj = parsed_output["obj"]
|
|
||||||
|
|
||||||
if lang == "XML":
|
|
||||||
xml_node_names = (node.tag for node in obj)
|
|
||||||
assert node_name in xml_node_names, str(list(xml_node_names))
|
|
||||||
|
|
||||||
actual_entry_count = len(obj.find(node_name))
|
|
||||||
assert actual_entry_count == number, actual_entry_count
|
|
||||||
|
|
||||||
elif lang == "JSON":
|
|
||||||
my_obj = obj
|
|
||||||
|
|
||||||
for node in node_name.split("."):
|
|
||||||
try:
|
|
||||||
my_obj = my_obj[int(node)]
|
|
||||||
except ValueError:
|
|
||||||
assert node in my_obj
|
|
||||||
my_obj = my_obj[node]
|
|
||||||
|
|
||||||
assert len(my_obj) == number, len(my_obj)
|
|
||||||
|
|
||||||
else:
|
|
||||||
assert False, f"Language name {lang} not recognized"
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('"{field_name}" in the parsed output should {comparison}\n{expected_keys}'))
|
|
||||||
def assert_output_field_content(field_name, comparison, expected_keys, parsed_output):
|
|
||||||
lang = parsed_output["lang"]
|
|
||||||
obj = parsed_output["obj"]
|
|
||||||
expected_keys = expected_keys.split("\n")
|
|
||||||
if len(expected_keys) == 1:
|
|
||||||
expected_keys = expected_keys[0]
|
|
||||||
|
|
||||||
if lang == "XML":
|
|
||||||
xml_node_names = (node.tag for node in obj)
|
|
||||||
assert field_name in xml_node_names, str(list(xml_node_names))
|
|
||||||
|
|
||||||
if field_name == "tags":
|
|
||||||
actual_tags = set(t.attrib["name"] for t in obj.find("tags"))
|
|
||||||
assert set(actual_tags) == set(expected_keys), [
|
|
||||||
actual_tags,
|
|
||||||
set(expected_keys),
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
assert False, "This test only works for tags in XML"
|
|
||||||
|
|
||||||
elif lang == "JSON":
|
|
||||||
my_obj = obj
|
|
||||||
|
|
||||||
for node in field_name.split("."):
|
|
||||||
try:
|
|
||||||
my_obj = my_obj[int(node)]
|
|
||||||
except ValueError:
|
|
||||||
assert node in my_obj, [my_obj.keys(), node]
|
|
||||||
my_obj = my_obj[node]
|
|
||||||
|
|
||||||
if comparison == "be":
|
|
||||||
if type(my_obj) is str:
|
|
||||||
assert expected_keys == my_obj, [my_obj, 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:
|
|
||||||
assert False, f"Language name {lang} not recognized"
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('there should be {number:d} "{item}" elements'))
|
|
||||||
def count_elements(number, item, cli_run):
|
|
||||||
actual_output = cli_run["stdout"]
|
|
||||||
xml_tree = ElementTree.fromstring(actual_output)
|
|
||||||
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
|
|
||||||
|
|
||||||
if isinstance(num_args, int):
|
|
||||||
assert len(editor_state["command"]) == int(num_args)
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the editor filename should end with "{suffix}"'))
|
|
||||||
def editor_filename_suffix(suffix, editor_state):
|
|
||||||
editor_filename = editor_state["tmpfile"]["name"]
|
|
||||||
|
|
||||||
assert editor_state["tmpfile"]["name"].endswith(suffix), (editor_filename, suffix)
|
|
||||||
|
|
||||||
|
|
||||||
@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"
|
|
|
@ -1,113 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
from contextlib import ExitStack
|
|
||||||
import os
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from pytest_bdd import parsers
|
|
||||||
from pytest_bdd import when
|
|
||||||
from pytest_bdd.parsers import parse
|
|
||||||
|
|
||||||
from jrnl.cli import cli
|
|
||||||
from jrnl.os_compat import split_args
|
|
||||||
|
|
||||||
|
|
||||||
@when(parse('we change directory to "{directory_name}"'))
|
|
||||||
def when_we_change_directory(directory_name):
|
|
||||||
if not os.path.isdir(directory_name):
|
|
||||||
os.mkdir(directory_name)
|
|
||||||
|
|
||||||
os.chdir(directory_name)
|
|
||||||
|
|
||||||
|
|
||||||
@when(parse('we run "jrnl {command}" and {input_method}\n{user_input}'))
|
|
||||||
@when(
|
|
||||||
parsers.re(
|
|
||||||
'we run "jrnl (?P<command>[^"]+)" and (?P<input_method>enter|pipe) "(?P<user_input>[^"]+)"'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@when(parse('we run "jrnl" and {input_method} "{user_input}"'))
|
|
||||||
@when(parse('we run "jrnl {command}"'))
|
|
||||||
@when('we run "jrnl <command>"')
|
|
||||||
@when('we run "jrnl"')
|
|
||||||
def we_run(
|
|
||||||
command,
|
|
||||||
config_path,
|
|
||||||
user_input,
|
|
||||||
cli_run,
|
|
||||||
capsys,
|
|
||||||
password,
|
|
||||||
cache_dir,
|
|
||||||
editor,
|
|
||||||
keyring,
|
|
||||||
input_method,
|
|
||||||
mocks,
|
|
||||||
):
|
|
||||||
assert input_method in ["", "enter", "pipe"]
|
|
||||||
is_tty = input_method != "pipe"
|
|
||||||
|
|
||||||
if cache_dir["exists"]:
|
|
||||||
command = command.format(cache_dir=cache_dir["path"])
|
|
||||||
|
|
||||||
args = split_args(command)
|
|
||||||
status = 0
|
|
||||||
|
|
||||||
if user_input:
|
|
||||||
user_input = user_input.splitlines() if is_tty else [user_input]
|
|
||||||
|
|
||||||
if password:
|
|
||||||
password = password.splitlines()
|
|
||||||
|
|
||||||
if not password and user_input:
|
|
||||||
password = user_input
|
|
||||||
|
|
||||||
with ExitStack() as stack:
|
|
||||||
|
|
||||||
stack.enter_context(patch("sys.argv", ["jrnl"] + args))
|
|
||||||
|
|
||||||
mock_stdin = stack.enter_context(
|
|
||||||
patch("sys.stdin.read", side_effect=user_input)
|
|
||||||
)
|
|
||||||
stack.enter_context(patch("sys.stdin.isatty", return_value=is_tty))
|
|
||||||
mock_input = stack.enter_context(
|
|
||||||
patch("builtins.input", side_effect=user_input)
|
|
||||||
)
|
|
||||||
mock_getpass = stack.enter_context(
|
|
||||||
patch("getpass.getpass", side_effect=password)
|
|
||||||
)
|
|
||||||
|
|
||||||
if "datetime" in mocks:
|
|
||||||
stack.enter_context(mocks["datetime"])
|
|
||||||
stack.enter_context(mocks["calendar_parse"])
|
|
||||||
|
|
||||||
# stack.enter_context(patch("datetime.datetime", new=mocks["datetime"]))
|
|
||||||
# stack.enter_context(patch("jrnl.time.__get_pdt_calendar", return_value=mocks["calendar_parse"]))
|
|
||||||
|
|
||||||
stack.enter_context(
|
|
||||||
patch("jrnl.install.get_config_path", return_value=config_path)
|
|
||||||
)
|
|
||||||
stack.enter_context(
|
|
||||||
patch("jrnl.config.get_config_path", return_value=config_path)
|
|
||||||
)
|
|
||||||
mock_editor = stack.enter_context(patch("subprocess.call", side_effect=editor))
|
|
||||||
|
|
||||||
try:
|
|
||||||
cli(args)
|
|
||||||
except StopIteration:
|
|
||||||
# This happens when input is expected, but don't have any input left
|
|
||||||
pass
|
|
||||||
except SystemExit as e:
|
|
||||||
status = e.code
|
|
||||||
|
|
||||||
captured = capsys.readouterr()
|
|
||||||
|
|
||||||
cli_run["status"] = status
|
|
||||||
cli_run["stdout"] = captured.out
|
|
||||||
cli_run["stderr"] = captured.err
|
|
||||||
cli_run["mocks"] = {
|
|
||||||
"stdin": mock_stdin,
|
|
||||||
"input": mock_input,
|
|
||||||
"getpass": mock_getpass,
|
|
||||||
"editor": mock_editor,
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue