mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 08:38:32 +02:00
Add more steps to pytest
, fully remove behave
(#1347)
* update yaml loader to new method * Add config overrides steps to pytest This requires some patching around the config object, which now happens in every test. Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com> * udpate docs for new tests * remove behave from deps * remove feature dir from flake8 checks * udpate lock file * disable pip version check (it keeps spamming the pipeline) Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
parent
a98f3f78af
commit
44edb9bdee
112 changed files with 264 additions and 4814 deletions
10
.github/workflows/testing.yaml
vendored
10
.github/workflows/testing.yaml
vendored
|
@ -55,7 +55,7 @@ jobs:
|
||||||
if: ${{ matrix.python-version != '3.10-dev' }}
|
if: ${{ matrix.python-version != '3.10-dev' }}
|
||||||
run: |
|
run: |
|
||||||
echo '::group::poetry'
|
echo '::group::poetry'
|
||||||
pip install poetry
|
pip --disable-pip-version-check install poetry
|
||||||
poetry config --local virtualenvs.in-project true
|
poetry config --local virtualenvs.in-project true
|
||||||
echo '::endgroup::'
|
echo '::endgroup::'
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ jobs:
|
||||||
if: ${{ matrix.python-version == '3.10-dev' }}
|
if: ${{ matrix.python-version == '3.10-dev' }}
|
||||||
run: |
|
run: |
|
||||||
echo '::group::poetry'
|
echo '::group::poetry'
|
||||||
pip install poetry==1.2.0a2
|
pip --disable-pip-version-check install poetry==1.2.0a2
|
||||||
poetry config --local virtualenvs.in-project true
|
poetry config --local virtualenvs.in-project true
|
||||||
echo '::endgroup::'
|
echo '::endgroup::'
|
||||||
|
|
||||||
|
@ -90,12 +90,8 @@ jobs:
|
||||||
if: ${{ matrix.python-version != '3.10-dev' && env.DEPS_INSTALLED == 'true' }}
|
if: ${{ matrix.python-version != '3.10-dev' && env.DEPS_INSTALLED == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
poetry run pflake8 --version
|
poetry run pflake8 --version
|
||||||
poetry run pflake8 jrnl features tests
|
poetry run pflake8 jrnl tests
|
||||||
|
|
||||||
- name: Test with pytest
|
- name: Test with pytest
|
||||||
if: ${{ env.DEPS_INSTALLED == 'true' }}
|
if: ${{ env.DEPS_INSTALLED == 'true' }}
|
||||||
run: poetry run pytest --junitxml=reports/pytest/results.xml
|
run: poetry run pytest --junitxml=reports/pytest/results.xml
|
||||||
|
|
||||||
- name: Test with behave
|
|
||||||
if: ${{ env.DEPS_INSTALLED == 'true' }}
|
|
||||||
run: poetry run behave --no-skipped --format progress2 --junit --junit-directory reports/behave
|
|
||||||
|
|
|
@ -96,9 +96,9 @@ A typical development workflow includes:
|
||||||
|
|
||||||
When resolving bugs or adding new functionality, please add tests to prevent that functionality from breaking in the future. If you notice any functionality that isn't covered in the tests, feel free to submit a test-only pull request as well.
|
When resolving bugs or adding new functionality, please add tests to prevent that functionality from breaking in the future. If you notice any functionality that isn't covered in the tests, feel free to submit a test-only pull request as well.
|
||||||
|
|
||||||
For integration testing, jrnl uses [behave](https://behave.readthedocs.io/) tests, which are all in the `features` folder.
|
For testing, jrnl uses [pytest](https://docs.pytest.org) for unit tests, and [pytest-bdd](https://pytest-bdd.readthedocs.io/) for integration testing. All tests are in the `tests` folder.
|
||||||
|
|
||||||
Many tests can be created by only editing `feature` files with the same format as other tests. For more complicated functionality, you may need to implement steps in `features/steps` which are then executed by your tests in the `feature` files.
|
Many tests can be created by only editing `*.feature` files with the same format as other tests. For more complicated functionality, you may need to implement steps in `tests/lib/` which are then executed by your tests in the `feature` files.
|
||||||
|
|
||||||
Starting in 2020, jrnl is also using [pytest](https://docs.pytest.org/) for unit tests. These tests are in the `tests` folder.
|
Starting in 2020, jrnl is also using [pytest](https://docs.pytest.org/) for unit tests. These tests are in the `tests` folder.
|
||||||
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -30,7 +30,7 @@ bdd: # bdd tests
|
||||||
bdd-debug: # bdd tests
|
bdd-debug: # bdd tests
|
||||||
poetry run pytest tests/bdd --gherkin-terminal-reporter --tb=native -x -vv
|
poetry run pytest tests/bdd --gherkin-terminal-reporter --tb=native -x -vv
|
||||||
|
|
||||||
test: lint unit bdd ## Run unit tests and behave tests
|
test: lint unit bdd
|
||||||
|
|
||||||
build:
|
build:
|
||||||
poetry build
|
poetry build
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
Feature: Build process
|
|
||||||
|
|
||||||
@deployment_tests
|
|
||||||
Scenario: Version numbers should stay in sync
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --version"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should contain pyproject.toml version
|
|
|
@ -1,21 +0,0 @@
|
||||||
Feature: Functionality of jrnl outside of actually handling journals
|
|
||||||
|
|
||||||
Scenario: Displaying the version number
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --version"
|
|
||||||
Then we should get no error
|
|
||||||
Then the output should match "^jrnl version v\d+\.\d+(\.\d+)?(-(alpha|beta)\d*)?"
|
|
||||||
|
|
||||||
Scenario: Displaying the version number
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl -v"
|
|
||||||
Then we should get no error
|
|
||||||
Then the output should match "^jrnl version v\d+\.\d+(\.\d+)?(-(alpha|beta)\d*)?"
|
|
||||||
|
|
||||||
Scenario: Running the diagnostic command
|
|
||||||
When we run "jrnl --diagnostic"
|
|
||||||
Then the output should contain "jrnl"
|
|
||||||
And the output should contain "Python"
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Listing available journals
|
|
|
@ -1,17 +0,0 @@
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/basic_dayone.dayone
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
encrypt: true
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/basic_encrypted.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/basic_folder
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/basic_onefile.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/brackets.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/bug153.dayone
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
template: false
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,13 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
template: false
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
simple: features/journals/simple.journal
|
|
||||||
work: features/journals/work.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/bug780.dayone
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
template: false
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
template: false
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/dayone.dayone
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: noop
|
|
||||||
template: false
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/dayone_empty.dayone
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/deletion.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/deletion_filters.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: vim -f -c 'setf markdown'
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: "vim"
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: 'vim'
|
|
||||||
template: false
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/empty_folder
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
colors:
|
|
||||||
body: green
|
|
||||||
date: blue
|
|
||||||
tags: none
|
|
||||||
title: yellow
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: "vim"
|
|
||||||
encrypt: true
|
|
||||||
template: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/encrypted.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,18 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
editor: "vim"
|
|
||||||
journals:
|
|
||||||
default: features/journals/editor_markdown_extension.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: features/templates/extension.md
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
template: false
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/empty_folder
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: true
|
|
||||||
template: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/encrypted.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"default_hour": 9,
|
|
||||||
"default_minute": 0,
|
|
||||||
"editor": "",
|
|
||||||
"encrypt": true,
|
|
||||||
"highlight": true,
|
|
||||||
"journals": {
|
|
||||||
"default": "features/journals/encrypted_jrnl-1-9-5.journal"
|
|
||||||
},
|
|
||||||
"linewrap": 80,
|
|
||||||
"tagsymbols": "@",
|
|
||||||
"timeformat": "%Y-%m-%d %H:%M"
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: true
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/encrypted_jrnl1-9-5.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,19 +0,0 @@
|
||||||
colors:
|
|
||||||
body: none
|
|
||||||
date: none
|
|
||||||
tags: none
|
|
||||||
title: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
display_format: markdown
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
indent_character: '|'
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
template: false
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
version: v2.4.5
|
|
|
@ -1,19 +0,0 @@
|
||||||
colors:
|
|
||||||
body: none
|
|
||||||
date: none
|
|
||||||
tags: none
|
|
||||||
title: none
|
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
display_format: text
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
indent_character: '|'
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
template: false
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
version: v2.4.5
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: not-a-color
|
|
||||||
title: also-not-a-color
|
|
||||||
body: still-no-color
|
|
||||||
tags: me-too
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/little_endian_dates.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%d.%m.%Y %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
template: false
|
|
||||||
journals:
|
|
||||||
default: features/journals/markdown-headings-335.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/missing_directory/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/missing.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/mostlyreadabledates.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/multiline-tags.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/multiline.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,18 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
template: false
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
ideas: features/journals/nothing.journal
|
|
||||||
simple: features/journals/simple.journal
|
|
||||||
work: features/journals/work.journal
|
|
||||||
new_encrypted:
|
|
||||||
encrypt: true
|
|
||||||
journal: features/journals/new_encrypted.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
|
@ -1,12 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/simple.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
template: false
|
|
||||||
journals:
|
|
||||||
default: features/journals/tags-216.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
template: false
|
|
||||||
journals:
|
|
||||||
default: features/journals/tags-237.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ''
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
template: false
|
|
||||||
journals:
|
|
||||||
default: features/journals/tags.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: '@'
|
|
||||||
timeformat: '%Y-%m-%d %H:%M'
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,17 +0,0 @@
|
||||||
default_hour: 9
|
|
||||||
default_minute: 0
|
|
||||||
editor: ""
|
|
||||||
encrypt: false
|
|
||||||
highlight: true
|
|
||||||
journals:
|
|
||||||
default: features/journals/unreadabledates.journal
|
|
||||||
linewrap: 80
|
|
||||||
tagsymbols: "@"
|
|
||||||
template: false
|
|
||||||
timeformat: "%Y-%m-%d %H:%M"
|
|
||||||
indent_character: "|"
|
|
||||||
colors:
|
|
||||||
date: none
|
|
||||||
title: none
|
|
||||||
body: none
|
|
||||||
tags: none
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"default_hour": 9,
|
|
||||||
"timeformat": "%Y-%m-%d %H:%M",
|
|
||||||
"linewrap": 80,
|
|
||||||
"encrypt": false,
|
|
||||||
"editor": "",
|
|
||||||
"default_minute": 0,
|
|
||||||
"highlight": true,
|
|
||||||
"journals": {"default": "features/journals/simple_jrnl-1-9-5.journal"},
|
|
||||||
"tagsymbols": "@"
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"default_hour": 9,
|
|
||||||
"timeformat": "%d.%m.%Y %H:%M",
|
|
||||||
"linewrap": 80,
|
|
||||||
"encrypt": false,
|
|
||||||
"editor": "",
|
|
||||||
"default_minute": 0,
|
|
||||||
"highlight": true,
|
|
||||||
"journals": {"default": "features/journals/simple_jrnl-1-9-5_little_endian_dates.journal"},
|
|
||||||
"tagsymbols": "@"
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"default_hour": 9,
|
|
||||||
"timeformat": "%Y-%m-%d %H:%M",
|
|
||||||
"linewrap": 80,
|
|
||||||
"encrypt": true,
|
|
||||||
"editor": "",
|
|
||||||
"default_minute": 0,
|
|
||||||
"highlight": true,
|
|
||||||
"journals": {"default": "features/journals/encrypted_jrnl-1-9-5.journal", "missing": "features/journals/missing.journal"},
|
|
||||||
"tagsymbols": "@"
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"default_hour": 9,
|
|
||||||
"timeformat": "%Y-%m-%d %H:%M",
|
|
||||||
"linewrap": 80,
|
|
||||||
"encrypt": false,
|
|
||||||
"editor": "",
|
|
||||||
"default_minute": 0,
|
|
||||||
"highlight": true,
|
|
||||||
"journals": {"default": "features/journals/simple_jrnl-1-9-5.journal", "missing": "features/journals/missing.journal"},
|
|
||||||
"tagsymbols": "@"
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2020-08-29T18:11:00Z</date>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>Entry the first.
|
|
||||||
Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu
|
|
||||||
consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In
|
|
||||||
commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget
|
|
||||||
venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo.
|
|
||||||
|
|
||||||
Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo
|
|
||||||
ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse
|
|
||||||
potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget
|
|
||||||
molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed lectus
|
|
||||||
hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis
|
|
||||||
feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, vestibulum
|
|
||||||
urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod enim.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget
|
|
||||||
velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac
|
|
||||||
porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per
|
|
||||||
conubia nostra, per inceptos himenaeos.</string>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>America/Los_Angeles</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>D04D335AFED711EABA18FAFFC2100C3D</string>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array>
|
|
||||||
<string>ipsum</string>
|
|
||||||
<string>tagone</string>
|
|
||||||
<string>tagtwo</string>
|
|
||||||
</array>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string></string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2020-09-25T02:35:45Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>iris.lan</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Darwin/19.3.0</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>jrnl/v2.4.5</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,55 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2020-08-31T21:32:00Z</date>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>A second entry in what I hope to be a long series.
|
|
||||||
Sed sit amet metus et sapien feugiat elementum. Aliquam bibendum lobortis leo
|
|
||||||
vitae tempus. Donec eleifend nec mi non volutpat. Lorem ipsum dolor sit amet,
|
|
||||||
consectetur adipiscing elit. Praesent ut sodales libero. Maecenas nisl lorem,
|
|
||||||
vestibulum in tempus sit amet, fermentum ut arcu. Donec vel vestibulum lectus,
|
|
||||||
eget pretium enim. Maecenas diam nunc, imperdiet vitae pharetra sed, pretium id
|
|
||||||
lectus. Donec eu metus et turpis tempor tristique ac non ex. In tellus arcu,
|
|
||||||
egestas at efficitur et, ultrices vel est. Sed commodo et nibh non elementum.
|
|
||||||
Mauris tempus vitae neque vel viverra. @tagtwo all by its lonesome.
|
|
||||||
|
|
||||||
Nulla mattis elementum magna, viverra pretium dui fermentum et. Cras vel
|
|
||||||
vestibulum odio. Quisque sit amet turpis et urna finibus maximus. Interdum et
|
|
||||||
malesuada fames ac ante ipsum primis in faucibus. Fusce porttitor iaculis sem,
|
|
||||||
non dictum ipsum varius nec. Nulla eu erat at risus gravida blandit non vel
|
|
||||||
ante. Nam egestas ipsum leo, eu ultricies ipsum tincidunt vel. Morbi a commodo
|
|
||||||
eros.
|
|
||||||
|
|
||||||
Nullam dictum, nisl ac varius tempus, ex tortor fermentum nisl, non
|
|
||||||
tempus dolor neque a lorem. Suspendisse a faucibus ex, vel ornare tortor.
|
|
||||||
Maecenas tincidunt id felis quis semper. Pellentesque enim libero, fermentum
|
|
||||||
quis metus id, rhoncus euismod magna. Nulla finibus velit eu purus bibendum
|
|
||||||
interdum. Integer id justo dui. Integer eu tellus in turpis bibendum blandit.
|
|
||||||
Quisque auctor lacinia consectetur.</string>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>America/Los_Angeles</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>FC8A86CAFED711EA8892FAFFC2100C3D</string>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array>
|
|
||||||
<string>tagtwo</string>
|
|
||||||
</array>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string></string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2020-09-25T02:36:59Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>iris.lan</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Darwin/19.3.0</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>jrnl/v2.4.5</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,44 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2020-09-24T16:14:00Z</date>
|
|
||||||
<key>Starred</key>
|
|
||||||
<true/>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>The third entry finally after weeks without writing.
|
|
||||||
I'm so excited about emojis. 💯 🎶 💩
|
|
||||||
|
|
||||||
Donec semper pellentesque iaculis. Nullam cursus et justo sit amet venenatis.
|
|
||||||
Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. Nulla
|
|
||||||
eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis
|
|
||||||
dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh malesuada.
|
|
||||||
Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis
|
|
||||||
vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo.
|
|
||||||
Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at
|
|
||||||
ante eget fringilla. @tagthree and also @tagone</string>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>America/Los_Angeles</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>FD8ABC8EFED711EABC35FAFFC2100C3D</string>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array>
|
|
||||||
<string>tagthree</string>
|
|
||||||
<string>tagone</string>
|
|
||||||
</array>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string></string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2020-09-25T02:37:01Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>iris.lan</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Darwin/19.3.0</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>jrnl/v2.4.5</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1 +0,0 @@
|
||||||
gAAAAABfb4gQBMqqGn_W8v_s7qCi14bX7inuCOKbsBqIUf7_ch14vTUp7lrysPFvhBp5vGijTwDIbk4LKoIISj8NwM31I8L0zEbMx9y6iyF_zseGGNxBvNN0wzAXa67bs-ohiQhhebcdIc_52sltxL2ELh8JAKUaXRwyapgnMgJ7z6deJppLK-B7RE7BiT0eKjWTDMd2x6cZDswvHs9opDp5yjuKWV5m7x6ggCKYgHT3savT9Tg7V0Fq6K3LGWaE59lCrqlAB0u6dnrDX3qcF4SKyckaniXzRShZGebdkUKDcLFun2V2syZwYQN772xjznIsJ16iXicox2uYKg8CnTefsyCwaOZyBvySGEy3CrlBiuIRIcxCtjKbYJ2B-Aq7LZitnBR7Ny_6_Wm8HsBf3N-cFCp4GShiCKrxuXKcOZ7vszG5EKb78JS85bb0mswU5CSdgp6UAHjIZqfJq00qQsViBCbXq3oklCPZXdQkOf5U0KpG2MVUiD-Zcn5Qj3gnUhSEr-5wKU9tWrE63MGPyE6KjZlArZX2W2LeGnW2CEYw9eREGon06AzLJ4mj3BgtjVWLIdGcCwORXvHRjUqazWgbEmXNVTbtp_cKnkW-rFzRBrUoVme9v-1Y3sH0VvHBq7QIj915VzBklzWs1qzIyTPZG5Db9LvdQ7SiV8slf1Jo7l-ayUUdVj6igvKZcgfB4RUHolJoMps5p4lZ5sPqv59KtSa8DCpuoRczIj71OCpuRVARZgy1m5sUD9xSMxOBdy46u1Jnry6iMtzXWI3mEZe5m7UhmW_L4Zcv4bbk8XjkBeHjPdgm2B69jkLmCBFecD5ztoGesCGt_pNo_sWSKqLHV1-coKFB2Nn__a4utU9NJNdeNRkr8_ahU6tn3jmaFjfQ7cKfrXG_NCcYBRX9fja8EQIeBEp_3TCoXQqhuV_bGsNPA2qL63Pt6YiRaUf1g9FNBqJRlKCSOYNixSXQZN_rTePzx0SQ0aIQhADWls62WX-LG5-byJcB6W2P_cH21hDOXkoNEIyLnCz9HQ6Yd6Fbv7298ps3F6jiUDdWES23zv8sDgBuKUN94qSN34j6MDYGFnGI9zsJ-Y-I2frdlLfWPx3pUL7afcKh1nRgXdjctsTSxU2BDrsu03eBz2IoZjoOR0U51IrNMOD1NNT3kctXxHLuOHSEkwAzS3doncQbdRLi5Gc1dQuOUa4sC-p8gVjUKXO-oi_49kp9Km2Ay9wFg0epBbXx2QMzyMsN2dXeSbHF-BDXD6sULaq5syC0fOHqaMLycTCMk2wLfNyXgEt05WvAiDn-LDsRdylMRW2hXp5HWq3Poaul-7VNg6UEMlwVfgJ-7hNreuO6IRtwmx6YdqMscw0ms6mU_MQZU_dTIPg3JU4KL0YyMqPBPSGNCx3gMp41O05Ubir45FoJSnT5Dkj4v3N0S87Ys3HuFLverASsGt9bkcSzd2uMKCJjkspemPPi9VhrY4IOO03DWSWbHmxYzFc1SJ-24WM8Ch404QKpe1qy5LNzFgLvDwQhSIHjluezHXqrD-DVh1lWNNY3WmHI2ubOZfaorvLKqzBPZ6AhpIa60rKjm0OZIQOmJwWXwkdnzut6m8PtoiLzRN897YMgeztf1nmDwp0xE-EhknVZ3WV3TeqgZJ5ykfHQ5BU8x0Db57-UtKSuesKbqPPdBe91OdsPpkGlyl6psHj1_gPm4nLvzXQePwiPaEemR_gYCWGPvl9l1ANJufgCV9qQTmZGof3fb9mjv-9lS-9l_m8KirPPRpSBToNeDtk50ceYUsOlDGzIyusppG9pOcIGyiln1IO5aZ8d4_1E83qjcHTSaKGizICZU7a-pt5STBPMesy3JgBm23A2jO4m68ayBRMcLnw_RirHvvBaj0C6UR2tac45F0Ob3PpXcvFuK0g54ziIAhzGqwF9I-LZ6asXQWMW4y4EBOak8JJBorkfztzfkMaIgGu-4ZoRKOkVfdr4uzcghk3r6KUxD4-nv1ioX69-G5RwhMHppYk7z8RXS1cq5FkvzXbfEQ-Uv6M-sx32DcUy9dH-ZYhc7UWm75JJfiNXLaXT_bsc6VqQ7KPkg2-RA7CywUFCW9S0S-XdO03VdwqlUVo7fp1SKywEfhZv_9bhDCdMJBwZmigv2KP9Iz7fF6LrpLwZkzHuQGFPcyTHFpsVIFrFyJjNYCXpET9y0Q5Vt4fnea5fy-9ZiCt3S8aS0YOFJ35_kM5i3ss8eFPL0v7fIQS3ZilzdGB3bWL0J7kppHN_ekHu-wVk3UZxauoFh7hXLjPcipua-FYUIklLjcK6DG1bYP7_q6OnkC8Jl650FNezeWPomHEv7l_DO3y0tjI6SGdWvL3ZJns7Xp3ew8KsCREAUO7ffqumD03uF9N-9uWbDDjM7rk0vcg0ggfOs9Ni725mxqYpu4R285XCOVWHDvw7iU6eAvE6ry8TDXQBbNgGjTuTYFYYli7GuOqMxFIe1op2s7sRnoJE8O0J76S6APhjhjcnZRSuONWkVG_5o83uFMPSF8DtqLwuRA5E8AGfIwAUcj324sw-DA0ixBGUqomb-osUIisv3x0b044xn-FvD-8R3PZDnPbPsao8XYNxfQWStrNcZSrX2Ua-WAcv9qbQ73_57RKW4pao4ajOu7K5800D231WGiIa6aJzDnFUlzXEzYxFQyx7qegkm_9rrEp_v8TC9mfAcjWX5DMrCkxUskx9YKDfpFYq4NuxO_414gReKzd-lmorfigvttgS10N1XD74SwFluXJv-bqTbI5-SuYAhDGMv1dqrn38i3rOMQqqnQomvaUJRprqxUsKz14sSE1Y-cNqq1FXzZ6vIJq-K3YTfFWPRLeqi6gHzqS_R2YBXXUduKuYgmakiVdP3bWc-Ca8WKh5sVi6P51MO-cS7i9AZWOaOz7F8PsB4JZxAJjSOr3NBmv3EEve9auTFCudRjfC6668I_NMHaTP5CCV4cuhuAxUuKUGgd6WFjDcvoYPyn_lu3bQiqD9MEag4CaJYI9PlraRv5mbqptwxv3pca7usd0GmXN_2No_nwxB4gVb48LsBBkH35njCa5iv2EKXUSOf0k3swaTSEahqbyI4EDzPXtU5uBO39iQzNpgfV_sUpnGdysjqueUVcdWGI_s5CnrNJ-_yDAY06AoXfLrjP8_3NXB2058xZ2rfmTNJNCULz9634dICJReXNnmplxIg3i6GbzFvjfNtqjrWr_iqBShyIwuOUJRbXzdJNggx2BDNG-PEWDXl89SaudFICkDvyZKEcATIss6ZXfULIMfCrqmWmFwgXfNEd9TuvjqoxFlLSaY4UfDMiYa_arUMblFfoo5nV07GANhUoQd-6HRe7LjYeX5VRodOx6ZmZjIAUq-DYr-hatJJFR2tjT_qZht2MJeYT3GZ3o54m8zBBt0JTN7HVpKaOaM3A2hEM_Ah0QZ-DkLDxtCzMuv987GDiLT2-Riya97a47yHIJhZFzFpflW2FcuC8RFWXlfUKTQfZkFmxh3MUekUuS4yu4Z121xojVswk_4P7-FqLaSnGT2epI69I_cvalRx3wjds9-5TFYqf4GridlFBRx6Fv2fpNB9Zvp9k7NQ9oYcPuXGLoXH5kmWBagPhEGKHA_pjFUZmCuwUIoeP4nP8lhFrX8OGezsbSBG773CRJzEdfcgAc5G-p6M_24WZLZHDrsVBAvgrNt6R9eQbEviWU28t_417QCp-or9qqt4OTKv1dp_4MlZh8YBg2-dtpvzSc1l5e4kQFJu7oWlpbgsjB6pl1oRRKp1maedX-gOAf559zC4l85gfEpPln9Cnl6xvERQzfO0Ey4q91SdsgK7i7FBrKKmi2wGiemFvnaQsrjZ_IFujLo8-2c8g9zTiyH1knyoVOAAnQxqGpsz6z6PNfSxr3_G8tOlNFTV-yqN_LdVHMgXtXjn3U9koGsfMulyUcBDdR3d_0Yn6iEjBt77tbxKi2ry-0gQrB1fdGsgKjyE_tMrW8D_lQz0IXsVOzd2ixsFVXMFzD6OOD8JldV0FbA-VDAS-Tp_ezIZVp6lRq54XBgvsjzDyOmOgDbSOQN6SQmvxPnIsml1wgmtm80z-9gHBqmimHBtLKB6L7CtLmmPICMS2pX3eWOmakxscxqs8AVjijJdz_NYNfcdBeDj_fhm6dqD6iwk3EBZZfsrmMGdXtAMqf1r9ng9tsz-FriXwQiJ3IM3loBsk5DKr9CcaJtKSPuwDDlRynD2vwcD-XyF6YTQdSJa9fEcq-qXya2Scj4mqQ4RDemJgErdradRfwJfII3fWHh18XxmYVqi9Bwn3YRgwEadyo0-HjbNq6vJXi12igmP99ciRAfMVQLjfUfTwoOHj44Y2Ru_hPjJcvB6FIn6KLrrCSrZnrshFdFn4L36z1CrS8fbtdvrG3kdZQxsUJnMqttuwKRpLnDWTWkIwj_GRBFrzCFgbwGp1XYhemxggyKVuhZPfyyTIM9rhlPth6eGyrpYfap24Av_mGPRBLnzcjtpGbACGdKQL034kVmI7yENGvmY40KSrWsVG_BE9bSJhx0EptFsT2IxnxbuFD4hGb4fFag9V0BDiKpUoOZqIVqVO8cAp-5w4twvWZKkrhu16JNlLoXWMoFANrw-tp5LKSin1CUeRa4LWVI1GR8tRkIad_GnCHRv9JEMswlNy9wi2sDNsSxWT7WNasUW5-glgK9pR7d2pXGGOWfHj1U6CKIqmAiO3iw8igzhvyx_dAxMxPo
|
|
|
@ -1,19 +0,0 @@
|
||||||
[2020-08-29 11:11:00 AM] Entry the first.
|
|
||||||
Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu
|
|
||||||
consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In
|
|
||||||
commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget
|
|
||||||
venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo.
|
|
||||||
|
|
||||||
Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo
|
|
||||||
ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse
|
|
||||||
potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget
|
|
||||||
molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed lectus
|
|
||||||
hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis
|
|
||||||
feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, vestibulum
|
|
||||||
urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod enim.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget
|
|
||||||
velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac
|
|
||||||
porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per
|
|
||||||
conubia nostra, per inceptos himenaeos.
|
|
|
@ -1,23 +0,0 @@
|
||||||
[2020-08-31 02:32:00 PM] A second entry in what I hope to be a long series. *
|
|
||||||
Sed sit amet metus et sapien feugiat elementum. Aliquam bibendum lobortis leo
|
|
||||||
vitae tempus. Donec eleifend nec mi non volutpat. Lorem ipsum dolor sit amet,
|
|
||||||
consectetur adipiscing elit. Praesent ut sodales libero. Maecenas nisl lorem,
|
|
||||||
vestibulum in tempus sit amet, fermentum ut arcu. Donec vel vestibulum lectus,
|
|
||||||
eget pretium enim. Maecenas diam nunc, imperdiet vitae pharetra sed, pretium id
|
|
||||||
lectus. Donec eu metus et turpis tempor tristique ac non ex. In tellus arcu,
|
|
||||||
egestas at efficitur et, ultrices vel est. Sed commodo et nibh non elementum.
|
|
||||||
Mauris tempus vitae neque vel viverra. @tagtwo all by its lonesome.
|
|
||||||
|
|
||||||
Nulla mattis elementum magna, viverra pretium dui fermentum et. Cras vel
|
|
||||||
vestibulum odio. Quisque sit amet turpis et urna finibus maximus. Interdum et
|
|
||||||
malesuada fames ac ante ipsum primis in faucibus. Fusce porttitor iaculis sem,
|
|
||||||
non dictum ipsum varius nec. Nulla eu erat at risus gravida blandit non vel
|
|
||||||
ante. Nam egestas ipsum leo, eu ultricies ipsum tincidunt vel. Morbi a commodo
|
|
||||||
eros.
|
|
||||||
|
|
||||||
Nullam dictum, nisl ac varius tempus, ex tortor fermentum nisl, non
|
|
||||||
tempus dolor neque a lorem. Suspendisse a faucibus ex, vel ornare tortor.
|
|
||||||
Maecenas tincidunt id felis quis semper. Pellentesque enim libero, fermentum
|
|
||||||
quis metus id, rhoncus euismod magna. Nulla finibus velit eu purus bibendum
|
|
||||||
interdum. Integer id justo dui. Integer eu tellus in turpis bibendum blandit.
|
|
||||||
Quisque auctor lacinia consectetur.
|
|
|
@ -1,11 +0,0 @@
|
||||||
[2020-09-24 09:14:00 AM] The third entry finally after weeks without writing.
|
|
||||||
I'm so excited about emojis. 💯 🎶 💩
|
|
||||||
|
|
||||||
Donec semper pellentesque iaculis. Nullam cursus et justo sit amet venenatis.
|
|
||||||
Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. Nulla
|
|
||||||
eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis
|
|
||||||
dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh malesuada.
|
|
||||||
Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis
|
|
||||||
vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo.
|
|
||||||
Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at
|
|
||||||
ante eget fringilla. @tagthree and also @tagone
|
|
|
@ -1,58 +0,0 @@
|
||||||
[2020-08-29 11:11] Entry the first.
|
|
||||||
|
|
||||||
Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu
|
|
||||||
consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In
|
|
||||||
commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget
|
|
||||||
venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo.
|
|
||||||
|
|
||||||
Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo
|
|
||||||
ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse
|
|
||||||
potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget
|
|
||||||
molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed lectus
|
|
||||||
hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis
|
|
||||||
feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, vestibulum
|
|
||||||
urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod enim.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget
|
|
||||||
velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac
|
|
||||||
porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per
|
|
||||||
conubia nostra, per inceptos himenaeos.
|
|
||||||
|
|
||||||
[2020-08-31 14:32] A second entry in what I hope to be a long series. *
|
|
||||||
|
|
||||||
Sed sit amet metus et sapien feugiat elementum. Aliquam bibendum lobortis leo
|
|
||||||
vitae tempus. Donec eleifend nec mi non volutpat. Lorem ipsum dolor sit amet,
|
|
||||||
consectetur adipiscing elit. Praesent ut sodales libero. Maecenas nisl lorem,
|
|
||||||
vestibulum in tempus sit amet, fermentum ut arcu. Donec vel vestibulum lectus,
|
|
||||||
eget pretium enim. Maecenas diam nunc, imperdiet vitae pharetra sed, pretium id
|
|
||||||
lectus. Donec eu metus et turpis tempor tristique ac non ex. In tellus arcu,
|
|
||||||
egestas at efficitur et, ultrices vel est. Sed commodo et nibh non elementum.
|
|
||||||
Mauris tempus vitae neque vel viverra. @tagtwo all by its lonesome.
|
|
||||||
|
|
||||||
Nulla mattis elementum magna, viverra pretium dui fermentum et. Cras vel
|
|
||||||
vestibulum odio. Quisque sit amet turpis et urna finibus maximus. Interdum et
|
|
||||||
malesuada fames ac ante ipsum primis in faucibus. Fusce porttitor iaculis sem,
|
|
||||||
non dictum ipsum varius nec. Nulla eu erat at risus gravida blandit non vel
|
|
||||||
ante. Nam egestas ipsum leo, eu ultricies ipsum tincidunt vel. Morbi a commodo
|
|
||||||
eros.
|
|
||||||
|
|
||||||
Nullam dictum, nisl ac varius tempus, ex tortor fermentum nisl, non
|
|
||||||
tempus dolor neque a lorem. Suspendisse a faucibus ex, vel ornare tortor.
|
|
||||||
Maecenas tincidunt id felis quis semper. Pellentesque enim libero, fermentum
|
|
||||||
quis metus id, rhoncus euismod magna. Nulla finibus velit eu purus bibendum
|
|
||||||
interdum. Integer id justo dui. Integer eu tellus in turpis bibendum blandit.
|
|
||||||
Quisque auctor lacinia consectetur.
|
|
||||||
|
|
||||||
[2020-09-24 09:14] The third entry finally after weeks without writing.
|
|
||||||
|
|
||||||
I'm so excited about emojis. 💯 🎶 💩
|
|
||||||
|
|
||||||
Donec semper pellentesque iaculis. Nullam cursus et justo sit amet venenatis.
|
|
||||||
Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. Nulla
|
|
||||||
eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis
|
|
||||||
dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh malesuada.
|
|
||||||
Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis
|
|
||||||
vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo.
|
|
||||||
Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at
|
|
||||||
ante eget fringilla. @tagthree and also @tagone
|
|
|
@ -1,2 +0,0 @@
|
||||||
[2019-07-08 05:42] Entry subject
|
|
||||||
[1] line starting with 1
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
||||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-10-27T02:27:27Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>iPhone/iPhone3,1</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-10-27T07:02:27Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>omrt104001</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>iOS/7.0.3</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (iOS)/1.11.4</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>Some text.</string>
|
|
||||||
<key>Location</key>
|
|
||||||
<dict>
|
|
||||||
<key>Administrative Area</key>
|
|
||||||
<string>Östergötlands län</string>
|
|
||||||
<key>Country</key>
|
|
||||||
<string>Sverige</string>
|
|
||||||
<key>Latitude</key>
|
|
||||||
<real>58.383400000000000</real>
|
|
||||||
<key>Locality</key>
|
|
||||||
<string>City</string>
|
|
||||||
<key>Longitude</key>
|
|
||||||
<real>15.577170000000000</real>
|
|
||||||
<key>Place Name</key>
|
|
||||||
<string>Street</string>
|
|
||||||
</dict>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>Europe/Stockholm</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>B40EE704E15846DE8D45C44118A4D511</string>
|
|
||||||
<key>Weather</key>
|
|
||||||
<dict>
|
|
||||||
<key>Celsius</key>
|
|
||||||
<string>12</string>
|
|
||||||
<key>Description</key>
|
|
||||||
<string>Clear</string>
|
|
||||||
<key>Fahrenheit</key>
|
|
||||||
<string>54</string>
|
|
||||||
<key>IconName</key>
|
|
||||||
<string>sunnyn.png</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,52 +0,0 @@
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-10-27T02:27:27Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>iPhone/iPhone3,1</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-10-27T07:02:27Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>omrt104001</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>iOS/7.0.3</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (iOS)/1.11.4</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>This is not a valid plist.</string>
|
|
||||||
<key>Location</key>
|
|
||||||
<dict>
|
|
||||||
<key>Administrative Area</key>
|
|
||||||
<string>Östergötlands län</string>
|
|
||||||
<key>Country</key>
|
|
||||||
<string>Sverige</string>
|
|
||||||
<key>Latitude</key>
|
|
||||||
<real>58.383400000000000</real>
|
|
||||||
<key>Locality</key>
|
|
||||||
<string>City</string>
|
|
||||||
<key>Longitude</key>
|
|
||||||
<real>15.577170000000000</real>
|
|
||||||
<key>Place Name</key>
|
|
||||||
<string>Street</string>
|
|
||||||
</dict>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>Europe/Stockholm</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>B40EE704E15846DE8D45C44118A4D511</string>
|
|
||||||
<key>Weather</key>
|
|
||||||
<dict>
|
|
||||||
<key>Celsius</key>
|
|
||||||
<string>12</string>
|
|
||||||
<key>Description</key>
|
|
||||||
<string>Clear</string>
|
|
||||||
<key>Fahrenheit</key>
|
|
||||||
<string>54</string>
|
|
||||||
<key>IconName</key>
|
|
||||||
<string>sunnyn.png</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Activity</key>
|
|
||||||
<string>Stationary</string>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2019-12-30T21:28:54Z</date>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string></string>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false />
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>48A25033B34047C591160A4480197D8B</string>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>PC</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2019-12-30T21:28:54Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>LE-TREPORT</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Microsoft Windows/10 Home</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Journaley/2.1</string>
|
|
||||||
</dict>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array>
|
|
||||||
<string>i_have_no_body</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-05-17T18:39:20Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>Macintosh/MacBookAir5,2</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-08-17T18:39:20Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>Egeria</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Mac OS X/10.8.4</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (Mac)/1.8</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>This entry has tags!</string>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array>
|
|
||||||
<string>work</string>
|
|
||||||
<string>PLaY</string>
|
|
||||||
</array>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>America/Los_Angeles</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>044F3747A38546168B572C2E3F217FA2</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-06-17T18:38:29Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>Macintosh/MacBookAir5,2</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-08-17T18:38:29Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>Egeria</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Mac OS X/10.8.4</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (Mac)/1.8</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>This entry has a location.</string>
|
|
||||||
<key>Location</key>
|
|
||||||
<dict>
|
|
||||||
<key>Administrative Area</key>
|
|
||||||
<string>California</string>
|
|
||||||
<key>Country</key>
|
|
||||||
<string>Germany</string>
|
|
||||||
<key>Latitude</key>
|
|
||||||
<real>52.4979764</real>
|
|
||||||
<key>Locality</key>
|
|
||||||
<string>Berlin</string>
|
|
||||||
<key>Longitude</key>
|
|
||||||
<real>13.2404758</real>
|
|
||||||
<key>Place Name</key>
|
|
||||||
<string>Abandoned Spy Tower</string>
|
|
||||||
</dict>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array/>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>Europe/Berlin</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>0BDDD6CDA43C4A9AA2681517CC35AD9D</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-07-17T18:38:08Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>Macintosh/MacBookAir5,2</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-08-17T18:38:08Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>Egeria</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Mac OS X/10.8.4</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (Mac)/1.8</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>This entry is starred!</string>
|
|
||||||
<key>Starred</key>
|
|
||||||
<true/>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array/>
|
|
||||||
<key>Time Zone</key>
|
|
||||||
<string>America/Los_Angeles</string>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>422BC895507944A291E6FC44FC6B8BFC</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Creation Date</key>
|
|
||||||
<date>2013-01-17T18:37:50Z</date>
|
|
||||||
<key>Creator</key>
|
|
||||||
<dict>
|
|
||||||
<key>Device Agent</key>
|
|
||||||
<string>Macintosh/MacBookAir5,2</string>
|
|
||||||
<key>Generation Date</key>
|
|
||||||
<date>2013-08-17T18:37:50Z</date>
|
|
||||||
<key>Host Name</key>
|
|
||||||
<string>Egeria</string>
|
|
||||||
<key>OS Agent</key>
|
|
||||||
<string>Mac OS X/10.8.4</string>
|
|
||||||
<key>Software Agent</key>
|
|
||||||
<string>Day One (Mac)/1.8</string>
|
|
||||||
</dict>
|
|
||||||
<key>Entry Text</key>
|
|
||||||
<string>This is a DayOne entry without Timezone.</string>
|
|
||||||
<key>Starred</key>
|
|
||||||
<false/>
|
|
||||||
<key>Tags</key>
|
|
||||||
<array/>
|
|
||||||
<key>UUID</key>
|
|
||||||
<string>4BB1F46946AD439996C9B59DE7C4DDC1</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1 +0,0 @@
|
||||||
This file exists to preserve the directory structure, but should be ignored by jrnl.
|
|
|
@ -1,5 +0,0 @@
|
||||||
[2019-10-29 11:11] First entry.
|
|
||||||
|
|
||||||
[2019-10-29 11:11] Second entry.
|
|
||||||
|
|
||||||
[2019-10-29 11:13] Third entry.
|
|
|
@ -1,14 +0,0 @@
|
||||||
[2019-10-01 08:00] It's just another day in October.
|
|
||||||
Not much to write about.
|
|
||||||
|
|
||||||
[2020-01-01 08:00] Happy New Year!
|
|
||||||
So this is the New Year. @holidays
|
|
||||||
|
|
||||||
[2020-03-01 08:00] It's just another day in March.
|
|
||||||
A stick, a stone, it's the end of the road.
|
|
||||||
|
|
||||||
[2020-05-01 09:00] Happy May Day!
|
|
||||||
@holidays @springtime Several holidays fall on this date.
|
|
||||||
|
|
||||||
[2020-05-02 12:10] Writing tests. *
|
|
||||||
@springtime They will help prevent bugs.
|
|
|
@ -1 +0,0 @@
|
||||||
Nothing to see here
|
|
|
@ -1 +0,0 @@
|
||||||
gAAAAABVIHB7tnwKExG7aC5ZbAbBL9SG2oY2GENeoOJ22i1PZigOvCYvrQN3kpsu0KGr7ay5K-_46R5YFlqJvtQ8anPH2FSITsaZy-l5Lz_5quw3rmzhLwAR1tc0icgtR4MEpXEdsuQ7cyb12Xq-JLDrnATs0id5Vow9Ri_tE7Xe4BXgXaySn3aRPwWKoninVxVPVvETY3MXHSUEXV9OZ-pH5kYBLGYbLA==
|
|
Binary file not shown.
|
@ -1,5 +0,0 @@
|
||||||
[09.06.2013 15:39] My first entry.
|
|
||||||
Everything is alright
|
|
||||||
|
|
||||||
[10.07.2013 15:40] Life is good.
|
|
||||||
But I'm better.
|
|
|
@ -1,42 +0,0 @@
|
||||||
[2015-04-14 13:23] Heading Test
|
|
||||||
|
|
||||||
H1-1
|
|
||||||
=
|
|
||||||
|
|
||||||
H1-2
|
|
||||||
===
|
|
||||||
|
|
||||||
H1-3
|
|
||||||
============================
|
|
||||||
|
|
||||||
H2-1
|
|
||||||
-
|
|
||||||
|
|
||||||
H2-2
|
|
||||||
---
|
|
||||||
|
|
||||||
H2-3
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
Horizontal Rules (ignore)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
===
|
|
||||||
|
|
||||||
# ATX H1
|
|
||||||
|
|
||||||
## ATX H2
|
|
||||||
|
|
||||||
### ATX H3
|
|
||||||
|
|
||||||
#### ATX H4
|
|
||||||
|
|
||||||
##### ATX H5
|
|
||||||
|
|
||||||
###### ATX H6
|
|
||||||
|
|
||||||
Stuff
|
|
||||||
|
|
||||||
More stuff
|
|
||||||
more stuff again
|
|
|
@ -1,8 +0,0 @@
|
||||||
[2019-07-18 14:23] Entry subject
|
|
||||||
Time machines are possible. I know, because I've built one in my garage.
|
|
||||||
|
|
||||||
[2019-07-19 14:23] Entry subject
|
|
||||||
I'm going to activate the machine. Nobody knows what comes next after this. Or before this?
|
|
||||||
|
|
||||||
[2019-07 14:23] Entry subject
|
|
||||||
I've crossed so many timelines. Is there any going back?
|
|
|
@ -1,7 +0,0 @@
|
||||||
[2013-06-09 15:39] Multiple @line entry with @tags.
|
|
||||||
Tag with @punctuation. afterwards
|
|
||||||
@TagOnLineAloneWithOutPunctuation
|
|
||||||
@TagOnLineAloneWithPunctuation.
|
|
||||||
Text before @tag. And After.
|
|
||||||
@hi. Hello
|
|
||||||
hi Hello
|
|
|
@ -1,5 +0,0 @@
|
||||||
[2013-06-09 15:39] Multiple line entry.
|
|
||||||
This is the first line.
|
|
||||||
This line doesn't have any ending punctuation
|
|
||||||
|
|
||||||
There is a blank line above this.
|
|
|
@ -1,5 +0,0 @@
|
||||||
[2013-06-09 15:39] My first entry.
|
|
||||||
Everything is alright
|
|
||||||
|
|
||||||
[2013-06-10 15:40] Life is good.
|
|
||||||
But I'm better.
|
|
|
@ -1,13 +0,0 @@
|
||||||
2010-06-10 15:00 A life without chocolate is like a bad analogy.
|
|
||||||
|
|
||||||
2013-06-10 15:40 He said "[this] is the best time to be alive".
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis.
|
|
||||||
|
|
||||||
[2019-08-03 12:55] Some chat log or something
|
|
||||||
|
|
||||||
Suspendisse potenti. Sed dignissim sed nisl eu consequat. Aenean ante ex,
|
|
||||||
elementum ut interdum et, mattis eget lacus. In commodo nulla nec tellus
|
|
||||||
placerat, sed ultricies metus bibendum. Duis eget venenatis erat. In at dolor
|
|
||||||
dui.
|
|
|
@ -1,13 +0,0 @@
|
||||||
10.06.2010 15:00 A life without chocolate is like a bad analogy.
|
|
||||||
|
|
||||||
10.06.2013 15:40 He said "[this] is the best time to be alive".
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis.
|
|
||||||
|
|
||||||
[03.08.2019 12:55] Some chat log or something
|
|
||||||
|
|
||||||
Suspendisse potenti. Sed dignissim sed nisl eu consequat. Aenean ante ex,
|
|
||||||
elementum ut interdum et, mattis eget lacus. In commodo nulla nec tellus
|
|
||||||
placerat, sed ultricies metus bibendum. Duis eget venenatis erat. In at dolor
|
|
||||||
dui.
|
|
|
@ -1,2 +0,0 @@
|
||||||
[2013-06-10 15:40] I programmed for @OS/2.
|
|
||||||
Almost makes me want to go back to @C++, though. (Still better than @C#).
|
|
|
@ -1,3 +0,0 @@
|
||||||
[2014-07-22 11:11] This entry has an email.
|
|
||||||
@Newline tag should show as a tag.
|
|
||||||
Kyla's @email is kyla@clevelandunderdog.org and Guinness's is guinness@fortheloveofpits.org.
|
|
|
@ -1,8 +0,0 @@
|
||||||
[2013-04-09 15:39] I have an @idea:
|
|
||||||
(1) write a command line @journal software
|
|
||||||
(2) ???
|
|
||||||
(3) PROFIT!
|
|
||||||
|
|
||||||
[2013-06-10 15:40] I met with @dan.
|
|
||||||
As alway's he shared his latest @idea on how to rule the world with me.
|
|
||||||
inst
|
|
|
@ -1,5 +0,0 @@
|
||||||
[ashasd7zdskhz7asdkjasd] Entry subject
|
|
||||||
I've lost track of time.
|
|
||||||
|
|
||||||
[sadfhakjsdf88sdf7sdff] Entry subject
|
|
||||||
Time has no meaning.
|
|
|
@ -1,19 +0,0 @@
|
||||||
---
|
|
||||||
extension: txt
|
|
||||||
---
|
|
||||||
|
|
||||||
{% block journal %}
|
|
||||||
{% for entry in entries %}
|
|
||||||
{% include entry %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block entry %}
|
|
||||||
{{ entry.title }}
|
|
||||||
{{ "-" * len(entry.title) }}
|
|
||||||
|
|
||||||
{{ entry.body }}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
`
|
|
|
@ -1,155 +0,0 @@
|
||||||
Feature: Reading and writing to journal with custom date formats
|
|
||||||
|
|
||||||
Scenario: Dates can include a time
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/117
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl 2013-11-30 15:42: Project Started."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
And the journal should contain "[2013-11-30 15:42] Project Started."
|
|
||||||
|
|
||||||
Scenario: Dates can be in the future
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/185
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl 26/06/2099: Planet? Earth. Year? 2099."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
And the journal should contain "[2099-06-26 09:00] Planet?"
|
|
||||||
|
|
||||||
Scenario: Loading a sample journal with custom date
|
|
||||||
Given we use the config "little_endian_dates.yaml"
|
|
||||||
When we run "jrnl -n 2"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
09.06.2013 15:39 My first entry.
|
|
||||||
| Everything is alright
|
|
||||||
|
|
||||||
10.07.2013 15:40 Life is good.
|
|
||||||
| But I'm better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario Outline: Writing an entry from command line with custom date
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl <input>"
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -n 1"
|
|
||||||
Then the output should contain "<output>"
|
|
||||||
|
|
||||||
Examples: Day-first Dates
|
|
||||||
| config | input | output |
|
|
||||||
| little_endian_dates | 2020-09-19: My first entry. | 19.09.2020 09:00 My first entry. |
|
|
||||||
| little_endian_dates | 2020-08-09: My second entry. | 09.08.2020 09:00 My second entry. |
|
|
||||||
| little_endian_dates | 2020-02-29: Test. | 29.02.2020 09:00 Test. |
|
|
||||||
| little_endian_dates | 2019-02-29: Test. | 2019-02-29: Test. |
|
|
||||||
| little_endian_dates | 2020-08-32: Test. | 2020-08-32: Test. |
|
|
||||||
| little_endian_dates | 2032-02-01: Test. | 01.02.2032 09:00 Test. |
|
|
||||||
| little_endian_dates | 2020-01-01: Test. | 01.01.2020 09:00 Test. |
|
|
||||||
| little_endian_dates | 2020-12-31: Test. | 31.12.2020 09:00 Test. |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for dates with custom date
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -on '<input>' --short"
|
|
||||||
Then the output should be "<output>"
|
|
||||||
|
|
||||||
Examples: Day-first Dates
|
|
||||||
| config | input | output |
|
|
||||||
| little_endian_dates | 2013-07-10 | 10.07.2013 15:40 Life is good. |
|
|
||||||
| little_endian_dates | june 9 2013 | 09.06.2013 15:39 My first entry. |
|
|
||||||
| little_endian_dates | july 10 2013 | 10.07.2013 15:40 Life is good. |
|
|
||||||
| little_endian_dates | june 2013 | 09.06.2013 15:39 My first entry. |
|
|
||||||
| little_endian_dates | july 2013 | 10.07.2013 15:40 Life is good. |
|
|
||||||
# @todo month alone with no year should work
|
|
||||||
# | little_endian_dates | june | 09.06.2013 15:39 My first entry. |
|
|
||||||
# | little_endian_dates | july | 10.07.2013 15:40 Life is good. |
|
|
||||||
|
|
||||||
Scenario: Writing an entry at the prompt with custom date
|
|
||||||
Given we use the config "little_endian_dates.yaml"
|
|
||||||
When we run "jrnl" and enter "2013-05-10: I saw Elvis. He's alive."
|
|
||||||
Then we should get no error
|
|
||||||
And the journal should contain "[10.05.2013 09:00] I saw Elvis."
|
|
||||||
And the journal should contain "He's alive."
|
|
||||||
|
|
||||||
Scenario: Viewing today's entries does not print the entire journal
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/741
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl -on today"
|
|
||||||
Then the output should not contain "Life is good"
|
|
||||||
And the output should not contain "But I'm better."
|
|
||||||
|
|
||||||
Scenario Outline: Create entry using day of the week as entry date.
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl <day>: This is an entry on a <day>."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -1"
|
|
||||||
Then the output should contain "<day> at 9am" in the local time
|
|
||||||
And the output should contain "This is an entry on a <day>."
|
|
||||||
|
|
||||||
Examples: Days of the week
|
|
||||||
| day |
|
|
||||||
| Monday |
|
|
||||||
| Tuesday |
|
|
||||||
| Wednesday |
|
|
||||||
| Thursday |
|
|
||||||
| Friday |
|
|
||||||
| Saturday |
|
|
||||||
| Sunday |
|
|
||||||
| sunday |
|
|
||||||
| sUndAy |
|
|
||||||
|
|
||||||
Scenario Outline: Create entry using day of the week abbreviations as entry date.
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl <day>: This is an entry on a <weekday>."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -1"
|
|
||||||
Then the output should contain "<weekday> at 9am" in the local time
|
|
||||||
|
|
||||||
Examples: Days of the week
|
|
||||||
| day | weekday |
|
|
||||||
| mon | Monday |
|
|
||||||
| tue | Tuesday |
|
|
||||||
| wed | Wednesday |
|
|
||||||
| thu | Thursday |
|
|
||||||
| fri | Friday |
|
|
||||||
| sat | Saturday |
|
|
||||||
| sun | Sunday |
|
|
||||||
|
|
||||||
Scenario: Journals with unreadable dates should still be loaded
|
|
||||||
Given we use the config "unreadabledates.yaml"
|
|
||||||
When we run "jrnl -2"
|
|
||||||
Then the output should contain "I've lost track of time."
|
|
||||||
And the output should contain "Time has no meaning."
|
|
||||||
|
|
||||||
Scenario: Journals with readable dates AND unreadable dates should still contain all data.
|
|
||||||
Given we use the config "mostlyreadabledates.yaml"
|
|
||||||
When we run "jrnl -3"
|
|
||||||
Then the output should contain "Time machines are possible."
|
|
||||||
Then the output should contain "I'm going to activate the machine."
|
|
||||||
And the output should contain "I've crossed so many timelines. Is there any going back?"
|
|
||||||
And the journal should have 3 entries
|
|
||||||
|
|
||||||
Scenario: Update near-valid dates after journal is edited
|
|
||||||
Given we use the config "mostlyreadabledates.yaml"
|
|
||||||
When we run "jrnl 2222-08-19: I have made it exactly one month into the future."
|
|
||||||
Then the journal should contain "[2019-07-01 14:23] Entry subject"
|
|
||||||
|
|
||||||
Scenario: Integers in square brackets should not be read as dates
|
|
||||||
Given we use the config "brackets.yaml"
|
|
||||||
When we run "jrnl -1"
|
|
||||||
Then the output should contain "[1] line starting with 1"
|
|
||||||
|
|
||||||
# broken still
|
|
||||||
@skip
|
|
||||||
Scenario: Dayone entries without timezone information are interpreted in current timezone
|
|
||||||
Given we use the config "dayone.yaml"
|
|
||||||
When we run "jrnl -until 'feb 2013'"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should contain "2013-01-17T18:37Z" in the local time
|
|
||||||
|
|
||||||
Scenario: Loading entry with ambiguous time stamp in timezone-aware journal (like Dayone)
|
|
||||||
#https://github.com/jrnl-org/jrnl/issues/153
|
|
||||||
Given we use the config "bug153.yaml"
|
|
||||||
When we run "jrnl -1"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
2013-10-27 03:27 Some text.
|
|
||||||
"""
|
|
|
@ -1,229 +0,0 @@
|
||||||
Feature: Delete entries from journal
|
|
||||||
Scenario Outline: Delete flag allows deletion of single entry
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -1"
|
|
||||||
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
|
||||||
When we run "jrnl --delete" and enter
|
|
||||||
"""
|
|
||||||
N
|
|
||||||
N
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Backing out of interactive delete does not change journal
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -n 1" and enter
|
|
||||||
"""
|
|
||||||
N
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with nonsense input deletes nothing (issue #932)
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete asdfasdf"
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with tag only deletes tagged entries
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete @ipsum" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with multiple tags deletes all entries matching any of the tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete @ipsum @tagthree" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -and deletes boolean AND of tagged entries
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -and @tagone @tagtwo" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -not does not delete entries from given tag
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete @tagone -not @ipsum" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -from search operator only deletes entries since that date
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -from 2020-09-01" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -to only deletes entries up to specified date
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -to 2020-08-31" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -starred only deletes starred entries
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -starred" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Delete flag with -contains only entries containing expression
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --delete -contains dignissim" and enter
|
|
||||||
"""
|
|
||||||
Y
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
Feature: Encrypting and decrypting journals
|
|
||||||
|
|
||||||
Scenario: Decrypting a journal
|
|
||||||
Given we use the config "encrypted.yaml"
|
|
||||||
When we run "jrnl --decrypt" and enter "bad doggie no biscuit"
|
|
||||||
Then the config for journal "default" should have "encrypt" set to "bool:False"
|
|
||||||
And we should see the message "Journal decrypted"
|
|
||||||
And the journal should have 2 entries
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Trying to decrypt an already unencrypted journal
|
|
||||||
# This should warn the user that the journal is already encrypted
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --decrypt"
|
|
||||||
Then the config for journal "default" should have "encrypt" set to "bool:False"
|
|
||||||
And the journal should have 2 entries
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Trying to encrypt an already encrypted journal
|
|
||||||
# This should warn the user that the journal is already encrypted
|
|
||||||
|
|
||||||
Scenario: Encrypting a journal
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
swordfish
|
|
||||||
swordfish
|
|
||||||
n
|
|
||||||
"""
|
|
||||||
Then we should see the message "Journal encrypted"
|
|
||||||
And the config for journal "default" should have "encrypt" set to "bool:True"
|
|
||||||
When we run "jrnl -n 1" and enter "swordfish"
|
|
||||||
Then we should be prompted for a password
|
|
||||||
And the output should contain "2013-06-10 15:40 Life is good"
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
from jrnl.os_compat import on_windows
|
|
||||||
|
|
||||||
CWD = os.getcwd()
|
|
||||||
|
|
||||||
# @see https://behave.readthedocs.io/en/latest/tutorial.html#debug-on-error-in-case-of-step-failures
|
|
||||||
BEHAVE_DEBUG_ON_ERROR = False
|
|
||||||
|
|
||||||
|
|
||||||
def setup_debug_on_error(userdata):
|
|
||||||
global BEHAVE_DEBUG_ON_ERROR
|
|
||||||
BEHAVE_DEBUG_ON_ERROR = userdata.getbool("BEHAVE_DEBUG_ON_ERROR")
|
|
||||||
|
|
||||||
|
|
||||||
def before_all(context):
|
|
||||||
setup_debug_on_error(context.config.userdata)
|
|
||||||
|
|
||||||
|
|
||||||
# def after_step(context, step):
|
|
||||||
# if BEHAVE_DEBUG_ON_ERROR and step.status == "failed":
|
|
||||||
# -- ENTER DEBUGGER: Zoom in on failure location.
|
|
||||||
# NOTE: Use IPython debugger, same for pdb (basic python debugger).
|
|
||||||
# import ipdb
|
|
||||||
# ipdb.post_mortem(step.exc_traceback)
|
|
||||||
|
|
||||||
|
|
||||||
def clean_all_working_dirs():
|
|
||||||
if os.path.exists("test.txt"):
|
|
||||||
os.remove("test.txt")
|
|
||||||
for folder in ("configs", "journals", "cache"):
|
|
||||||
working_dir = os.path.join("features", folder)
|
|
||||||
if os.path.exists(working_dir):
|
|
||||||
shutil.rmtree(working_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def before_feature(context, feature):
|
|
||||||
# add "skip" tag
|
|
||||||
# https://stackoverflow.com/a/42721605/4276230
|
|
||||||
if "skip" in feature.tags:
|
|
||||||
feature.skip()
|
|
||||||
return
|
|
||||||
|
|
||||||
if "skip_win" in feature.tags and on_windows():
|
|
||||||
feature.skip("Skipping on Windows")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def before_scenario(context, scenario):
|
|
||||||
"""Before each scenario, backup all config and journal test data."""
|
|
||||||
# Clean up in case something went wrong
|
|
||||||
clean_all_working_dirs()
|
|
||||||
for folder in ("configs", "journals"):
|
|
||||||
original = os.path.join("features", "data", folder)
|
|
||||||
working_dir = os.path.join("features", folder)
|
|
||||||
if not os.path.exists(working_dir):
|
|
||||||
os.mkdir(working_dir)
|
|
||||||
for filename in os.listdir(original):
|
|
||||||
source = os.path.join(original, filename)
|
|
||||||
if os.path.isdir(source):
|
|
||||||
shutil.copytree(source, os.path.join(working_dir, filename))
|
|
||||||
else:
|
|
||||||
shutil.copy2(source, working_dir)
|
|
||||||
|
|
||||||
# add "skip" tag
|
|
||||||
# https://stackoverflow.com/a/42721605/4276230
|
|
||||||
if "skip" in scenario.effective_tags:
|
|
||||||
scenario.skip()
|
|
||||||
return
|
|
||||||
|
|
||||||
if "skip_win" in scenario.effective_tags and on_windows():
|
|
||||||
scenario.skip("Skipping on Windows")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def after_scenario(context, scenario):
|
|
||||||
"""After each scenario, restore all test data and remove working_dirs."""
|
|
||||||
if os.getcwd() != CWD:
|
|
||||||
os.chdir(CWD)
|
|
||||||
|
|
||||||
# only clean up if debugging is off and the scenario passed
|
|
||||||
if BEHAVE_DEBUG_ON_ERROR and scenario.status != "failed":
|
|
||||||
clean_all_working_dirs()
|
|
||||||
else:
|
|
||||||
clean_all_working_dirs()
|
|
|
@ -1,56 +0,0 @@
|
||||||
Feature: Journals iteracting with the file system in a way that users can see
|
|
||||||
|
|
||||||
Scenario: Adding entries to a Folder journal should generate date files
|
|
||||||
Given we use the config "empty_folder.yaml"
|
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When the journal directory is listed
|
|
||||||
Then the output should contain "2013/07/23.txt" or "2013\07\23.txt"
|
|
||||||
|
|
||||||
Scenario: Adding multiple entries to a Folder journal should generate multiple date files
|
|
||||||
Given we use the config "empty_folder.yaml"
|
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
|
||||||
And we run "jrnl 3/7/2014: Second entry of journal."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When the journal directory is listed
|
|
||||||
Then the output should contain "2013/07/23.txt" or "2013\07\23.txt"
|
|
||||||
Then the output should contain "2014/03/07.txt" or "2014\03\07.txt"
|
|
||||||
|
|
||||||
Scenario: If the journal and its parent directory don't exist, they should be created
|
|
||||||
Given we use the config "missing_directory.yaml"
|
|
||||||
Then the journal should not exist
|
|
||||||
When we run "jrnl This is a new entry in my journal"
|
|
||||||
Then the journal should exist
|
|
||||||
When we run "jrnl -n 1"
|
|
||||||
Then the output should contain "This is a new entry in my journal"
|
|
||||||
And the journal should have 1 entry
|
|
||||||
|
|
||||||
Scenario: If the journal file doesn't exist, then it should be created
|
|
||||||
Given we use the config "missing_journal.yaml"
|
|
||||||
Then the journal should not exist
|
|
||||||
When we run "jrnl This is a new entry in my journal"
|
|
||||||
Then the journal should exist
|
|
||||||
When we run "jrnl -n 1"
|
|
||||||
Then the output should contain "This is a new entry in my journal"
|
|
||||||
And the journal should have 1 entry
|
|
||||||
|
|
||||||
Scenario: Creating journal with relative path should update to absolute path
|
|
||||||
Given we use the config "missingconfig"
|
|
||||||
When we run "jrnl hello world" and enter
|
|
||||||
"""
|
|
||||||
test.txt
|
|
||||||
n
|
|
||||||
"""
|
|
||||||
And we change directory to "features"
|
|
||||||
And we run "jrnl -n 1"
|
|
||||||
Then the output should contain "hello world"
|
|
||||||
|
|
||||||
Scenario: the temporary filename suffix should default to ".jrnl"
|
|
||||||
Given we use the config "editor.yaml"
|
|
||||||
When we run "jrnl --edit"
|
|
||||||
Then the temporary filename suffix should be ".jrnl"
|
|
||||||
|
|
||||||
Scenario: the temporary filename suffix should be "-{template_filename}"
|
|
||||||
Given we use the config "editor_markdown_extension.yaml"
|
|
||||||
When we run "jrnl --edit"
|
|
||||||
Then the temporary filename suffix should be "-extension.md"
|
|
|
@ -1,621 +0,0 @@
|
||||||
Feature: Custom formats
|
|
||||||
|
|
||||||
Scenario Outline: Short printing via --format flag
|
|
||||||
Given We use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --format short -3"
|
|
||||||
Then we should get no error
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Pretty Printing aka the Default
|
|
||||||
Given We use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --format pretty -3"
|
|
||||||
Then we should get no error
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: JSON format
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --format json"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be parsable as json
|
|
||||||
And "entries" in the json output should have 3 elements
|
|
||||||
And "tags" in the json output should contain "@ipsum"
|
|
||||||
And "tags" in the json output should contain "@tagone"
|
|
||||||
And "tags" in the json output should contain "@tagthree"
|
|
||||||
And "tags" in the json output should contain "@tagtwo"
|
|
||||||
And entry 1 should have an array "tags" with 3 elements
|
|
||||||
And entry 2 should have an array "tags" with 1 elements
|
|
||||||
And entry 3 should have an array "tags" with 2 elements
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario: Exporting dayone to json
|
|
||||||
Given we use the config "dayone.yaml"
|
|
||||||
When we run "jrnl --export json"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be parsable as json
|
|
||||||
And the json output should contain entries.0.uuid = "4BB1F46946AD439996C9B59DE7C4DDC1"
|
|
||||||
|
|
||||||
Scenario Outline: Printing a journal that has multiline entries with tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -n 1 @ipsum"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
| Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
| quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus
|
|
||||||
| pellentesque
|
|
||||||
| augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu
|
|
||||||
| consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In
|
|
||||||
| commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget
|
|
||||||
| venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo.
|
|
||||||
|
|
|
||||||
| Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo
|
|
||||||
| ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse
|
|
||||||
| potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget
|
|
||||||
| molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed lectus
|
|
||||||
| hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis
|
|
||||||
| feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, vestibulum
|
|
||||||
| urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod enim.
|
|
||||||
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget
|
|
||||||
| velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac
|
|
||||||
| porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per
|
|
||||||
| conubia nostra, per inceptos himenaeos.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Exporting using filters should only export parts of the journal
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -until 'August 2020' --format json"
|
|
||||||
Then the output should be parsable as json
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be parsable as json
|
|
||||||
And "entries" in the json output should have 2 elements
|
|
||||||
And "tags" in the json output should contain "@ipsum"
|
|
||||||
And "tags" in the json output should contain "@tagone"
|
|
||||||
And "tags" in the json output should contain "@tagtwo"
|
|
||||||
And entry 1 should have an array "tags" with 3 elements
|
|
||||||
And entry 2 should have an array "tags" with 1 elements
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Exporting using custom templates
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we load template "sample.template"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -1 --format sample"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
The third entry finally after weeks without writing.
|
|
||||||
----------------------------------------------------
|
|
||||||
|
|
||||||
I'm so excited about emojis. 💯 🎶 💩
|
|
||||||
|
|
||||||
Donec semper pellentesque iaculis. Nullam cursus et justo sit amet venenatis.
|
|
||||||
Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. Nulla
|
|
||||||
eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis
|
|
||||||
dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh malesuada.
|
|
||||||
Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis
|
|
||||||
vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo.
|
|
||||||
Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at
|
|
||||||
ante eget fringilla. @tagthree and also @tagone
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Increasing Headings on Markdown export
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we open the editor and append
|
|
||||||
"""
|
|
||||||
[2020-10-14 13:23] Heading Test
|
|
||||||
|
|
||||||
H1-1
|
|
||||||
=
|
|
||||||
|
|
||||||
H1-2
|
|
||||||
===
|
|
||||||
|
|
||||||
H1-3
|
|
||||||
============================
|
|
||||||
|
|
||||||
H2-1
|
|
||||||
-
|
|
||||||
|
|
||||||
H2-2
|
|
||||||
---
|
|
||||||
|
|
||||||
H2-3
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
Horizontal Rules (ignore)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
===
|
|
||||||
|
|
||||||
# ATX H1
|
|
||||||
|
|
||||||
## ATX H2
|
|
||||||
|
|
||||||
### ATX H3
|
|
||||||
|
|
||||||
#### ATX H4
|
|
||||||
|
|
||||||
##### ATX H5
|
|
||||||
|
|
||||||
###### ATX H6
|
|
||||||
|
|
||||||
Stuff
|
|
||||||
|
|
||||||
More stuff
|
|
||||||
more stuff again
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -1 --export markdown"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
# 2020
|
|
||||||
|
|
||||||
## October
|
|
||||||
|
|
||||||
### 2020-10-14 13:23 Heading Test
|
|
||||||
|
|
||||||
#### H1-1
|
|
||||||
|
|
||||||
#### H1-2
|
|
||||||
|
|
||||||
#### H1-3
|
|
||||||
|
|
||||||
##### H2-1
|
|
||||||
|
|
||||||
##### H2-2
|
|
||||||
|
|
||||||
##### H2-3
|
|
||||||
|
|
||||||
Horizontal Rules (ignore)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
===
|
|
||||||
|
|
||||||
#### ATX H1
|
|
||||||
|
|
||||||
##### ATX H2
|
|
||||||
|
|
||||||
###### ATX H3
|
|
||||||
|
|
||||||
####### ATX H4
|
|
||||||
|
|
||||||
######## ATX H5
|
|
||||||
|
|
||||||
######### ATX H6
|
|
||||||
|
|
||||||
Stuff
|
|
||||||
|
|
||||||
More stuff
|
|
||||||
more stuff again
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: Add a blank line to Markdown export if there isn't one already
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/768
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/881
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we open the editor and append
|
|
||||||
"""
|
|
||||||
[2020-10-29 11:11] First entry.
|
|
||||||
[2020-10-29 11:11] Second entry.
|
|
||||||
[2020-10-29 11:13] Third entry.
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -3 --format markdown"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
# 2020
|
|
||||||
|
|
||||||
## October
|
|
||||||
|
|
||||||
### 2020-10-29 11:11 First entry.
|
|
||||||
|
|
||||||
|
|
||||||
### 2020-10-29 11:11 Second entry.
|
|
||||||
|
|
||||||
|
|
||||||
### 2020-10-29 11:13 Third entry.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
@skip
|
|
||||||
Scenario Outline: Exporting to XML
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --export xml"
|
|
||||||
Then the output should be a valid XML string
|
|
||||||
And "entries" node in the xml output should have 3 elements
|
|
||||||
And "tags" in the xml output should contain ["@ipsum", "@tagone", "@tagtwo", "@tagthree"]
|
|
||||||
And there should be 10 "tag" elements
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
# | basic_onefile | @todo
|
|
||||||
# | basic_encrypted | @todo
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario: Exporting to XML
|
|
||||||
Given we use the config "tags.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --export xml"
|
|
||||||
Then the output should be a valid XML string
|
|
||||||
And "entries" node in the xml output should have 2 elements
|
|
||||||
And "tags" in the xml output should contain ["@idea", "@journal", "@dan"]
|
|
||||||
And there should be 7 "tag" elements
|
|
||||||
|
|
||||||
Scenario Outline: Exporting tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --export tags"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
@tagtwo : 2
|
|
||||||
@tagone : 2
|
|
||||||
@tagthree : 1
|
|
||||||
@ipsum : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Export fancy with small linewrap
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --config-override linewrap 35 --format fancy -3"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be 35 columns wide
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario Outline: Exporting fancy
|
|
||||||
# Needs better emoji support
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --export fancy"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
┎──────────────────────────────────────────────────────────────╮2020-08-29 11:11
|
|
||||||
┃ Entry the first. ╘═══════════════╕
|
|
||||||
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
|
|
||||||
┃ Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada │
|
|
||||||
┃ quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus │
|
|
||||||
┃ pellentesque │
|
|
||||||
┃ augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu │
|
|
||||||
┃ consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In │
|
|
||||||
┃ commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget │
|
|
||||||
┃ venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo. │
|
|
||||||
┃ │
|
|
||||||
┃ Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo │
|
|
||||||
┃ ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. │
|
|
||||||
┃ Suspendisse │
|
|
||||||
┃ potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas │
|
|
||||||
┃ eget │
|
|
||||||
┃ molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed │
|
|
||||||
┃ lectus │
|
|
||||||
┃ hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis │
|
|
||||||
┃ feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, │
|
|
||||||
┃ vestibulum │
|
|
||||||
┃ urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod │
|
|
||||||
┃ enim. │
|
|
||||||
┃ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget │
|
|
||||||
┃ velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac │
|
|
||||||
┃ porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per │
|
|
||||||
┃ conubia nostra, per inceptos himenaeos. │
|
|
||||||
┖──────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
┎──────────────────────────────────────────────────────────────╮2020-08-31 14:32
|
|
||||||
┃ A second entry in what I hope to be a long series. ╘═══════════════╕
|
|
||||||
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
|
|
||||||
┃ Sed sit amet metus et sapien feugiat elementum. Aliquam bibendum lobortis │
|
|
||||||
┃ leo │
|
|
||||||
┃ vitae tempus. Donec eleifend nec mi non volutpat. Lorem ipsum dolor sit │
|
|
||||||
┃ amet, │
|
|
||||||
┃ consectetur adipiscing elit. Praesent ut sodales libero. Maecenas nisl │
|
|
||||||
┃ lorem, │
|
|
||||||
┃ vestibulum in tempus sit amet, fermentum ut arcu. Donec vel vestibulum │
|
|
||||||
┃ lectus, │
|
|
||||||
┃ eget pretium enim. Maecenas diam nunc, imperdiet vitae pharetra sed, pretium │
|
|
||||||
┃ id │
|
|
||||||
┃ lectus. Donec eu metus et turpis tempor tristique ac non ex. In tellus arcu, │
|
|
||||||
┃ egestas at efficitur et, ultrices vel est. Sed commodo et nibh non │
|
|
||||||
┃ elementum. │
|
|
||||||
┃ Mauris tempus vitae neque vel viverra. @tagtwo all by its lonesome. │
|
|
||||||
┃ │
|
|
||||||
┃ Nulla mattis elementum magna, viverra pretium dui fermentum et. Cras vel │
|
|
||||||
┃ vestibulum odio. Quisque sit amet turpis et urna finibus maximus. Interdum │
|
|
||||||
┃ et │
|
|
||||||
┃ malesuada fames ac ante ipsum primis in faucibus. Fusce porttitor iaculis │
|
|
||||||
┃ sem, │
|
|
||||||
┃ non dictum ipsum varius nec. Nulla eu erat at risus gravida blandit non vel │
|
|
||||||
┃ ante. Nam egestas ipsum leo, eu ultricies ipsum tincidunt vel. Morbi a │
|
|
||||||
┃ commodo │
|
|
||||||
┃ eros. │
|
|
||||||
┃ │
|
|
||||||
┃ Nullam dictum, nisl ac varius tempus, ex tortor fermentum nisl, non │
|
|
||||||
┃ tempus dolor neque a lorem. Suspendisse a faucibus ex, vel ornare tortor. │
|
|
||||||
┃ Maecenas tincidunt id felis quis semper. Pellentesque enim libero, fermentum │
|
|
||||||
┃ quis metus id, rhoncus euismod magna. Nulla finibus velit eu purus bibendum │
|
|
||||||
┃ interdum. Integer id justo dui. Integer eu tellus in turpis bibendum │
|
|
||||||
┃ blandit. │
|
|
||||||
┃ Quisque auctor lacinia consectetur. │
|
|
||||||
┖──────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
┎──────────────────────────────────────────────────────────────╮2020-09-24 09:14
|
|
||||||
┃ The third entry finally after weeks without writing. ╘═══════════════╕
|
|
||||||
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
|
|
||||||
┃ I'm so excited about emojis. 💯 🎶 💩 │
|
|
||||||
┃ │
|
|
||||||
┃ Donec semper pellentesque iaculis. Nullam cursus et justo sit amet │
|
|
||||||
┃ venenatis. │
|
|
||||||
┃ Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. │
|
|
||||||
┃ Nulla │
|
|
||||||
┃ eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis │
|
|
||||||
┃ dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh │
|
|
||||||
┃ malesuada. │
|
|
||||||
┃ Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis │
|
|
||||||
┃ vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan │
|
|
||||||
┃ justo. │
|
|
||||||
┃ Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at │
|
|
||||||
┃ ante eget fringilla. @tagthree and also @tagone │
|
|
||||||
┖──────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
@skip_win
|
|
||||||
Scenario Outline: Export to yaml
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
And we create a cache directory
|
|
||||||
When we run "jrnl --export yaml -o {cache_dir}"
|
|
||||||
Then the cache should contain the files
|
|
||||||
"""
|
|
||||||
2020-08-29_entry-the-first.md
|
|
||||||
2020-08-31_a-second-entry-in-what-i-hope-to-be-a-long-series.md
|
|
||||||
2020-09-24_the-third-entry-finally-after-weeks-without-writing.md
|
|
||||||
"""
|
|
||||||
And the content of file "2020-08-29_entry-the-first.md" in the cache should be
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
title: Entry the first.
|
|
||||||
date: 2020-08-29 11:11
|
|
||||||
starred: False
|
|
||||||
tags: tagone, ipsum, tagtwo
|
|
||||||
body: |
|
|
||||||
Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada
|
|
||||||
quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque
|
|
||||||
augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu
|
|
||||||
consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In
|
|
||||||
commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget
|
|
||||||
venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo.
|
|
||||||
|
|
||||||
Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo
|
|
||||||
ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse
|
|
||||||
potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget
|
|
||||||
molestie metus. Mauris porttitor dui ornare gravida porta. Quisque sed lectus
|
|
||||||
hendrerit, lacinia ante eget, vulputate ante. Aliquam vitae erat non felis
|
|
||||||
feugiat sagittis. Phasellus quis arcu fringilla, mattis ligula id, vestibulum
|
|
||||||
urna. Vivamus facilisis leo a mi tincidunt condimentum. Donec eu euismod enim.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget
|
|
||||||
velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac
|
|
||||||
porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per
|
|
||||||
conubia nostra, per inceptos himenaeos.
|
|
||||||
...
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
# | basic_dayone |
|
|
||||||
|
|
||||||
@skip_win # @todo YAML exporter does not correctly export emoji on Windows
|
|
||||||
Scenario Outline: Add a blank line to YAML export if there isn't one already
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/768
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/881
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
And we create a cache directory
|
|
||||||
When we run "jrnl --export yaml -o {cache_dir}"
|
|
||||||
Then the cache should contain the files
|
|
||||||
"""
|
|
||||||
2020-08-29_entry-the-first.md
|
|
||||||
2020-08-31_a-second-entry-in-what-i-hope-to-be-a-long-series.md
|
|
||||||
2020-09-24_the-third-entry-finally-after-weeks-without-writing.md
|
|
||||||
"""
|
|
||||||
And the content of file "2020-09-24_the-third-entry-finally-after-weeks-without-writing.md" in the cache should be
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
title: The third entry finally after weeks without writing.
|
|
||||||
date: 2020-09-24 09:14
|
|
||||||
starred: False
|
|
||||||
tags: tagone, tagthree
|
|
||||||
body: |
|
|
||||||
I'm so excited about emojis. 💯 🎶 💩
|
|
||||||
|
|
||||||
Donec semper pellentesque iaculis. Nullam cursus et justo sit amet venenatis.
|
|
||||||
Vivamus tempus ex dictum metus vehicula gravida. Aliquam sed sem dolor. Nulla
|
|
||||||
eget ultrices purus. Quisque at nunc at quam pharetra consectetur vitae quis
|
|
||||||
dolor. Fusce ultricies purus eu est feugiat, quis scelerisque nibh malesuada.
|
|
||||||
Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis
|
|
||||||
vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo.
|
|
||||||
Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at
|
|
||||||
ante eget fringilla. @tagthree and also @tagone
|
|
||||||
...
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario: Empty DayOne entry bodies should not error
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/780
|
|
||||||
Given we use the config "bug780.yaml"
|
|
||||||
When we run "jrnl --short"
|
|
||||||
Then we should get no error
|
|
||||||
|
|
||||||
Scenario Outline: --short displays the short version of entries (only the title)
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -on 2020-08-31 --short"
|
|
||||||
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: -s displays the short version of entries (only the title)
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -on 2020-08-31 -s"
|
|
||||||
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario: Markdown Support from config file
|
|
||||||
Given we use the config "format_md.yaml"
|
|
||||||
When we run "jrnl -n 1"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
# 2013
|
|
||||||
|
|
||||||
## June
|
|
||||||
|
|
||||||
### 2013-06-10 15:40 Life is good.
|
|
||||||
|
|
||||||
But I'm better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Text Formatter from config file
|
|
||||||
Given we use the config "format_text.yaml"
|
|
||||||
When we run "jrnl -n 1"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
[2013-06-10 15:40] Life is good.
|
|
||||||
But I'm better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario Outline: Exporting entries with Cyrillic characters to directory should not fail
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
And we create a cache directory
|
|
||||||
When we run "jrnl 2020-11-21: Первая"
|
|
||||||
When we run "jrnl --format md --file {cache_dir} -on 2020-11-21"
|
|
||||||
Then the cache should contain the files
|
|
||||||
"""
|
|
||||||
2020-11-21_первая.md
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Export date counts
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl 2020-08-31 01:01: Hi."
|
|
||||||
And we run "jrnl --format dates"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29, 1
|
|
||||||
2020-08-31, 2
|
|
||||||
2020-09-24, 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
|
@ -1,93 +0,0 @@
|
||||||
Feature: Importing data
|
|
||||||
|
|
||||||
Scenario Outline: --import allows new entry from stdin
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --import" and pipe "[2020-07-05 15:00] Observe and import."
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -c import"
|
|
||||||
Then the output should contain "Observe and import"
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: --import allows new large entry from stdin
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --import" and pipe
|
|
||||||
"""
|
|
||||||
[2020-07-05 15:00] Observe and import.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada quis
|
|
||||||
est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus pellentesque augue
|
|
||||||
et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu consequat.
|
|
||||||
Aenean ante ex, elementum ut interdum et, mattis eget lacus. In commodo nulla nec
|
|
||||||
tellus placerat, sed ultricies metus bibendum. Duis eget venenatis erat. In at
|
|
||||||
dolor dui end of entry.
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -on 2020-07-05"
|
|
||||||
Then the output should contain "2020-07-05 15:00 Observe and import."
|
|
||||||
And the output should contain "Lorem ipsum"
|
|
||||||
And the output should contain "end of entry."
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario Outline: --import allows multiple new entries from stdin
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --import" and pipe
|
|
||||||
"""
|
|
||||||
[2020-07-05 15:00] Observe and import.
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
||||||
|
|
||||||
[2020-07-05 15:01] Twice as nice.
|
|
||||||
Sed dignissim sed nisl eu consequat.
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -on 2020-07-05"
|
|
||||||
Then the output should contain "2020-07-05 15:00 Observe and import."
|
|
||||||
And the output should contain "Lorem ipsum"
|
|
||||||
And the output should contain "2020-07-05 15:01 Twice as nice."
|
|
||||||
And the output should contain "Sed dignissim"
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
# | basic_folder | @todo
|
|
||||||
# | basic_dayone | @todo
|
|
||||||
|
|
||||||
Scenario: --import allows import new entries from file
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
Then the journal should contain "My first entry."
|
|
||||||
And the journal should contain "Life is good."
|
|
||||||
But the journal should not contain "I have an @idea"
|
|
||||||
And the journal should not contain "I met with"
|
|
||||||
When we run "jrnl --import --file features/journals/tags.journal"
|
|
||||||
Then the journal should contain "My first entry."
|
|
||||||
And the journal should contain "Life is good."
|
|
||||||
And the journal should contain "PROFIT!"
|
|
||||||
|
|
||||||
Scenario: --import prioritizes --file over pipe data if both are given
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
Then the journal should contain "My first entry."
|
|
||||||
And the journal should contain "Life is good."
|
|
||||||
But the journal should not contain "I have an @idea"
|
|
||||||
And the journal should not contain "I met with"
|
|
||||||
When we run "jrnl --import --file features/journals/tags.journal" and pipe
|
|
||||||
"""
|
|
||||||
[2020-07-05 15:00] I should not exist!
|
|
||||||
"""
|
|
||||||
Then the journal should contain "My first entry."
|
|
||||||
And the journal should contain "PROFIT!"
|
|
||||||
But the journal should not contain "I should not exist!"
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
Feature: Multiple journals
|
|
||||||
|
|
||||||
Scenario: Loading a config with two journals
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
Then journal "default" should have 2 entries
|
|
||||||
And journal "work" should have 0 entries
|
|
||||||
|
|
||||||
Scenario: Write to default config by default
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl this goes to default"
|
|
||||||
Then journal "default" should have 3 entries
|
|
||||||
And journal "work" should have 0 entries
|
|
||||||
|
|
||||||
Scenario: Write to specified journal
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl work a long day in the office"
|
|
||||||
Then journal "default" should have 2 entries
|
|
||||||
And journal "work" should have 1 entry
|
|
||||||
|
|
||||||
Scenario: Tell user which journal was used
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl work a long day in the office"
|
|
||||||
Then we should see the message "Entry added to work journal"
|
|
||||||
|
|
||||||
Scenario: Write to specified journal with a timestamp
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl work 23 july 2012: a long day in the office"
|
|
||||||
Then journal "default" should have 2 entries
|
|
||||||
And journal "work" should have 1 entry
|
|
||||||
And journal "work" should contain "2012-07-23"
|
|
||||||
|
|
||||||
Scenario: Write to specified journal without a timestamp but with colon
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl work : a long day in the office"
|
|
||||||
Then journal "default" should have 2 entries
|
|
||||||
And journal "work" should have 1 entry
|
|
||||||
And journal "work" should contain "a long day in the office"
|
|
||||||
|
|
||||||
Scenario: Write to specified journal without a timestamp but with colon
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl work: a long day in the office"
|
|
||||||
Then journal "default" should have 2 entries
|
|
||||||
And journal "work" should have 1 entry
|
|
||||||
And journal "work" should contain "a long day in the office"
|
|
||||||
|
|
||||||
Scenario: Create new journals as required
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
Then journal "ideas" should not exist
|
|
||||||
When we run "jrnl ideas 23 july 2012: sell my junk on ebay and make lots of money"
|
|
||||||
Then journal "ideas" should have 1 entry
|
|
||||||
|
|
||||||
Scenario: Don't crash if no default journal is specified
|
|
||||||
Given we use the config "bug343.yaml"
|
|
||||||
When we run "jrnl a long day in the office"
|
|
||||||
Then we should see the message "No default journal configured"
|
|
||||||
|
|
||||||
Scenario: Don't crash if no file exists for a configured encrypted journal
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
When we run "jrnl new_encrypted Adding first entry" and enter
|
|
||||||
"""
|
|
||||||
these three eyes
|
|
||||||
these three eyes
|
|
||||||
n
|
|
||||||
"""
|
|
||||||
Then we should see the message "Encrypted journal 'new_encrypted' created"
|
|
|
@ -1,98 +0,0 @@
|
||||||
Feature: Implementing Runtime Overrides for Select Configuration Keys
|
|
||||||
|
|
||||||
Scenario: Override configured editor with built-in input === editor:''
|
|
||||||
Given we use the config "basic_encrypted.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --config-override editor ''"
|
|
||||||
Then the stdin prompt should have been called
|
|
||||||
|
|
||||||
Scenario: Postconfig commands with overrides
|
|
||||||
Given We use the config "basic_encrypted.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --decrypt --config-override highlight false --config-override editor nano"
|
|
||||||
Then the config should have "highlight" set to "bool:false"
|
|
||||||
And no editor should have been called
|
|
||||||
|
|
||||||
Scenario: Override configured linewrap with a value of 23
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -2 --config-override linewrap 23 --format fancy"
|
|
||||||
Then the output should be
|
|
||||||
|
|
||||||
"""
|
|
||||||
┎─────╮2013-06-09 15:39
|
|
||||||
┃ My ╘═══════════════╕
|
|
||||||
┃ fir st ent ry. │
|
|
||||||
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
|
|
||||||
┃ Everything is │
|
|
||||||
┃ alright │
|
|
||||||
┖─────────────────────┘
|
|
||||||
┎─────╮2013-06-10 15:40
|
|
||||||
┃ Lif ╘═══════════════╕
|
|
||||||
┃ e is goo d. │
|
|
||||||
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
|
|
||||||
┃ But I'm better. │
|
|
||||||
┖─────────────────────┘
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Override color selections with runtime overrides
|
|
||||||
Given we use the config "basic_encrypted.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -1 --config-override colors.body blue"
|
|
||||||
Then the config should have "colors.body" set to "blue"
|
|
||||||
|
|
||||||
Scenario: Apply multiple config overrides
|
|
||||||
Given we use the config "basic_encrypted.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -1 --config-override colors.body green --config-override editor 'nano'"
|
|
||||||
Then the config should have "colors.body" set to "green"
|
|
||||||
And the config should have "editor" set to "nano"
|
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Override configured editor
|
|
||||||
Given we use the config "basic_encrypted.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --config-override editor '<editor>'"
|
|
||||||
Then the editor <editor> should have been called
|
|
||||||
Examples: Editor Commands
|
|
||||||
| editor |
|
|
||||||
| nano |
|
|
||||||
| vi -c startinsert |
|
|
||||||
| code -w |
|
|
||||||
|
|
||||||
Scenario: Override default journal
|
|
||||||
Given we use the config "basic_dayone.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --debug --config-override journals.default features/journals/simple.journal 20 Mar 2000: The rain in Spain comes from clouds"
|
|
||||||
Then we should get no error
|
|
||||||
And we should see the message "Entry added"
|
|
||||||
When we run "jrnl -3 --debug --config-override journals.default features/journals/simple.journal"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2000-03-20 09:00 The rain in Spain comes from clouds
|
|
||||||
|
|
||||||
2013-06-09 15:39 My first entry.
|
|
||||||
| Everything is alright
|
|
||||||
|
|
||||||
2013-06-10 15:40 Life is good.
|
|
||||||
| But I'm better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Make an entry into an overridden journal
|
|
||||||
Given we use the config "basic_dayone.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp Sep 06 1969: @say Ni"
|
|
||||||
Then we should get no error
|
|
||||||
And we should see the message "Entry added"
|
|
||||||
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp -3"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
1969-09-06 09:00 @say Ni
|
|
||||||
|
|
||||||
2013-06-09 15:39 My first entry.
|
|
||||||
| Everything is alright
|
|
||||||
|
|
||||||
2013-06-10 15:40 Life is good.
|
|
||||||
| But I'm better.
|
|
||||||
"""
|
|
|
@ -1,116 +0,0 @@
|
||||||
Feature: Using the installed keyring
|
|
||||||
|
|
||||||
Scenario: Storing a password in keyring
|
|
||||||
Given we use the config "multiple.yaml"
|
|
||||||
And we have a keyring
|
|
||||||
When we run "jrnl simple --encrypt" and enter
|
|
||||||
"""
|
|
||||||
sabertooth
|
|
||||||
sabertooth
|
|
||||||
y
|
|
||||||
"""
|
|
||||||
Then the config for journal "simple" should have "encrypt" set to "bool:True"
|
|
||||||
When we run "jrnl simple -n 1"
|
|
||||||
Then the output should contain "2013-06-10 15:40 Life is good"
|
|
||||||
|
|
||||||
Scenario: Encrypt journal with no keyring backend and do not store in keyring
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
And we do not have a keyring
|
|
||||||
When we run "jrnl test entry"
|
|
||||||
And we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
password
|
|
||||||
password
|
|
||||||
n
|
|
||||||
"""
|
|
||||||
Then we should get no error
|
|
||||||
And we should not see the message "Failed to retrieve keyring"
|
|
||||||
|
|
||||||
Scenario: Encrypt journal with no keyring backend and do store in keyring
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
And we do not have a keyring
|
|
||||||
When we run "jrnl test entry"
|
|
||||||
And we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
password
|
|
||||||
password
|
|
||||||
y
|
|
||||||
"""
|
|
||||||
Then we should get no error
|
|
||||||
And we should not see the message "Failed to retrieve keyring"
|
|
||||||
# @todo add step to check contents of keyring
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Open an encrypted journal with wrong password in keyring
|
|
||||||
# This should ask the user for the password after the keyring fails
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Decrypt journal with password in keyring
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Decrypt journal without a keyring
|
|
||||||
|
|
||||||
Scenario: Encrypt journal when keyring exists but fails
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
And we have a failed keyring
|
|
||||||
When we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
this password will not be saved in keyring
|
|
||||||
this password will not be saved in keyring
|
|
||||||
y
|
|
||||||
"""
|
|
||||||
Then we should see the message "Failed to retrieve keyring"
|
|
||||||
And we should get no error
|
|
||||||
And we should be prompted for a password
|
|
||||||
And the config for journal "default" should have "encrypt" set to "bool:True"
|
|
||||||
|
|
||||||
Scenario: Decrypt journal when keyring exists but fails
|
|
||||||
Given we use the config "encrypted.yaml"
|
|
||||||
And we have a failed keyring
|
|
||||||
When we run "jrnl --decrypt" and enter "bad doggie no biscuit"
|
|
||||||
Then we should see the message "Failed to retrieve keyring"
|
|
||||||
And we should get no error
|
|
||||||
And we should be prompted for a password
|
|
||||||
And we should see the message "Journal decrypted"
|
|
||||||
And the config for journal "default" should have "encrypt" set to "bool:False"
|
|
||||||
And the journal should have 2 entries
|
|
||||||
|
|
||||||
Scenario: Open encrypted journal when keyring exists but fails
|
|
||||||
# This should ask the user for the password after the keyring fails
|
|
||||||
Given we use the config "encrypted.yaml"
|
|
||||||
And we have a failed keyring
|
|
||||||
When we run "jrnl -n 1" and enter "bad doggie no biscuit"
|
|
||||||
Then we should see the message "Failed to retrieve keyring"
|
|
||||||
And we should get no error
|
|
||||||
And we should be prompted for a password
|
|
||||||
And the output should contain "2013-06-10 15:40 Life is good"
|
|
||||||
|
|
||||||
Scenario: Mistyping your password
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
swordfish
|
|
||||||
sordfish
|
|
||||||
"""
|
|
||||||
Then we should be prompted for a password
|
|
||||||
And we should see the message "Passwords did not match"
|
|
||||||
And the config for journal "default" should not have "encrypt" set
|
|
||||||
And the journal should have 2 entries
|
|
||||||
|
|
||||||
Scenario: Mistyping your password, then getting it right
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl --encrypt" and enter
|
|
||||||
"""
|
|
||||||
swordfish
|
|
||||||
sordfish
|
|
||||||
swordfish
|
|
||||||
swordfish
|
|
||||||
n
|
|
||||||
"""
|
|
||||||
Then we should be prompted for a password
|
|
||||||
And we should see the message "Passwords did not match"
|
|
||||||
And we should see the message "Journal encrypted"
|
|
||||||
And the config for journal "default" should have "encrypt" set to "bool:True"
|
|
||||||
When we run "jrnl -n 1" and enter "swordfish"
|
|
||||||
Then we should be prompted for a password
|
|
||||||
And the output should contain "2013-06-10 15:40 Life is good"
|
|
|
@ -1,318 +0,0 @@
|
||||||
Feature: Searching in a journal
|
|
||||||
|
|
||||||
Scenario Outline: Displaying entries using -on today should display entries created today
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl today: Adding an entry right now."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -on today"
|
|
||||||
Then the output should contain "Adding an entry right now."
|
|
||||||
But the output should not contain "Everything is alright"
|
|
||||||
And the output should not contain "Life is good"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| simple |
|
|
||||||
| empty_folder |
|
|
||||||
| dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Displaying entries using -from day should display correct entries
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl yesterday: This thing happened yesterday"
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl tomorrow: A future entry."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -from today"
|
|
||||||
Then the output should contain "Adding an entry right now."
|
|
||||||
And the output should contain "A future entry."
|
|
||||||
And the output should not contain "This thing happened yesterday"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| simple |
|
|
||||||
| empty_folder |
|
|
||||||
| dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Displaying entries using -from and -to day should display correct entries
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl yesterday: This thing happened yesterday"
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl tomorrow: A future entry."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -from yesterday -to today"
|
|
||||||
Then the output should contain "This thing happened yesterday"
|
|
||||||
And the output should contain "Adding an entry right now."
|
|
||||||
And the output should not contain "A future entry."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| simple |
|
|
||||||
| empty_folder |
|
|
||||||
| dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for a string
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -contains first --short"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
2020-08-29 11:11 Entry the first.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for a string within tag results
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl @tagone -contains maybe"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should contain "maybe"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for a string within AND tag results
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -and @tagone @tagtwo -contains maybe"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should contain "maybe"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for a string within NOT tag results
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -not @tagone -contains lonesome"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should contain "lonesome"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching for dates
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -on 2020-08-31 --short"
|
|
||||||
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl -on 'august 31 2020' --short"
|
|
||||||
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario: Out of order entries to a Folder journal should be listed in date order
|
|
||||||
Given we use the config "empty_folder.yaml"
|
|
||||||
When we run "jrnl 3/7/2014 4:37pm: Second entry of journal."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -2"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2013-07-23 09:00 Testing folder journal.
|
|
||||||
|
|
||||||
2014-03-07 16:37 Second entry of journal.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario Outline: Searching for all tags should show counts of each tag
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --tags"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
@tagtwo : 2
|
|
||||||
@tagone : 2
|
|
||||||
@tagthree : 1
|
|
||||||
@ipsum : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Filtering journals should also filter tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl -from 'september 2020' --tags"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
@tagthree : 1
|
|
||||||
@tagone : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Excluding a tag should filter out all entries with that tag
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --tags -not @tagtwo"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
@tagthree : 1
|
|
||||||
@tagone : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Excluding multiple tags should filter out all entries with those tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl --tags -not @tagone -not @tagthree"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
@tagtwo : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario: DayOne tag searching should work with tags containing a mixture of upper and lower case.
|
|
||||||
# https://github.com/jrnl-org/jrnl/issues/354
|
|
||||||
Given we use the config "dayone.yaml"
|
|
||||||
When we run "jrnl @plAy"
|
|
||||||
Then the output should contain "2013-05-17 11:39 This entry has tags!"
|
|
||||||
|
|
||||||
Scenario: Loading a sample journal
|
|
||||||
Given we use the config "simple.yaml"
|
|
||||||
When we run "jrnl -2"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
2013-06-09 15:39 My first entry.
|
|
||||||
| Everything is alright
|
|
||||||
|
|
||||||
2013-06-10 15:40 Life is good.
|
|
||||||
| But I'm better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario Outline: Searching by month
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -month 9 --short"
|
|
||||||
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -month Sept --short"
|
|
||||||
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -month September --short"
|
|
||||||
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching by day
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -day 31 --short"
|
|
||||||
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching by year
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl 2019-01-01 01:01: I like this year."
|
|
||||||
And we run "jrnl -year 2019 --short"
|
|
||||||
Then the output should be "2019-01-01 01:01 I like this year."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -year 19 --short"
|
|
||||||
Then the output should be "2019-01-01 01:01 I like this year."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Combining month, day, and year search terms
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl -month 08 -day 29 --short"
|
|
||||||
Then the output should be "2020-08-29 11:11 Entry the first."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -day 29 -year 2020 --short"
|
|
||||||
Then the output should be "2020-08-29 11:11 Entry the first."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -month 09 -year 2020 --short"
|
|
||||||
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
|
||||||
And we flush the output
|
|
||||||
When we run "jrnl -month 08 -day 29 -year 2020 --short"
|
|
||||||
Then the output should be "2020-08-29 11:11 Entry the first."
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Searching today in history
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
And we set current date and time to "2020-08-31 14:32"
|
|
||||||
When we run "jrnl 2019-08-31 01:01: Hi, from last year."
|
|
||||||
And we run "jrnl -today-in-history --short"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
2019-08-31 01:01 Hi, from last year.
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_encrypted |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario: Loading a DayOne Journal
|
|
||||||
Given we use the config "dayone.yaml"
|
|
||||||
When we run "jrnl -from 'feb 2013'"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
2013-05-17 11:39 This entry has tags!
|
|
||||||
|
|
||||||
2013-06-17 20:38 This entry has a location.
|
|
||||||
|
|
||||||
2013-07-17 11:38 This entry is starred!
|
|
||||||
"""
|
|
|
@ -1,35 +0,0 @@
|
||||||
Feature: Starring entries
|
|
||||||
|
|
||||||
Scenario Outline: Starring an entry will mark it in the journal file
|
|
||||||
Given we use the config "<config_file>.yaml"
|
|
||||||
When we run "jrnl 20 july 2013 *: Best day of my life!"
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -on 2013-07-20 -starred"
|
|
||||||
Then the output should contain "2013-07-20 09:00 Best day of my life!"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config_file |
|
|
||||||
| simple |
|
|
||||||
| empty_folder |
|
|
||||||
| dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Filtering by starred entries will show only starred entries
|
|
||||||
Given we use the config "<config_file>.yaml"
|
|
||||||
When we run "jrnl -starred"
|
|
||||||
Then the output should be empty
|
|
||||||
When we run "jrnl 20 july 2013 *: Best day of my life!"
|
|
||||||
When we run "jrnl -starred"
|
|
||||||
Then the output should be "2013-07-20 09:00 Best day of my life!"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config_file |
|
|
||||||
| simple |
|
|
||||||
| empty_folder |
|
|
||||||
| dayone_empty |
|
|
||||||
|
|
||||||
Scenario: Starring an entry will mark it in an encrypted journal
|
|
||||||
Given we use the config "encrypted.yaml"
|
|
||||||
When we run "jrnl 20 july 2013 *: Best day of my life!" and enter "bad doggie no biscuit"
|
|
||||||
Then we should see the message "Entry added"
|
|
||||||
When we run "jrnl -on 2013-07-20 -starred" and enter "bad doggie no biscuit"
|
|
||||||
Then the output should contain "2013-07-20 09:00 Best day of my life!"
|
|
|
@ -1,687 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
import ast
|
|
||||||
from collections import defaultdict
|
|
||||||
from jrnl.args import parse_args
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
import re
|
|
||||||
import time
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from behave import given
|
|
||||||
from behave import then
|
|
||||||
from behave import when
|
|
||||||
import keyring
|
|
||||||
|
|
||||||
import toml
|
|
||||||
import yaml
|
|
||||||
from yaml.loader import SafeLoader
|
|
||||||
|
|
||||||
|
|
||||||
import jrnl.time
|
|
||||||
from jrnl import Journal
|
|
||||||
from jrnl import __version__
|
|
||||||
from jrnl import plugins
|
|
||||||
from jrnl.cli import cli
|
|
||||||
from jrnl.config import load_config
|
|
||||||
from jrnl.os_compat import split_args
|
|
||||||
from jrnl.override import apply_overrides, _recursively_apply
|
|
||||||
|
|
||||||
try:
|
|
||||||
import parsedatetime.parsedatetime_consts as pdt
|
|
||||||
except ImportError:
|
|
||||||
import parsedatetime as pdt
|
|
||||||
|
|
||||||
consts = pdt.Constants(usePyICU=False)
|
|
||||||
consts.DOWParseStyle = -1 # Prefers past weekdays
|
|
||||||
CALENDAR = pdt.Calendar(consts)
|
|
||||||
|
|
||||||
|
|
||||||
class TestKeyring(keyring.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(keyring.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 keyring.errors.NoKeyringError
|
|
||||||
|
|
||||||
def get_password(self, servicename, username):
|
|
||||||
raise keyring.errors.NoKeyringError
|
|
||||||
|
|
||||||
def delete_password(self, servicename, username):
|
|
||||||
raise keyring.errors.NoKeyringError
|
|
||||||
|
|
||||||
|
|
||||||
class FailedKeyring(keyring.backend.KeyringBackend):
|
|
||||||
"""
|
|
||||||
A keyring that cannot be retrieved.
|
|
||||||
"""
|
|
||||||
|
|
||||||
priority = 2
|
|
||||||
|
|
||||||
def set_password(self, servicename, username, password):
|
|
||||||
raise keyring.errors.KeyringError
|
|
||||||
|
|
||||||
def get_password(self, servicename, username):
|
|
||||||
raise keyring.errors.KeyringError
|
|
||||||
|
|
||||||
def delete_password(self, servicename, username):
|
|
||||||
raise keyring.errors.KeyringError
|
|
||||||
|
|
||||||
|
|
||||||
# set a default keyring
|
|
||||||
keyring.set_keyring(TestKeyring())
|
|
||||||
|
|
||||||
|
|
||||||
def read_journal(context, journal_name="default"):
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
with open(configuration["journals"][journal_name]) as journal_file:
|
|
||||||
journal = journal_file.read()
|
|
||||||
return journal
|
|
||||||
|
|
||||||
|
|
||||||
def open_journal(context, journal_name="default"):
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
journal_conf = configuration["journals"][journal_name]
|
|
||||||
|
|
||||||
# We can override the default config on a by-journal basis
|
|
||||||
if type(journal_conf) is dict:
|
|
||||||
configuration.update(journal_conf)
|
|
||||||
# But also just give them a string to point to the journal file
|
|
||||||
else:
|
|
||||||
configuration["journal"] = journal_conf
|
|
||||||
|
|
||||||
return Journal.open_journal(journal_name, configuration)
|
|
||||||
|
|
||||||
|
|
||||||
def read_value_from_string(string):
|
|
||||||
if string[0] == "{":
|
|
||||||
# Handle value being a dictionary
|
|
||||||
return ast.literal_eval(string)
|
|
||||||
|
|
||||||
# Takes strings like "bool:true" or "int:32" and coerces them into proper type
|
|
||||||
string_parts = string.split(":")
|
|
||||||
if len(string_parts) > 1:
|
|
||||||
type = string_parts[0]
|
|
||||||
value = string_parts[1:][0] # rest of the text
|
|
||||||
value = {"bool": lambda v: v.lower() == "true", "int": int, "str": str}[type](
|
|
||||||
value
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
value = string_parts[0]
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
@given('we use the config "{config_file}"')
|
|
||||||
def set_config(context, config_file):
|
|
||||||
full_path = os.path.join("features/configs", config_file)
|
|
||||||
|
|
||||||
context.config_path = os.path.abspath(full_path)
|
|
||||||
|
|
||||||
if config_file.endswith("yaml") and os.path.exists(full_path):
|
|
||||||
# Add jrnl version to file for 2.x journals
|
|
||||||
with open(context.config_path, "a") as cf:
|
|
||||||
cf.write("version: {}".format(__version__))
|
|
||||||
|
|
||||||
|
|
||||||
@given('we use the password "{password}" if prompted')
|
|
||||||
def use_password_forever(context, password):
|
|
||||||
context.password = password
|
|
||||||
|
|
||||||
|
|
||||||
@given('we use the password "{password}" {num:d} times if prompted')
|
|
||||||
def use_password(context, password, num=1):
|
|
||||||
context.password = iter([password] * num)
|
|
||||||
|
|
||||||
|
|
||||||
@given("we have a keyring")
|
|
||||||
@given("we have a {type} keyring")
|
|
||||||
def set_keyring(context, type=""):
|
|
||||||
if type == "failed":
|
|
||||||
keyring.set_keyring(FailedKeyring())
|
|
||||||
else:
|
|
||||||
keyring.set_keyring(TestKeyring())
|
|
||||||
|
|
||||||
|
|
||||||
@given("we do not have a keyring")
|
|
||||||
def disable_keyring(context):
|
|
||||||
keyring.core.set_keyring(NoKeyring())
|
|
||||||
|
|
||||||
|
|
||||||
@given('we set current date and time to "{dt}"')
|
|
||||||
def set_datetime(context, dt):
|
|
||||||
context.now = dt
|
|
||||||
|
|
||||||
|
|
||||||
@when('we change directory to "{path}"')
|
|
||||||
def move_up_dir(context, path):
|
|
||||||
os.chdir(path)
|
|
||||||
|
|
||||||
|
|
||||||
@when("we open the editor and {method}")
|
|
||||||
@when('we open the editor and {method} "{text}"')
|
|
||||||
@when("we open the editor and {method} nothing")
|
|
||||||
@when("we open the editor and {method} nothing")
|
|
||||||
def open_editor_and_enter(context, method, text=""):
|
|
||||||
text = text or context.text or ""
|
|
||||||
|
|
||||||
if method == "enter":
|
|
||||||
file_method = "w+"
|
|
||||||
elif method == "append":
|
|
||||||
file_method = "a"
|
|
||||||
else:
|
|
||||||
file_method = "r+"
|
|
||||||
|
|
||||||
def _mock_editor(command):
|
|
||||||
context.editor_command = command
|
|
||||||
tmpfile = command[-1]
|
|
||||||
with open(tmpfile, file_method) as f:
|
|
||||||
f.write(text)
|
|
||||||
|
|
||||||
return tmpfile
|
|
||||||
|
|
||||||
if "password" in context:
|
|
||||||
password = context.password
|
|
||||||
else:
|
|
||||||
password = ""
|
|
||||||
|
|
||||||
# fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
with \
|
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
|
||||||
patch("sys.stdin.isatty", return_value=True), \
|
|
||||||
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
|
||||||
:
|
|
||||||
context.editor = mock_editor
|
|
||||||
context.getpass = mock_getpass
|
|
||||||
try:
|
|
||||||
cli(["--edit"])
|
|
||||||
context.exit_status = 0
|
|
||||||
except SystemExit as e:
|
|
||||||
context.exit_status = e.code
|
|
||||||
|
|
||||||
# fmt: on
|
|
||||||
|
|
||||||
|
|
||||||
@then("the editor should have been called")
|
|
||||||
@then("the editor should have been called with {num} arguments")
|
|
||||||
def count_editor_args(context, num=None):
|
|
||||||
assert context.editor.called
|
|
||||||
|
|
||||||
if isinstance(num, int):
|
|
||||||
assert len(context.editor_command) == int(num)
|
|
||||||
|
|
||||||
|
|
||||||
@then("the editor should not have been called")
|
|
||||||
def no_editor_called(context, num=None):
|
|
||||||
assert "editor" not in context or not context.editor.called
|
|
||||||
|
|
||||||
|
|
||||||
@then('one editor argument should be "{arg}"')
|
|
||||||
def contains_editor_arg(context, arg):
|
|
||||||
args = context.editor_command
|
|
||||||
assert (
|
|
||||||
arg in args and args.count(arg) == 1
|
|
||||||
), f"\narg not in args exactly 1 time:\n{arg}\n{str(args)}"
|
|
||||||
|
|
||||||
|
|
||||||
@then('one editor argument should match "{regex}"')
|
|
||||||
def matches_editor_arg(context, regex):
|
|
||||||
args = context.editor_command
|
|
||||||
matches = list(filter(lambda x: re.search(regex, x), args))
|
|
||||||
assert (
|
|
||||||
len(matches) == 1
|
|
||||||
), f"\nRegex didn't match exactly 1 time:\n{regex}\n{str(args)}"
|
|
||||||
|
|
||||||
|
|
||||||
@then("the editor file content should {method}")
|
|
||||||
@then("the editor file content should {method} empty")
|
|
||||||
@then('the editor file content should {method} "{text}"')
|
|
||||||
def contains_editor_file(context, method, text=""):
|
|
||||||
text = text or context.text or ""
|
|
||||||
content = context.editor_file.get("content")
|
|
||||||
format = f'\n"""\n{content}\n"""\n'
|
|
||||||
if method == "be":
|
|
||||||
assert content == text, format
|
|
||||||
elif method == "contain":
|
|
||||||
assert text in content, format
|
|
||||||
else:
|
|
||||||
assert False, f"Method '{method}' not supported"
|
|
||||||
|
|
||||||
|
|
||||||
@then('the temporary filename suffix should be "{suffix}"')
|
|
||||||
def extension_editor_file(context, suffix):
|
|
||||||
filename = Path(context.editor_file["name"]).name
|
|
||||||
delimiter = "-" if "-" in filename else "."
|
|
||||||
filename_suffix = delimiter + filename.split(delimiter)[-1]
|
|
||||||
assert filename_suffix == suffix
|
|
||||||
|
|
||||||
|
|
||||||
def _mock_getpass(inputs):
|
|
||||||
def prompt_return(prompt=""):
|
|
||||||
if type(inputs) == str:
|
|
||||||
return inputs
|
|
||||||
try:
|
|
||||||
return next(inputs)
|
|
||||||
except StopIteration:
|
|
||||||
raise KeyboardInterrupt
|
|
||||||
|
|
||||||
return prompt_return
|
|
||||||
|
|
||||||
|
|
||||||
def _mock_input(inputs):
|
|
||||||
def prompt_return(prompt=""):
|
|
||||||
try:
|
|
||||||
val = next(inputs)
|
|
||||||
print(prompt, val)
|
|
||||||
return val
|
|
||||||
except StopIteration:
|
|
||||||
raise KeyboardInterrupt
|
|
||||||
|
|
||||||
return prompt_return
|
|
||||||
|
|
||||||
|
|
||||||
def _mock_time_parse(context):
|
|
||||||
original_parse = jrnl.time.parse
|
|
||||||
if "now" not in context:
|
|
||||||
return original_parse
|
|
||||||
|
|
||||||
def wrapper(input, *args, **kwargs):
|
|
||||||
input = context.now if input == "now" else input
|
|
||||||
return original_parse(input, *args, **kwargs)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@when('we run "{command}" and enter')
|
|
||||||
@when('we run "{command}" and enter nothing')
|
|
||||||
@when('we run "{command}" and enter "{inputs}"')
|
|
||||||
def run_with_input(context, command, inputs=""):
|
|
||||||
# create an iterator through all inputs. These inputs will be fed one by one
|
|
||||||
# to the mocked calls for 'input()', 'util.getpass()' and 'sys.stdin.read()'
|
|
||||||
if context.text:
|
|
||||||
text = iter(context.text.split("\n"))
|
|
||||||
else:
|
|
||||||
text = iter([inputs])
|
|
||||||
|
|
||||||
args = split_args(command)[1:]
|
|
||||||
context.args = args
|
|
||||||
|
|
||||||
def _mock_editor(command):
|
|
||||||
context.editor_command = command
|
|
||||||
tmpfile = command[-1]
|
|
||||||
with open(tmpfile, "r") as editor_file:
|
|
||||||
file_content = editor_file.read()
|
|
||||||
context.editor_file = {"name": tmpfile, "content": file_content}
|
|
||||||
Path(tmpfile).touch()
|
|
||||||
|
|
||||||
if "password" in context:
|
|
||||||
password = context.password
|
|
||||||
else:
|
|
||||||
password = text
|
|
||||||
|
|
||||||
# fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
with \
|
|
||||||
patch("builtins.input", side_effect=_mock_input(text)) as mock_input, \
|
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
|
||||||
patch("sys.stdin.read", side_effect=text) as mock_read, \
|
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
|
||||||
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
|
||||||
:
|
|
||||||
try:
|
|
||||||
cli(args or [])
|
|
||||||
context.exit_status = 0
|
|
||||||
except SystemExit as e:
|
|
||||||
context.exit_status = e.code
|
|
||||||
|
|
||||||
# put mocks into context so they can be checked later in "then" statements
|
|
||||||
context.editor = mock_editor
|
|
||||||
context.input = mock_input
|
|
||||||
context.getpass = mock_getpass
|
|
||||||
context.read = mock_read
|
|
||||||
context.iter_text = text
|
|
||||||
|
|
||||||
context.execute_steps('''
|
|
||||||
Then all input was used
|
|
||||||
And at least one input method was called
|
|
||||||
''')
|
|
||||||
|
|
||||||
# fmt: on
|
|
||||||
|
|
||||||
|
|
||||||
@then("at least one input method was called")
|
|
||||||
def inputs_were_called(context):
|
|
||||||
assert (
|
|
||||||
context.input.called
|
|
||||||
or context.getpass.called
|
|
||||||
or context.read.called
|
|
||||||
or context.editor.called
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should be prompted for a password")
|
|
||||||
def password_was_called(context):
|
|
||||||
assert context.getpass.called
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should not be prompted for a password")
|
|
||||||
def password_was_not_called(context):
|
|
||||||
assert not context.getpass.called
|
|
||||||
|
|
||||||
|
|
||||||
@then("all input was used")
|
|
||||||
def all_input_was_used(context):
|
|
||||||
# all inputs were used (ignore if empty string)
|
|
||||||
for temp in context.iter_text:
|
|
||||||
assert "" == temp, "Not all inputs were consumed"
|
|
||||||
|
|
||||||
|
|
||||||
@when('we run "{command}"')
|
|
||||||
@when('we run "{command}" and pipe')
|
|
||||||
@when('we run "{command}" and pipe "{text}"')
|
|
||||||
def run(context, command, text=""):
|
|
||||||
text = text or context.text or ""
|
|
||||||
|
|
||||||
if "config_path" in context and context.config_path is not None:
|
|
||||||
with open(context.config_path) as f:
|
|
||||||
context.jrnl_config = yaml.load(f, Loader=yaml.SafeLoader)
|
|
||||||
else:
|
|
||||||
context.jrnl_config = None
|
|
||||||
|
|
||||||
if "cache_dir" in context and context.cache_dir is not None:
|
|
||||||
cache_dir = os.path.join("features", "cache", context.cache_dir)
|
|
||||||
command = command.format(cache_dir=cache_dir)
|
|
||||||
if "config_path" in context and context.config_path is not None:
|
|
||||||
with open(context.config_path, "r") as f:
|
|
||||||
cfg = yaml.load(f, Loader=SafeLoader)
|
|
||||||
context.jrnl_config = cfg
|
|
||||||
|
|
||||||
args = split_args(command)
|
|
||||||
context.args = args[1:]
|
|
||||||
|
|
||||||
def _mock_editor(command):
|
|
||||||
context.editor_command = command
|
|
||||||
tmpfile = command[-1]
|
|
||||||
with open(tmpfile, "r") as editor_file:
|
|
||||||
file_content = editor_file.read()
|
|
||||||
context.editor_file = {"name": tmpfile, "content": file_content}
|
|
||||||
Path(tmpfile).touch()
|
|
||||||
|
|
||||||
if "password" in context:
|
|
||||||
password = context.password
|
|
||||||
else:
|
|
||||||
password = iter(text)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
with \
|
|
||||||
patch("sys.argv", args), \
|
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
|
||||||
patch("sys.stdin.read", side_effect=lambda: text), \
|
|
||||||
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
|
||||||
:
|
|
||||||
context.editor = mock_editor
|
|
||||||
context.getpass = mock_getpass
|
|
||||||
cli(args[1:])
|
|
||||||
context.exit_status = 0
|
|
||||||
# fmt: on
|
|
||||||
except SystemExit as e:
|
|
||||||
context.exit_status = e.code
|
|
||||||
|
|
||||||
|
|
||||||
@given('we load template "{filename}"')
|
|
||||||
def load_template(context, filename):
|
|
||||||
full_path = os.path.join("features/data/templates", filename)
|
|
||||||
exporter = plugins.template_exporter.__exporter_from_file(full_path)
|
|
||||||
plugins.__exporter_types[exporter.names[0]] = exporter
|
|
||||||
|
|
||||||
|
|
||||||
@when('we set the keyring password of "{journal}" to "{password}"')
|
|
||||||
def set_keyring_password(context, journal, password):
|
|
||||||
keyring.set_password("jrnl", journal, password)
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should get an error")
|
|
||||||
def has_error(context):
|
|
||||||
assert context.exit_status != 0, context.exit_status
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should get no error")
|
|
||||||
def no_error(context):
|
|
||||||
assert context.exit_status == 0, context.exit_status
|
|
||||||
|
|
||||||
|
|
||||||
@then("we flush the output")
|
|
||||||
def flush_stdout(context):
|
|
||||||
context.stdout_capture.truncate(0)
|
|
||||||
context.stdout_capture.seek(0)
|
|
||||||
|
|
||||||
|
|
||||||
@then("we flush the error output")
|
|
||||||
def flush_stderr(context):
|
|
||||||
context.stderr_capture.truncate(0)
|
|
||||||
context.stderr_capture.seek(0)
|
|
||||||
|
|
||||||
|
|
||||||
@then("we flush all the output")
|
|
||||||
def flush_all_output(context):
|
|
||||||
context.execute_steps(
|
|
||||||
"""
|
|
||||||
Then we flush the output
|
|
||||||
Then we flush the error output
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should be")
|
|
||||||
@then("the output should be empty")
|
|
||||||
@then('the output should be "{text}"')
|
|
||||||
def check_output(context, text=None):
|
|
||||||
text = (text or context.text or "").strip().splitlines()
|
|
||||||
out = context.stdout_capture.getvalue().strip().splitlines()
|
|
||||||
assert len(text) == len(out), "Output has {} lines (expected: {})".format(
|
|
||||||
len(out), len(text)
|
|
||||||
)
|
|
||||||
for line_text, line_out in zip(text, out):
|
|
||||||
assert line_text.strip() == line_out.strip(), [
|
|
||||||
line_text.strip(),
|
|
||||||
line_out.strip(),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@then('the output should contain "{text}" in the local time')
|
|
||||||
def check_output_time_inline(context, text):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
date, flag = CALENDAR.parse(text)
|
|
||||||
output_date = time.strftime("%Y-%m-%d %H:%M", date)
|
|
||||||
assert output_date in out, output_date
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should contain pyproject.toml version")
|
|
||||||
def check_output_version_inline(context):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
pyproject = (Path(__file__) / ".." / ".." / ".." / "pyproject.toml").resolve()
|
|
||||||
pyproject_contents = toml.load(pyproject)
|
|
||||||
pyproject_version = pyproject_contents["tool"]["poetry"]["version"]
|
|
||||||
assert pyproject_version in out, pyproject_version
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should contain")
|
|
||||||
@then('the output should contain "{text}"')
|
|
||||||
@then('the output should contain "{text}" or "{text2}"')
|
|
||||||
def check_output_inline(context, text=None, text2=None):
|
|
||||||
text = text or context.text
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
assert (text and text in out) or (text2 and text2 in out)
|
|
||||||
|
|
||||||
|
|
||||||
@then("the error output should contain")
|
|
||||||
@then('the error output should contain "{text}"')
|
|
||||||
@then('the error output should contain "{text}" or "{text2}"')
|
|
||||||
def check_error_output_inline(context, text=None, text2=None):
|
|
||||||
text = text or context.text
|
|
||||||
out = context.stderr_capture.getvalue()
|
|
||||||
assert (text and text in out) or (text2 and text2 in out)
|
|
||||||
|
|
||||||
|
|
||||||
@then('the output should match "{regex}"')
|
|
||||||
@then('the output should match "{regex}" {num} times')
|
|
||||||
def matches_std_output(context, regex, num=1):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
matches = re.findall(regex, out)
|
|
||||||
assert (
|
|
||||||
matches and len(matches) == num
|
|
||||||
), f"\nRegex didn't match exactly {num} time(s):\n{regex}\n{str(out)}\n{str(matches)}"
|
|
||||||
|
|
||||||
|
|
||||||
@then('the error output should match "{regex}"')
|
|
||||||
@then('the error output should match "{regex}" {num} times')
|
|
||||||
def matches_err_ouput(context, regex, num=1):
|
|
||||||
out = context.stderr_capture.getvalue()
|
|
||||||
matches = re.findall(regex, out)
|
|
||||||
assert (
|
|
||||||
matches and len(matches) == num
|
|
||||||
), f"\nRegex didn't match exactly {num} time(s):\n{regex}\n{str(out)}\n{str(matches)}"
|
|
||||||
|
|
||||||
|
|
||||||
@then('the output should not contain "{text}"')
|
|
||||||
def check_output_not_inline(context, text):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
assert text not in out
|
|
||||||
|
|
||||||
|
|
||||||
@then('we should see the message "{text}"')
|
|
||||||
@then('the error output should be "{text}"')
|
|
||||||
def check_message(context, text):
|
|
||||||
out = context.stderr_capture.getvalue()
|
|
||||||
assert text in out, [text, out]
|
|
||||||
|
|
||||||
|
|
||||||
@then('we should not see the message "{text}"')
|
|
||||||
def check_not_message(context, text):
|
|
||||||
out = context.stderr_capture.getvalue()
|
|
||||||
assert text not in out, [text, out]
|
|
||||||
|
|
||||||
|
|
||||||
@then('the journal should contain "{text}"')
|
|
||||||
@then('journal "{journal_name}" should contain "{text}"')
|
|
||||||
def check_journal_content(context, text, journal_name="default"):
|
|
||||||
journal = read_journal(context, journal_name)
|
|
||||||
assert text in journal, journal
|
|
||||||
|
|
||||||
|
|
||||||
@then('the journal should not contain "{text}"')
|
|
||||||
@then('journal "{journal_name}" should not contain "{text}"')
|
|
||||||
def check_not_journal_content(context, text, journal_name="default"):
|
|
||||||
journal = read_journal(context, journal_name)
|
|
||||||
assert text not in journal, journal
|
|
||||||
|
|
||||||
|
|
||||||
@then("the journal should not exist")
|
|
||||||
@then('journal "{journal_name}" should not exist')
|
|
||||||
def journal_doesnt_exist(context, journal_name="default"):
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
|
|
||||||
journal_path = configuration["journals"][journal_name]
|
|
||||||
assert not os.path.exists(journal_path)
|
|
||||||
|
|
||||||
|
|
||||||
@then("the journal should exist")
|
|
||||||
@then('journal "{journal_name}" should exist')
|
|
||||||
def journal_exists(context, journal_name="default"):
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
|
|
||||||
journal_path = configuration["journals"][journal_name]
|
|
||||||
assert os.path.exists(journal_path)
|
|
||||||
|
|
||||||
|
|
||||||
@then('the config should have "{key}" set to')
|
|
||||||
@then('the config should have "{key}" set to "{value}"')
|
|
||||||
@then('the config for journal "{journal}" should have "{key}" set to "{value}"')
|
|
||||||
def config_var(context, key, value="", journal=None):
|
|
||||||
key_as_vec = key.split(".")
|
|
||||||
|
|
||||||
if "args" in context:
|
|
||||||
parsed = parse_args(context.args)
|
|
||||||
overrides = parsed.config_override
|
|
||||||
value = read_value_from_string(value or context.text or "")
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
|
|
||||||
if journal:
|
|
||||||
configuration = configuration["journals"][journal]
|
|
||||||
|
|
||||||
if overrides:
|
|
||||||
with patch.object(
|
|
||||||
jrnl.override, "_recursively_apply", wraps=_recursively_apply
|
|
||||||
) as spy_recurse:
|
|
||||||
configuration = apply_overrides(overrides, configuration)
|
|
||||||
runtime_cfg = spy_recurse.call_args_list[0][0][0]
|
|
||||||
else:
|
|
||||||
runtime_cfg = configuration
|
|
||||||
# extract the value of the desired key from the configuration after overrides have been applied
|
|
||||||
for k in key_as_vec:
|
|
||||||
runtime_cfg = runtime_cfg["%s" % k]
|
|
||||||
assert runtime_cfg == value
|
|
||||||
|
|
||||||
|
|
||||||
@then('the config for journal "{journal}" should not have "{key}" set')
|
|
||||||
def config_no_var(context, key, value="", journal=None):
|
|
||||||
configuration = load_config(context.config_path)
|
|
||||||
|
|
||||||
if journal:
|
|
||||||
configuration = configuration["journals"][journal]
|
|
||||||
|
|
||||||
assert key not in configuration
|
|
||||||
|
|
||||||
|
|
||||||
@then("the journal should have {number:d} entries")
|
|
||||||
@then("the journal should have {number:d} entry")
|
|
||||||
@then('journal "{journal_name}" should have {number:d} entries')
|
|
||||||
@then('journal "{journal_name}" should have {number:d} entry')
|
|
||||||
def check_journal_entries(context, number, journal_name="default"):
|
|
||||||
journal = open_journal(context, journal_name)
|
|
||||||
assert len(journal.entries) == number
|
|
||||||
|
|
||||||
|
|
||||||
@when("the journal directory is listed")
|
|
||||||
def list_journal_directory(context, journal="default"):
|
|
||||||
with open(context.config_path) as config_file:
|
|
||||||
configuration = yaml.load(config_file, Loader=yaml.SafeLoader)
|
|
||||||
journal_path = configuration["journals"][journal]
|
|
||||||
for root, dirnames, f in os.walk(journal_path):
|
|
||||||
for file in f:
|
|
||||||
print(os.path.join(root, file))
|
|
||||||
|
|
||||||
|
|
||||||
@then("fail")
|
|
||||||
def debug_fail(context):
|
|
||||||
assert False
|
|
|
@ -1,200 +0,0 @@
|
||||||
# Copyright (C) 2012-2021 jrnl contributors
|
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import random
|
|
||||||
import string
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
from behave import given
|
|
||||||
from behave import then
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should be {width:d} columns wide")
|
|
||||||
def check_output_width(context, width):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
out_lines = out.splitlines()
|
|
||||||
for line in out_lines:
|
|
||||||
assert len(line) <= width
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should be parsable as json")
|
|
||||||
def check_output_json(context):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
assert json.loads(out), out
|
|
||||||
|
|
||||||
|
|
||||||
@then('"{field}" in the json output should have {number:d} elements')
|
|
||||||
@then('"{field}" in the json output should have 1 element')
|
|
||||||
def check_output_field(context, field, number=1):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
out_json = json.loads(out)
|
|
||||||
assert field in out_json, [field, out_json]
|
|
||||||
assert len(out_json[field]) == number, len(out_json[field])
|
|
||||||
|
|
||||||
|
|
||||||
@then('"{field}" in the json output should not contain "{key}"')
|
|
||||||
def check_output_field_not_key(context, field, key):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
out_json = json.loads(out)
|
|
||||||
assert field in out_json
|
|
||||||
assert key not in out_json[field]
|
|
||||||
|
|
||||||
|
|
||||||
@then('"{field}" in the json output should contain "{key}"')
|
|
||||||
def check_output_field_key(context, field, key):
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
struct = json.loads(out)
|
|
||||||
|
|
||||||
for node in field.split("."):
|
|
||||||
try:
|
|
||||||
struct = struct[int(node)]
|
|
||||||
except ValueError:
|
|
||||||
assert node in struct
|
|
||||||
struct = struct[node]
|
|
||||||
|
|
||||||
assert key in struct
|
|
||||||
|
|
||||||
|
|
||||||
@then("the json output should contain {path}")
|
|
||||||
@then('the json output should contain {path} = "{value}"')
|
|
||||||
def check_json_output_path(context, path, value=None):
|
|
||||||
"""E.g.
|
|
||||||
the json output should contain entries.0.title = "hello"
|
|
||||||
"""
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
struct = json.loads(out)
|
|
||||||
|
|
||||||
for node in path.split("."):
|
|
||||||
try:
|
|
||||||
struct = struct[int(node)]
|
|
||||||
except ValueError:
|
|
||||||
struct = struct[node]
|
|
||||||
|
|
||||||
if value is not None:
|
|
||||||
assert struct == value, struct
|
|
||||||
else:
|
|
||||||
assert struct is not None
|
|
||||||
|
|
||||||
|
|
||||||
@then(
|
|
||||||
'entry {entry_number:d} should have an array "{name}" with {items_number:d} elements'
|
|
||||||
)
|
|
||||||
def entry_array_count(context, entry_number, name, items_number):
|
|
||||||
# note that entry_number is 1-indexed.
|
|
||||||
out = context.stdout_capture.getvalue()
|
|
||||||
out_json = json.loads(out)
|
|
||||||
assert len(out_json["entries"][entry_number - 1][name]) == items_number
|
|
||||||
|
|
||||||
|
|
||||||
@then("the output should be a valid XML string")
|
|
||||||
def assert_valid_xml_string(context):
|
|
||||||
output = context.stdout_capture.getvalue()
|
|
||||||
xml_tree = ElementTree.fromstring(output)
|
|
||||||
assert xml_tree, output
|
|
||||||
|
|
||||||
|
|
||||||
@then('"{item}" node in the xml output should have {number:d} elements')
|
|
||||||
def assert_xml_output_entries_count(context, item, number):
|
|
||||||
output = context.stdout_capture.getvalue()
|
|
||||||
xml_tree = ElementTree.fromstring(output)
|
|
||||||
|
|
||||||
xml_tags = (node.tag for node in xml_tree)
|
|
||||||
assert item in xml_tags, str(list(xml_tags))
|
|
||||||
|
|
||||||
actual_entry_count = len(xml_tree.find(item))
|
|
||||||
assert actual_entry_count == number, actual_entry_count
|
|
||||||
|
|
||||||
|
|
||||||
@then('there should be {number:d} "{item}" elements')
|
|
||||||
def count_elements(context, number, item):
|
|
||||||
output = context.stdout_capture.getvalue()
|
|
||||||
xml_tree = ElementTree.fromstring(output)
|
|
||||||
assert len(xml_tree.findall(".//" + item)) == number
|
|
||||||
|
|
||||||
|
|
||||||
@then('"tags" in the xml output should contain {expected_tags_json_list}')
|
|
||||||
def assert_xml_output_tags(context, expected_tags_json_list):
|
|
||||||
output = context.stdout_capture.getvalue()
|
|
||||||
xml_tree = ElementTree.fromstring(output)
|
|
||||||
|
|
||||||
xml_tags = (node.tag for node in xml_tree)
|
|
||||||
assert "tags" in xml_tags, str(list(xml_tags))
|
|
||||||
|
|
||||||
expected_tags = json.loads(expected_tags_json_list)
|
|
||||||
actual_tags = set(t.attrib["name"] for t in xml_tree.find("tags"))
|
|
||||||
assert actual_tags == set(expected_tags), [actual_tags, set(expected_tags)]
|
|
||||||
|
|
||||||
|
|
||||||
@given('we create cache directory "{dir_name}"')
|
|
||||||
@given("we create a cache directory")
|
|
||||||
def create_directory(context, dir_name=None):
|
|
||||||
if not dir_name:
|
|
||||||
dir_name = "cache_" + "".join(
|
|
||||||
random.choices(string.ascii_uppercase + string.digits, k=20)
|
|
||||||
)
|
|
||||||
|
|
||||||
working_dir = os.path.join("features", "cache", dir_name)
|
|
||||||
if os.path.exists(working_dir):
|
|
||||||
shutil.rmtree(working_dir)
|
|
||||||
os.makedirs(working_dir)
|
|
||||||
context.cache_dir = dir_name
|
|
||||||
|
|
||||||
|
|
||||||
@then('cache "{dir_name}" should contain the files')
|
|
||||||
@then('cache "{dir_name}" should contain the files {expected_files_json_list}')
|
|
||||||
@then("the cache should contain the files")
|
|
||||||
def assert_dir_contains_files(context, dir_name=None, expected_files_json_list=""):
|
|
||||||
if not dir_name:
|
|
||||||
dir_name = context.cache_dir
|
|
||||||
|
|
||||||
working_dir = os.path.join("features", "cache", dir_name)
|
|
||||||
actual_files = os.listdir(working_dir)
|
|
||||||
|
|
||||||
expected_files = context.text or expected_files_json_list
|
|
||||||
expected_files = expected_files.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('the content of file "{file_path}" in cache directory "{cache_dir}" should be')
|
|
||||||
@then('the content of file "{file_path}" in the cache should be')
|
|
||||||
def assert_exported_yaml_file_content(context, file_path, cache_dir=None):
|
|
||||||
if not cache_dir:
|
|
||||||
cache_dir = context.cache_dir
|
|
||||||
|
|
||||||
expected_content = context.text.strip().splitlines()
|
|
||||||
full_file_path = os.path.join("features", "cache", cache_dir, file_path)
|
|
||||||
|
|
||||||
with open(full_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],
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
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,77 +0,0 @@
|
||||||
from jrnl.jrnl import run
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
# from __future__ import with_statement
|
|
||||||
from jrnl.args import parse_args
|
|
||||||
from behave import then
|
|
||||||
|
|
||||||
from features.steps.core import _mock_getpass, _mock_time_parse
|
|
||||||
|
|
||||||
|
|
||||||
@then("the editor {editor} should have been called")
|
|
||||||
@then("No editor should have been called")
|
|
||||||
def editor_override(context, editor=None):
|
|
||||||
def _mock_write_in_editor(config):
|
|
||||||
editor = config["editor"]
|
|
||||||
journal = "features/journals/journal.jrnl"
|
|
||||||
context.tmpfile = journal
|
|
||||||
print("%s has been launched" % editor)
|
|
||||||
return journal
|
|
||||||
|
|
||||||
if "password" in context:
|
|
||||||
password = context.password
|
|
||||||
else:
|
|
||||||
password = ""
|
|
||||||
# fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
with \
|
|
||||||
mock.patch("jrnl.jrnl._write_in_editor", side_effect=_mock_write_in_editor(context.jrnl_config)) as mock_write_in_editor, \
|
|
||||||
mock.patch("sys.stdin.isatty", return_value=True), \
|
|
||||||
mock.patch('getpass.getpass',side_effect=_mock_getpass(password)), \
|
|
||||||
mock.patch("jrnl.time.parse", side_effect = _mock_time_parse(context)), \
|
|
||||||
mock.patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
|
||||||
mock.patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
|
||||||
:
|
|
||||||
try :
|
|
||||||
parsed_args = parse_args(context.args)
|
|
||||||
run(parsed_args)
|
|
||||||
context.exit_status = 0
|
|
||||||
context.editor = mock_write_in_editor
|
|
||||||
expected_config = context.jrnl_config
|
|
||||||
expected_config['editor'] = '%s'%editor
|
|
||||||
expected_config['journal'] ='features/journals/journal.jrnl'
|
|
||||||
|
|
||||||
if editor is not None:
|
|
||||||
assert mock_write_in_editor.call_count == 1
|
|
||||||
assert mock_write_in_editor.call_args[0][0]['editor']==editor
|
|
||||||
else:
|
|
||||||
# Expect that editor is *never* called
|
|
||||||
mock_write_in_editor.assert_not_called()
|
|
||||||
except SystemExit as e:
|
|
||||||
context.exit_status = e.code
|
|
||||||
# fmt: on
|
|
||||||
|
|
||||||
|
|
||||||
@then("the stdin prompt should have been called")
|
|
||||||
def override_editor_to_use_stdin(context):
|
|
||||||
|
|
||||||
try:
|
|
||||||
with mock.patch(
|
|
||||||
"sys.stdin.read",
|
|
||||||
return_value="Zwei peanuts walk into a bar und one of zem was a-salted",
|
|
||||||
) as mock_stdin_read, mock.patch(
|
|
||||||
"jrnl.install.load_or_install_jrnl", return_value=context.jrnl_config
|
|
||||||
), mock.patch(
|
|
||||||
"jrnl.Journal.open_journal",
|
|
||||||
spec=False,
|
|
||||||
return_value="features/journals/journal.jrnl",
|
|
||||||
), mock.patch(
|
|
||||||
"getpass.getpass", side_effect=_mock_getpass("test")
|
|
||||||
):
|
|
||||||
parsed_args = parse_args(context.args)
|
|
||||||
run(parsed_args)
|
|
||||||
context.exit_status = 0
|
|
||||||
mock_stdin_read.assert_called_once()
|
|
||||||
|
|
||||||
except SystemExit as e:
|
|
||||||
context.exit_status = e.code
|
|
|
@ -1,53 +0,0 @@
|
||||||
Feature: Tagging
|
|
||||||
# See search.feature for tag-related searches
|
|
||||||
# And format.feature for tag-related output
|
|
||||||
|
|
||||||
Scenario Outline: Tags should allow certain special characters such as /, +, #
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl 2020-09-26: This is an entry about @os/2 and @c++ and @c#"
|
|
||||||
When we run "jrnl --tags -on 2020-09-26"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be
|
|
||||||
"""
|
|
||||||
@os/2 : 1
|
|
||||||
@c++ : 1
|
|
||||||
@c# : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Emails addresses should not be parsed as tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl 2020-09-26: The email address test@example.com does not seem to work for me"
|
|
||||||
When we run "jrnl 2020-09-26: The email address test@example.org also does not work for me"
|
|
||||||
When we run "jrnl 2020-09-26: I tried test@example.org and test@example.edu too"
|
|
||||||
Then we flush the output
|
|
||||||
When we run "jrnl --tags -on 2020-09-26"
|
|
||||||
Then we should get no error
|
|
||||||
And the output should be "[No tags found in journal.]"
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
||||||
|
|
||||||
Scenario Outline: Entry can start and end with tags
|
|
||||||
Given we use the config "<config>.yaml"
|
|
||||||
When we run "jrnl 2020-09-26: @foo came over, we went to a @bar"
|
|
||||||
When we run "jrnl --tags -on 2020-09-26"
|
|
||||||
Then the output should be
|
|
||||||
"""
|
|
||||||
@foo : 1
|
|
||||||
@bar : 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
Examples: configs
|
|
||||||
| config |
|
|
||||||
| basic_onefile |
|
|
||||||
| basic_folder |
|
|
||||||
| basic_dayone |
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue