From 758d913376703d79e43e6e6b8c66e19cb6e72146 Mon Sep 17 00:00:00 2001 From: Jonathan Wren Date: Sat, 17 Oct 2020 15:17:38 -0700 Subject: [PATCH] Lots of test refactoring (#1042) * make behave slightly less verbose for use with behave --format progress2 * standardize behave tests * move tests around to be more behavior driven * clean up txt file after tests * add more tests, add more functionality to behave for calling mock editor * move around behave tests, get rid of regression files * clean up some code around keyrings * add more placeholder test scenarios (marked with @todo) You can run just these tests with `behave --no-skipped --tags=todo` * fix "missing_directory" test This test was missing the config file it was trying to use. So, it was really a very useless, broken test that we absolutely should not have approved the PR (#963) for. * add write tests for each journal type * update version tests, add new regex match behave step * add config test outlines * add journal types to some search tests * change "basic" config reference to "simple" * update configs * add more journal types in search * fix basic folder journal reference * add flush output steps to behave, update delete flag tests * fix failing test with a flush * update more delete flag tests to include other journal types * fix file cleanup after failed test with no debug on * fix password test * fix DayOne tag sample data, move search/format tag tests, and run them on multiple jrnl types * added ability to auto-prompt for password for encrypted journals Only uses password when prompted, and doesn't get in the way of other input prompts. This allows us to run the same scenarios on both encrypted journals and other journal types. * fold encrypted scenarios into the rest of the scenarios where possible * remove apostrophe that is breaking tests on CI * add more journal type tests to import feature * standardize whitespace in behave tests, take out duplicate test * update handling of cache directories in test suite (easier syntax) * skip failing YAML exporter emoji test on Windows * added @todo tags for things that need follow-up Co-authored-by: Micah Jerome Ellison --- features/build.feature | 8 + features/contains.feature | 29 - features/core.feature | 200 +------ features/custom_dates.feature | 35 -- features/data/configs/basic_dayone.yaml | 17 + features/data/configs/basic_encrypted.yaml | 17 + features/data/configs/basic_folder.yaml | 17 + features/data/configs/basic_onefile.yaml | 17 + features/data/configs/dayone_empty.yaml | 17 + .../data/configs/editor_empty_folder.yaml | 12 + features/data/configs/editor_encrypted.yaml | 17 + features/data/configs/missing_directory.yaml | 17 + features/data/configs/missing_journal.yaml | 17 + .../data/configs/{basic.yaml => simple.yaml} | 0 .../D04D335AFED711EABA18FAFFC2100C3D.doentry | 53 ++ .../FC8A86CAFED711EA8892FAFFC2100C3D.doentry | 55 ++ .../FD8ABC8EFED711EABC35FAFFC2100C3D.doentry | 44 ++ .../data/journals/basic_encrypted.journal | 1 + .../data/journals/basic_folder/2020/08/29.txt | 19 + .../data/journals/basic_folder/2020/08/31.txt | 23 + .../data/journals/basic_folder/2020/09/24.txt | 11 + features/data/journals/basic_onefile.journal | 58 ++ .../dayone_empty.dayone/entries/empty.txt | 1 + .../data/journals/little_endian_dates.journal | 2 +- features/datetime.feature | 155 ++++++ features/dayone.feature | 95 ---- features/dayone_regressions.feature | 25 - features/delete.feature | 272 +++++---- features/encrypt.feature | 35 ++ features/encryption.feature | 81 --- features/environment.py | 33 +- features/exporting.feature | 147 ----- features/file_storage.feature | 46 ++ features/folder.feature | 42 -- features/format.feature | 514 ++++++++++++++++++ features/import.feature | 93 ++++ features/multiple_journals.feature | 12 +- features/password.feature | 87 +++ features/regression.feature | 175 ------ features/search.feature | 228 ++++++++ features/star.feature | 35 ++ features/starring.feature | 20 - features/steps/core.py | 299 +++++++--- features/steps/export_steps.py | 31 +- features/tag.feature | 53 ++ features/tagging.feature | 121 ----- features/upgrade.feature | 66 ++- features/write.feature | 182 +++++++ 48 files changed, 2367 insertions(+), 1167 deletions(-) create mode 100644 features/build.feature delete mode 100644 features/contains.feature delete mode 100644 features/custom_dates.feature create mode 100644 features/data/configs/basic_dayone.yaml create mode 100644 features/data/configs/basic_encrypted.yaml create mode 100644 features/data/configs/basic_folder.yaml create mode 100644 features/data/configs/basic_onefile.yaml create mode 100644 features/data/configs/dayone_empty.yaml create mode 100644 features/data/configs/editor_empty_folder.yaml create mode 100644 features/data/configs/editor_encrypted.yaml create mode 100644 features/data/configs/missing_directory.yaml create mode 100644 features/data/configs/missing_journal.yaml rename features/data/configs/{basic.yaml => simple.yaml} (100%) create mode 100644 features/data/journals/basic_dayone.dayone/entries/D04D335AFED711EABA18FAFFC2100C3D.doentry create mode 100644 features/data/journals/basic_dayone.dayone/entries/FC8A86CAFED711EA8892FAFFC2100C3D.doentry create mode 100644 features/data/journals/basic_dayone.dayone/entries/FD8ABC8EFED711EABC35FAFFC2100C3D.doentry create mode 100644 features/data/journals/basic_encrypted.journal create mode 100644 features/data/journals/basic_folder/2020/08/29.txt create mode 100644 features/data/journals/basic_folder/2020/08/31.txt create mode 100644 features/data/journals/basic_folder/2020/09/24.txt create mode 100644 features/data/journals/basic_onefile.journal create mode 100644 features/data/journals/dayone_empty.dayone/entries/empty.txt create mode 100644 features/datetime.feature delete mode 100644 features/dayone.feature delete mode 100644 features/dayone_regressions.feature create mode 100644 features/encrypt.feature delete mode 100644 features/encryption.feature delete mode 100644 features/exporting.feature create mode 100644 features/file_storage.feature delete mode 100644 features/folder.feature create mode 100644 features/format.feature create mode 100644 features/import.feature create mode 100644 features/password.feature delete mode 100644 features/regression.feature create mode 100644 features/search.feature create mode 100644 features/star.feature delete mode 100644 features/starring.feature create mode 100644 features/tag.feature delete mode 100644 features/tagging.feature create mode 100644 features/write.feature diff --git a/features/build.feature b/features/build.feature new file mode 100644 index 000000000..4725ea855 --- /dev/null +++ b/features/build.feature @@ -0,0 +1,8 @@ +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 diff --git a/features/contains.feature b/features/contains.feature deleted file mode 100644 index eac3a464f..000000000 --- a/features/contains.feature +++ /dev/null @@ -1,29 +0,0 @@ -Feature: Contains - - Scenario: Searching for a string - Given we use the config "basic.yaml" - When we run "jrnl -contains life" - Then we should get no error - and the output should be - """ - 2013-06-10 15:40 Life is good. - | But I'm better. - """ - - Scenario: Searching for a string within tag results - Given we use the config "tags.yaml" - When we run "jrnl @idea -contains software" - Then we should get no error - And the output should contain "software" - - Scenario: Searching for a string within AND tag results - Given we use the config "tags.yaml" - When we run "jrnl -and @journal @idea -contains software" - Then we should get no error - and the output should contain "software" - - Scenario: Searching for a string within NOT tag results - Given we use the config "tags.yaml" - When we run "jrnl -not @dan -contains software" - Then we should get no error - and the output should contain "software" diff --git a/features/core.feature b/features/core.feature index b8a987ec8..dc78a7a39 100644 --- a/features/core.feature +++ b/features/core.feature @@ -1,201 +1,21 @@ -Feature: Basic reading and writing to a journal +Feature: Functionality of jrnl outside of actually handling journals - Scenario: Loading a sample journal - Given we use the config "basic.yaml" - When we run "jrnl -n 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: Printing a journal that has multiline entries - Given we use the config "multiline.yaml" - When we run "jrnl -n 1" - Then we should get no error - and the output should be - """ - 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. - """ - - Scenario: Multiline entry with punctuation - Given we use the config "basic.yaml" - When we run "jrnl This is. the title\\n This is the second line" - and we run "jrnl -n 1" - Then the output should contain "This is. the title" - - Scenario: Single line entry with punctuation - Given we use the config "basic.yaml" - When we run "jrnl This is. the title" - and we run "jrnl -n 1" - Then the output should contain "| the title" - - Scenario: Writing an entry from command line - Given we use the config "basic.yaml" - When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." - Then we should see the message "Entry added" - When we run "jrnl -n 1" - Then the output should contain "2013-07-23 09:00 A cold and stormy day." - - Scenario: Writing an empty entry from the editor - Given we use the config "editor.yaml" - When we open the editor and enter nothing - Then we should see the message "[Nothing saved to file]" - - Scenario: Sending an argument with spaces to the editor should work - Given we use the config "editor-args.yaml" - When we open the editor and enter "lorem ipsum" - Then the editor should have been called with 5 arguments - And one editor argument should be "vim" - And one editor argument should be "-f" - And one editor argument should be "-c" - And one editor argument should match "'?setf markdown'?" - - Scenario: Writing an empty entry from the command line - Given we use the config "basic.yaml" - When we run "jrnl" and enter nothing - Then the output should be - """ - - """ - - Scenario: Filtering for dates - Given we use the config "basic.yaml" - When we run "jrnl -on 2013-06-10 --short" - Then the output should be "2013-06-10 15:40 Life is good." - When we run "jrnl -on 'june 6 2013' --short" - Then the output should be "2013-06-10 15:40 Life is good." - - Scenario: Emoji support - Given we use the config "basic.yaml" - When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘" - Then we should see the message "Entry added" - When we run "jrnl -n 1" - Then the output should contain "🌞" - and the output should contain "🐘" - - Scenario: Writing an entry at the prompt - Given we use the config "basic.yaml" - When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive." + Scenario: Displaying the version number + Given we use the config "simple.yaml" + When we run "jrnl --version" Then we should get no error - and the journal should contain "[2013-07-25 09:00] I saw Elvis." - and the journal should contain "He's alive." + Then the output should match "^jrnl version v\d+\.\d+\.\d+(-(alpha|beta))?$" Scenario: Displaying the version number - Given we use the config "basic.yaml" + Given we use the config "simple.yaml" When we run "jrnl -v" Then we should get no error - Then the output should contain "version" - - Scenario: --short displays the short version of entries (only the title) - Given we use the config "basic.yaml" - When we run "jrnl -on 2013-06-10 --short" - Then the output should be "2013-06-10 15:40 Life is good." - - Scenario: -s displays the short version of entries (only the title) - Given we use the config "basic.yaml" - When we run "jrnl -on 2013-06-10 -s" - Then the output should be "2013-06-10 15:40 Life is good." - - Scenario: Invalid color configuration - Given we use the config "invalid_color.yaml" - When we run "jrnl -on 2013-06-10 -s" - Then the output should be - """ - 2013-06-10 15:40 Life is good. - """ - And we should get no error - - Scenario: Journal directory does not exist - Given we use the config "missing_directory.yaml" - When we run "jrnl Life is good" - and we run "jrnl -n 1" - Then the output should contain "Life is good" - - Scenario: Installation with relative journal and referencing from another folder - 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" + Then the output should match "^jrnl version v\d+\.\d+\.\d+(-(alpha|beta))?$" - Scenario: --diagnostic runs without exceptions + Scenario: Running the diagnostic command When we run "jrnl --diagnostic" Then the output should contain "jrnl" And the output should contain "Python" - Scenario: --import allows new entry from stdin - Given we use the config "basic.yaml" - When we run "jrnl --import" and pipe "[2020-07-05 15:00] Observe and import." - And we run "jrnl -1" - Then the journal should contain "[2020-07-05 15:00] Observe and import." - And the output should contain "Observe and import" - - Scenario: --import allows new large entry from stdin - Given we use the config "basic.yaml" - 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. - """ - And we run "jrnl -1" - Then the journal should contain "[2020-07-05 15:00] Observe and import." - And the output should contain "Observe and import" - And the output should contain "Lorem ipsum" - And the output should contain "end of entry." - - Scenario: --import allows multiple new entries from stdin - Given we use the config "basic.yaml" - 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 the journal should contain "[2020-07-05 15:00] Observe and import." - Then the journal should contain "[2020-07-05 15:01] Twice as nice." - - Scenario: --import allows import new entries from file - Given we use the config "basic.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 doesn't get confused with piping and file - Given we use the config "basic.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!" - + @todo + Scenario: Listing available journals diff --git a/features/custom_dates.feature b/features/custom_dates.feature deleted file mode 100644 index d3489648e..000000000 --- a/features/custom_dates.feature +++ /dev/null @@ -1,35 +0,0 @@ -Feature: Reading and writing to journal with custom date formats - - Scenario: Loading a sample journal - 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.06.2013 15:40 Life is good. - | But I'm better. - """ - - Scenario: Writing an entry from command line - Given we use the config "little_endian_dates.yaml" - When we run "jrnl 2013-07-12: A cold and stormy day. I ate crisps on the sofa." - Then we should see the message "Entry added" - When we run "jrnl -n 1" - Then the output should contain "12.07.2013 09:00 A cold and stormy day." - - Scenario: Filtering for dates - Given we use the config "little_endian_dates.yaml" - When we run "jrnl -on 2013-06-10 --short" - Then the output should be "10.06.2013 15:40 Life is good." - When we run "jrnl -on 'june 6 2013' --short" - Then the output should be "10.06.2013 15:40 Life is good." - - Scenario: Writing an entry at the prompt - 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." \ No newline at end of file diff --git a/features/data/configs/basic_dayone.yaml b/features/data/configs/basic_dayone.yaml new file mode 100644 index 000000000..0209f2f74 --- /dev/null +++ b/features/data/configs/basic_dayone.yaml @@ -0,0 +1,17 @@ +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: "|" diff --git a/features/data/configs/basic_encrypted.yaml b/features/data/configs/basic_encrypted.yaml new file mode 100644 index 000000000..77f4e48d3 --- /dev/null +++ b/features/data/configs/basic_encrypted.yaml @@ -0,0 +1,17 @@ +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: "|" diff --git a/features/data/configs/basic_folder.yaml b/features/data/configs/basic_folder.yaml new file mode 100644 index 000000000..ba0de638d --- /dev/null +++ b/features/data/configs/basic_folder.yaml @@ -0,0 +1,17 @@ +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: "|" diff --git a/features/data/configs/basic_onefile.yaml b/features/data/configs/basic_onefile.yaml new file mode 100644 index 000000000..fb48c6f84 --- /dev/null +++ b/features/data/configs/basic_onefile.yaml @@ -0,0 +1,17 @@ +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: "|" diff --git a/features/data/configs/dayone_empty.yaml b/features/data/configs/dayone_empty.yaml new file mode 100644 index 000000000..7750d3896 --- /dev/null +++ b/features/data/configs/dayone_empty.yaml @@ -0,0 +1,17 @@ +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 diff --git a/features/data/configs/editor_empty_folder.yaml b/features/data/configs/editor_empty_folder.yaml new file mode 100644 index 000000000..1724bbfb7 --- /dev/null +++ b/features/data/configs/editor_empty_folder.yaml @@ -0,0 +1,12 @@ +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: "|" diff --git a/features/data/configs/editor_encrypted.yaml b/features/data/configs/editor_encrypted.yaml new file mode 100644 index 000000000..75273c964 --- /dev/null +++ b/features/data/configs/editor_encrypted.yaml @@ -0,0 +1,17 @@ +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: "|" diff --git a/features/data/configs/missing_directory.yaml b/features/data/configs/missing_directory.yaml new file mode 100644 index 000000000..d600404ca --- /dev/null +++ b/features/data/configs/missing_directory.yaml @@ -0,0 +1,17 @@ +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 diff --git a/features/data/configs/missing_journal.yaml b/features/data/configs/missing_journal.yaml new file mode 100644 index 000000000..a1f6f8cf6 --- /dev/null +++ b/features/data/configs/missing_journal.yaml @@ -0,0 +1,17 @@ +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 diff --git a/features/data/configs/basic.yaml b/features/data/configs/simple.yaml similarity index 100% rename from features/data/configs/basic.yaml rename to features/data/configs/simple.yaml diff --git a/features/data/journals/basic_dayone.dayone/entries/D04D335AFED711EABA18FAFFC2100C3D.doentry b/features/data/journals/basic_dayone.dayone/entries/D04D335AFED711EABA18FAFFC2100C3D.doentry new file mode 100644 index 000000000..9721dd55f --- /dev/null +++ b/features/data/journals/basic_dayone.dayone/entries/D04D335AFED711EABA18FAFFC2100C3D.doentry @@ -0,0 +1,53 @@ + + + + + Creation Date + 2020-08-29T18:11:00Z + Starred + + Entry Text + 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. + Time Zone + America/Los_Angeles + UUID + D04D335AFED711EABA18FAFFC2100C3D + Tags + + ipsum + tagone + tagtwo + + Creator + + Device Agent + + Generation Date + 2020-09-25T02:35:45Z + Host Name + iris.lan + OS Agent + Darwin/19.3.0 + Software Agent + jrnl/v2.4.5 + + + diff --git a/features/data/journals/basic_dayone.dayone/entries/FC8A86CAFED711EA8892FAFFC2100C3D.doentry b/features/data/journals/basic_dayone.dayone/entries/FC8A86CAFED711EA8892FAFFC2100C3D.doentry new file mode 100644 index 000000000..8c2f3c520 --- /dev/null +++ b/features/data/journals/basic_dayone.dayone/entries/FC8A86CAFED711EA8892FAFFC2100C3D.doentry @@ -0,0 +1,55 @@ + + + + + Creation Date + 2020-08-31T21:32:00Z + Starred + + Entry Text + 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. + Time Zone + America/Los_Angeles + UUID + FC8A86CAFED711EA8892FAFFC2100C3D + Tags + + tagtwo + + Creator + + Device Agent + + Generation Date + 2020-09-25T02:36:59Z + Host Name + iris.lan + OS Agent + Darwin/19.3.0 + Software Agent + jrnl/v2.4.5 + + + diff --git a/features/data/journals/basic_dayone.dayone/entries/FD8ABC8EFED711EABC35FAFFC2100C3D.doentry b/features/data/journals/basic_dayone.dayone/entries/FD8ABC8EFED711EABC35FAFFC2100C3D.doentry new file mode 100644 index 000000000..d998c36bd --- /dev/null +++ b/features/data/journals/basic_dayone.dayone/entries/FD8ABC8EFED711EABC35FAFFC2100C3D.doentry @@ -0,0 +1,44 @@ + + + + + Creation Date + 2020-09-24T16:14:00Z + Starred + + Entry Text + 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 + Time Zone + America/Los_Angeles + UUID + FD8ABC8EFED711EABC35FAFFC2100C3D + Tags + + tagthree + tagone + + Creator + + Device Agent + + Generation Date + 2020-09-25T02:37:01Z + Host Name + iris.lan + OS Agent + Darwin/19.3.0 + Software Agent + jrnl/v2.4.5 + + + diff --git a/features/data/journals/basic_encrypted.journal b/features/data/journals/basic_encrypted.journal new file mode 100644 index 000000000..ffc122dfe --- /dev/null +++ b/features/data/journals/basic_encrypted.journal @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/features/data/journals/basic_folder/2020/08/29.txt b/features/data/journals/basic_folder/2020/08/29.txt new file mode 100644 index 000000000..c8af54caf --- /dev/null +++ b/features/data/journals/basic_folder/2020/08/29.txt @@ -0,0 +1,19 @@ +[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. diff --git a/features/data/journals/basic_folder/2020/08/31.txt b/features/data/journals/basic_folder/2020/08/31.txt new file mode 100644 index 000000000..826e7cdb9 --- /dev/null +++ b/features/data/journals/basic_folder/2020/08/31.txt @@ -0,0 +1,23 @@ +[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. diff --git a/features/data/journals/basic_folder/2020/09/24.txt b/features/data/journals/basic_folder/2020/09/24.txt new file mode 100644 index 000000000..2bd885ce7 --- /dev/null +++ b/features/data/journals/basic_folder/2020/09/24.txt @@ -0,0 +1,11 @@ +[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 diff --git a/features/data/journals/basic_onefile.journal b/features/data/journals/basic_onefile.journal new file mode 100644 index 000000000..0d9880492 --- /dev/null +++ b/features/data/journals/basic_onefile.journal @@ -0,0 +1,58 @@ +[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 diff --git a/features/data/journals/dayone_empty.dayone/entries/empty.txt b/features/data/journals/dayone_empty.dayone/entries/empty.txt new file mode 100644 index 000000000..c86b8f66a --- /dev/null +++ b/features/data/journals/dayone_empty.dayone/entries/empty.txt @@ -0,0 +1 @@ +This file exists to preserve the directory structure, but should be ignored by jrnl. diff --git a/features/data/journals/little_endian_dates.journal b/features/data/journals/little_endian_dates.journal index a3c5c3019..d74929692 100644 --- a/features/data/journals/little_endian_dates.journal +++ b/features/data/journals/little_endian_dates.journal @@ -1,5 +1,5 @@ [09.06.2013 15:39] My first entry. Everything is alright -[10.06.2013 15:40] Life is good. +[10.07.2013 15:40] Life is good. But I'm better. diff --git a/features/datetime.feature b/features/datetime.feature new file mode 100644 index 000000000..8fe335c96 --- /dev/null +++ b/features/datetime.feature @@ -0,0 +1,155 @@ +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 ".yaml" + When we run "jrnl " + Then we should see the message "Entry added" + When we run "jrnl -n 1" + Then the output should contain "" + + 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 ".yaml" + When we run "jrnl -on '' --short" + Then the output should be "" + + 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 : This is an entry on a ." + Then we should see the message "Entry added" + When we run "jrnl -1" + Then the output should contain " at 9am" in the local time + And the output should contain "This is an entry on a ." + + 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 : This is an entry on a ." + Then we should see the message "Entry added" + When we run "jrnl -1" + Then the output should contain " 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. + """ diff --git a/features/dayone.feature b/features/dayone.feature deleted file mode 100644 index 39abae951..000000000 --- a/features/dayone.feature +++ /dev/null @@ -1,95 +0,0 @@ -Feature: Dayone specific implementation details. - - 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! - """ - - # broken still - @skip - Scenario: Entries without timezone information will be interpreted as in the 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: Writing into Dayone - Given we use the config "dayone.yaml" - When we run "jrnl 01 may 1979: Being born hurts." - and we run "jrnl -until 1980" - Then the output should be - """ - 1979-05-01 09:00 Being born hurts. - """ - - Scenario: Loading tags from a DayOne Journal - Given we use the config "dayone.yaml" - When we run "jrnl --tags" - Then the output should be - """ - @work : 1 - @play : 1 - """ - - Scenario: Saving tags from a DayOne Journal - Given we use the config "dayone.yaml" - When we run "jrnl A hard day at @work" - and we run "jrnl --tags" - Then the output should be - """ - @work : 2 - @play : 1 - """ - - Scenario: Filtering by tags from a DayOne Journal - Given we use the config "dayone.yaml" - When we run "jrnl @work" - Then the output should be - """ - 2013-05-17 11:39 This entry has tags! - """ - - 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: Writing into Dayone adds extended metadata - Given we use the config "dayone.yaml" - When we run "jrnl 01 may 1979: Being born hurts." - and we run "jrnl --export json" - Then "entries" in the json output should have 5 elements - and the json output should contain entries.0.creator.software_agent - and the json output should contain entries.0.creator.os_agent - and the json output should contain entries.0.creator.host_name - and the json output should contain entries.0.creator.generation_date - and the json output should contain entries.0.creator.device_agent - and "entries.0.creator.software_agent" in the json output should contain "jrnl" - - Scenario: Editing Dayone with mock editor - Given we use the config "dayone.yaml" - When we run "jrnl --edit" - Then we should get no error - - Scenario: Editing Dayone entries - Given we use the config "dayone.yaml" - When we open the editor and append - """ - Here is the first line. - Here is the second line. - """ - When we run "jrnl -n 1" - Then we should get no error - and the output should contain "This entry is starred!" - and the output should contain "Here is the first line" - and the output should contain "Here is the second line" diff --git a/features/dayone_regressions.feature b/features/dayone_regressions.feature deleted file mode 100644 index 3e98f9e95..000000000 --- a/features/dayone_regressions.feature +++ /dev/null @@ -1,25 +0,0 @@ -Feature: Zapped Dayone bugs stay dead! - - # fails when system time is UTC (as on Travis-CI) - @skip - 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! - """ - - # fails when system time is UTC (as on Travis-CI) - @skip - Scenario: Title with an embedded period on DayOne journal - Given we use the config "dayone.yaml" - When we run "jrnl 04-24-2014: "Ran 6.2 miles today in 1:02:03. I'm feeling sore because I forgot to stretch."" - Then we should see the message "Entry added" - When we run "jrnl -1" - Then the output should be - """ - 2014-04-24 09:00 Ran 6.2 miles today in 1:02:03. - | I'm feeling sore because I forgot to stretch. - """ diff --git a/features/delete.feature b/features/delete.feature index d12fe8f87..2fc3f8f72 100644 --- a/features/delete.feature +++ b/features/delete.feature @@ -1,149 +1,229 @@ Feature: Delete entries from journal - Scenario: --delete flag allows deletion of single entry - Given we use the config "deletion.yaml" - When we run "jrnl -n 1" - Then the output should contain - """ - 2019-10-29 11:13 Third entry. - """ + Scenario Outline: Delete flag allows deletion of single entry + Given we use the 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 """ - When we run "jrnl -n 1" - Then the output should contain + Then we flush the output + When we run "jrnl -99 --short" + Then the output should be """ - 2019-10-29 11:11 Second entry. + 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. """ - Scenario: Backing out of interactive delete does not change journal - Given we use the config "deletion.yaml" + 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 ".yaml" When we run "jrnl --delete -n 1" and enter """ N """ - Then the journal should have 3 entries - And the journal should contain "[2019-10-29 11:11] First entry." - And the journal should contain "[2019-10-29 11:11] Second entry." - And the journal should contain "[2019-10-29 11:13] Third entry." + 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. + """ - Scenario: --delete flag with nonsense input deletes nothing (issue #932) - Given we use the config "deletion.yaml" + 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 ".yaml" When we run "jrnl --delete asdfasdf" - When we run "jrnl -n 1" - Then the output should contain + Then we flush the output + When we run "jrnl -99 --short" + Then the output should be """ - 2019-10-29 11:13 Third entry. + 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. """ - And the journal should have 3 entries - Scenario: --delete flag with tag only deletes tagged entries - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete @holidays" and enter + Examples: Configs + | config | + | basic_onefile | + | basic_folder | + | basic_dayone | + + Scenario Outline: Delete flag with tag only deletes tagged entries + Given we use the config ".yaml" + When we run "jrnl --delete @ipsum" and enter """ Y - Y """ - Then the journal should have 3 entries - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should contain "[2020-05-02 12:10] Writing tests." + 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: --delete flag with multiple tags deletes all entries matching any of the tags - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete @holidays @springtime" and enter + Scenario Outline: Delete flag with multiple tags deletes all entries matching any of the tags + Given we use the config ".yaml" + When we run "jrnl --delete @ipsum @tagthree" and enter """ Y Y - Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should not contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should not contain "[2020-05-01 09:00] Happy May Day!" - and the journal should not contain "[2020-05-02 12:10] Writing tests. *" - and the journal should have 2 entries + 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: --delete flag with -and and tags only deletes boolean AND of tagged entries - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete -and @holidays @springtime" and enter + Scenario Outline: Delete flag with -and deletes boolean AND of tagged entries + Given we use the config ".yaml" + When we run "jrnl --delete -and @tagone @tagtwo" and enter """ Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should not contain "[2020-05-01 09:00] Happy May Day!" - and the journal should contain "[2020-05-02 12:10] Writing tests. *" - and the journal should have 4 entries + 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: --delete flag with -not does not delete entries with -not tag - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete @holidays -not @springtime" and enter + Scenario Outline: Delete flag with -not does not delete entries from given tag + Given we use the config ".yaml" + When we run "jrnl --delete @tagone -not @ipsum" and enter """ Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should not contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should contain "[2020-05-01 09:00] Happy May Day!" - and the journal should contain "[2020-05-02 12:10] Writing tests. *" - and the journal should have 4 entries + 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: --delete flag with -from only deletes entries since a specified date - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete -from 2020-01-02" and enter + Scenario Outline: Delete flag with -from search operator only deletes entries since that date + Given we use the config ".yaml" + When we run "jrnl --delete -from 2020-09-01" and enter """ Y - Y - Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should contain "[2020-01-01 08:00] Happy New Year!" - and the journal should not contain "[2020-03-01 08:00] It's just another day in March." - and the journal should not contain "[2020-05-01 09:00] Happy May Day!" - and the journal should not contain "[2020-05-02 12:10] Writing tests." - and the journal should have 2 entries + 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: --delete flag with -to only deletes entries up to specified date - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete -to 2020-01-02" and enter + Scenario Outline: Delete flag with -to only deletes entries up to specified date + Given we use the config ".yaml" + When we run "jrnl --delete -to 2020-08-31" and enter """ Y Y """ - Then the journal should not contain "[2019-10-01 08:00] It's just another day in October." - and the journal should not contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should contain "[2020-05-01 09:00] Happy May Day!" - and the journal should contain "[2020-05-02 12:10] Writing tests." - and the journal should have 3 entries + 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. + """ - Scenario: --delete flag with -starred only deletes starred entries - Given we use the config "deletion_filters.yaml" + 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 ".yaml" When we run "jrnl --delete -starred" and enter """ Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should contain "[2020-05-01 09:00] Happy May Day!" - and the journal should not contain "[2020-05-02 12:10] Writing tests. *" - and the journal should have 4 entries + 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: --delete flag with -contains only entries containing expression - Given we use the config "deletion_filters.yaml" - When we run "jrnl --delete -contains happy" and enter + Scenario Outline: Delete flag with -contains only entries containing expression + Given we use the config ".yaml" + When we run "jrnl --delete -contains dignissim" and enter """ Y - Y """ - Then the journal should contain "[2019-10-01 08:00] It's just another day in October." - and the journal should not contain "[2020-01-01 08:00] Happy New Year!" - and the journal should contain "[2020-03-01 08:00] It's just another day in March." - and the journal should not contain "[2020-05-01 09:00] Happy May Day!" - and the journal should contain "[2020-05-02 12:10] Writing tests. *" - and the journal should have 3 entries + 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 + diff --git a/features/encrypt.feature b/features/encrypt.feature new file mode 100644 index 000000000..f2d0a62f4 --- /dev/null +++ b/features/encrypt.feature @@ -0,0 +1,35 @@ +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" + diff --git a/features/encryption.feature b/features/encryption.feature deleted file mode 100644 index 02f8b4232..000000000 --- a/features/encryption.feature +++ /dev/null @@ -1,81 +0,0 @@ - Feature: Encrypted journals - Scenario: Loading an encrypted journal - Given we use the config "encrypted.yaml" - When we run "jrnl -n 1" and enter "bad doggie no biscuit" - Then the output should contain "Password" - And the output should contain "2013-06-10 15:40 Life is good" - - 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" - Then we should see the message "Journal decrypted" - And the journal should have 2 entries - - Scenario: Encrypting a journal - Given we use the config "basic.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 the output should contain "Password" - And the output should contain "2013-06-10 15:40 Life is good" - - Scenario: Mistyping your password - Given we use the config "basic.yaml" - When we run "jrnl --encrypt" and enter - """ - swordfish - sordfish - swordfish - swordfish - n - """ - Then 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 the output should contain "Password" - And the output should contain "2013-06-10 15:40 Life is good" - - Scenario: Storing a password in Keychain - Given we use the config "multiple.yaml" - When we run "jrnl simple --encrypt" and enter - """ - sabertooth - sabertooth - y - """ - When we set the keychain password of "simple" to "sabertooth" - 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 "basic.yaml" - When we disable the keychain - and we run "jrnl test entry" - and we run "jrnl --encrypt" and enter - """ - password - password - n - """ - Then we should get no error - - Scenario: Encrypt journal with no keyring backend and do store in keyring - Given we use the config "basic.yaml" - When we disable the keychain - and we run "jrnl test entry" - and we run "jrnl --encrypt" and enter - """ - password - password - y - """ - Then we should get no error diff --git a/features/environment.py b/features/environment.py index 63fec4a64..71ed89690 100644 --- a/features/environment.py +++ b/features/environment.py @@ -5,8 +5,30 @@ 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): @@ -17,7 +39,7 @@ def before_feature(context, feature): # add "skip" tag # https://stackoverflow.com/a/42721605/4276230 if "skip" in feature.tags: - feature.skip("Marked with @skip") + feature.skip() return if "skip_win" in feature.tags and on_windows: @@ -44,7 +66,7 @@ def before_scenario(context, scenario): # add "skip" tag # https://stackoverflow.com/a/42721605/4276230 if "skip" in scenario.effective_tags: - scenario.skip("Marked with @skip") + scenario.skip() return if "skip_win" in scenario.effective_tags and on_windows: @@ -56,4 +78,9 @@ def after_scenario(context, scenario): """After each scenario, restore all test data and remove working_dirs.""" if os.getcwd() != CWD: os.chdir(CWD) - clean_all_working_dirs() + + # 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() diff --git a/features/exporting.feature b/features/exporting.feature deleted file mode 100644 index 96a9558f1..000000000 --- a/features/exporting.feature +++ /dev/null @@ -1,147 +0,0 @@ -Feature: Exporting a Journal - - Scenario: Exporting to json - Given we use the config "tags.yaml" - When we run "jrnl --export 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 "@idea" - And "tags" in the json output should contain "@journal" - And "tags" in the json output should contain "@dan" - And entry 1 should have an array "tags" with 2 elements - And entry 2 should have an array "tags" with 2 elements - - Scenario: Exporting using filters should only export parts of the journal - Given we use the config "tags.yaml" - When we run "jrnl -until 'may 2013' --export json" - Then the output should be parsable as json - And "entries" in the json output should have 1 element - And "tags" in the json output should contain "@idea" - And "tags" in the json output should contain "@journal" - And "tags" in the json output should not contain "@dan" - - Scenario: Exporting using custom templates - Given we use the config "basic.yaml" - Given we load template "sample.template" - When we run "jrnl --export sample" - Then the output should be - """ - My first entry. - --------------- - - Everything is alright - - Life is good. - ------------- - - But I'm better. - """ - - Scenario: Increasing Headings on Markdown export - Given we use the config "markdown-headings-335.yaml" - When we run "jrnl --export markdown" - Then the output should be - """ - # 2015 - - ## April - - ### 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 - """ - - Scenario: Exporting to XML - Given we use the config "tags.yaml" - 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: Exporting tags - Given we use the config "tags.yaml" - When we run "jrnl --export tags" - Then the output should be - """ - @idea : 2 - @journal : 1 - @dan : 1 - """ - - Scenario: Exporting fancy - Given we use the config "tags.yaml" - When we run "jrnl --export fancy" - Then the output should be - """ - ┎──────────────────────────────────────────────────────────────╮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 │ - ┖──────────────────────────────────────────────────────────────────────────────┘ - """ - - Scenario: Export to yaml - Given we use the config "tags.yaml" - And we create cache directory "exported_journal" - When we run "jrnl --export yaml -o {cache_dir}" with cache directory "exported_journal" - Then cache directory "exported_journal" should contain the files - """ - [ - "2013-04-09_i-have-an-idea.md", - "2013-06-10_i-met-with-dan.md" - ] - """ - And the content of file "2013-04-09_i-have-an-idea.md" in cache directory "exported_journal" should be - """ - title: I have an @idea: - date: 2013-04-09 15:39 - starred: False - tags: idea, journal - - (1) write a command line @journal software - (2) ??? - (3) PROFIT! - """ diff --git a/features/file_storage.feature b/features/file_storage.feature new file mode 100644 index 000000000..0e2c0b3ca --- /dev/null +++ b/features/file_storage.feature @@ -0,0 +1,46 @@ +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" diff --git a/features/folder.feature b/features/folder.feature deleted file mode 100644 index 650ac53e8..000000000 --- a/features/folder.feature +++ /dev/null @@ -1,42 +0,0 @@ -Feature: Testing a journal with a root directory and multiple files in the format of yyyy/mm/dd.txt - - Scenario: Opening an folder that's not a DayOne folder should treat as folder journal - 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 we run "jrnl -1" - Then the output should be - """ - 2013-07-23 09:00 Testing folder journal. - """ - - 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: 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. - """ diff --git a/features/format.feature b/features/format.feature new file mode 100644 index 000000000..e689a9f35 --- /dev/null +++ b/features/format.feature @@ -0,0 +1,514 @@ +Feature: Custom formats + + Scenario Outline: JSON format + Given we use the 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 ".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 ".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 ".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 ".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 ".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 ".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 ".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 | + + @todo + Scenario Outline: Exporting fancy + # Needs better emoji support + Given we use the 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 | + + Scenario Outline: Export to yaml + Given we use the 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 + + 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 ".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 + + 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 ".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 ".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 | diff --git a/features/import.feature b/features/import.feature new file mode 100644 index 000000000..63b042fcd --- /dev/null +++ b/features/import.feature @@ -0,0 +1,93 @@ +Feature: Importing data + + Scenario Outline: --import allows new entry from stdin + Given we use the 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 ".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 ".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!" + diff --git a/features/multiple_journals.feature b/features/multiple_journals.feature index 0f41b0d94..6a9efe783 100644 --- a/features/multiple_journals.feature +++ b/features/multiple_journals.feature @@ -3,19 +3,19 @@ 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 + 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 + 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 + And journal "work" should have 1 entry Scenario: Tell user which journal was used Given we use the config "multiple.yaml" @@ -26,8 +26,8 @@ Feature: Multiple journals 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" + And journal "work" should have 1 entry + And journal "work" should contain "2012-07-23" Scenario: Create new journals as required Given we use the config "multiple.yaml" @@ -48,4 +48,4 @@ Feature: Multiple journals these three eyes n """ - Then we should see the message "Encrypted journal 'new_encrypted' created" + Then we should see the message "Encrypted journal 'new_encrypted' created" diff --git a/features/password.feature b/features/password.feature new file mode 100644 index 000000000..86fa7f6bf --- /dev/null +++ b/features/password.feature @@ -0,0 +1,87 @@ +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 + + 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 + # @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: Open encrypted journal when keyring exists but fails + # 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 + + @todo + Scenario: Decrypt journal when keyring exists but fails + # This should ask the user for the password after the keyring fails + + 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" diff --git a/features/regression.feature b/features/regression.feature deleted file mode 100644 index 5342b746b..000000000 --- a/features/regression.feature +++ /dev/null @@ -1,175 +0,0 @@ -Feature: Zapped bugs should stay dead. - - Scenario: Writing an entry does not print the entire journal - # https://github.com/jrnl-org/jrnl/issues/87 - Given we use the config "basic.yaml" - When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." - Then we should see the message "Entry added" - When we run "jrnl -n 1" - Then the output should not contain "Life is good" - - Scenario: Date with time should be parsed correctly - # https://github.com/jrnl-org/jrnl/issues/117 - Given we use the config "basic.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: Loading entry with ambiguous time stamp - #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. - """ - - Scenario: Date in the future should be parsed correctly - # https://github.com/jrnl-org/jrnl/issues/185 - Given we use the config "basic.yaml" - When we run "jrnl 26/06/2019: Planet? Earth. Year? 2019." - Then we should see the message "Entry added" - and the journal should contain "[2019-06-26 09:00] Planet?" - - 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: Title with an embedded period. - Given we use the config "basic.yaml" - When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic." - Then we should see the message "Entry added" - When we run "jrnl -1" - Then the output should be - """ - 2014-04-24 09:00 Created a new website - empty.com. - | Hope to get a lot of traffic. - """ - - 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" - - Scenario: Journals with unreadable dates should still be viewable - Given we use the config "unreadabledates.yaml" - When we run "jrnl -2" - Then the output should contain "I've lost track of time." - Then 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." - When we run "jrnl -1" - Then the output should contain "I'm going to activate the machine." - Then the output should contain "I've crossed so many timelines. Is there any going back?" - - Scenario: Viewing today's entries does not print the entire journal - # https://github.com/jrnl-org/jrnl/issues/741 - Given we use the config "basic.yaml" - When we run "jrnl -on today" - Then the output should not contain "Life is good" - Then the output should not contain "But I'm better." - - Scenario: Create entry using day of the week as entry date. - Given we use the config "basic.yaml" - When we run "jrnl monday: This is an entry on a Monday." - Then we should see the message "Entry added" - When we run "jrnl -1" - Then the output should contain "monday at 9am" in the local time - Then the output should contain "This is an entry on a Monday." - - Scenario: Create entry using day of the week abbreviations as entry date. - Given we use the config "basic.yaml" - When we run "jrnl fri: This is an entry on a Friday." - Then we should see the message "Entry added" - When we run "jrnl -1" - Then the output should contain "friday at 9am" in the local time - - Scenario: Displaying entries using -on today should display entries created today. - Given we use the config "basic.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." - - Scenario: Displaying entries using -from day should display correct entries - Given we use the config "basic.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." - Then the output should contain "A future entry." - Then the output should not contain "This thing happened yesterday" - - Scenario: Displaying entries using -from and -to day should display correct entries - Given we use the config "basic.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" - Then the output should contain "Adding an entry right now." - Then the output should not contain "A future entry." - - # See issues #768 and #881 - # the "deletion" journal is used because it doesn't have a newline at the - # end of the last entry - Scenario: Add a blank line to Markdown export is there isn't one already - Given we use the config "deletion.yaml" - When we run "jrnl --export markdown" - Then the output should be - """ - # 2019 - - ## October - - ### 2019-10-29 11:11 First entry. - - - ### 2019-10-29 11:11 Second entry. - - - ### 2019-10-29 11:13 Third entry. - - """ - - # See issues #768 and #881 - Scenario: Add a blank line to YAML export is there isn't one already - Given we use the config "deletion.yaml" - And we create cache directory "bug768" - When we run "jrnl --export yaml -o {cache_dir}" with cache directory "bug768" - Then cache directory "bug768" should contain the files - """ - [ - "2019-10-29_first-entry.md", - "2019-10-29_second-entry.md", - "2019-10-29_third-entry.md" - ] - """ - And the content of file "2019-10-29_third-entry.md" in cache directory "bug768" should be - """ - title: Third entry. - date: 2019-10-29 11:13 - starred: False - tags: - - """ - - @deployment_tests - Scenario: Version numbers should stay in sync - Given we use the config "basic.yaml" - When we run "jrnl --version" - Then we should get no error - Then the output should contain pyproject.toml version diff --git a/features/search.feature b/features/search.feature new file mode 100644 index 000000000..9d31bb063 --- /dev/null +++ b/features/search.feature @@ -0,0 +1,228 @@ +Feature: Searching in a journal + + Scenario Outline: Displaying entries using -on today should display entries created today + Given we use the 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 ".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 ".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 ".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 ".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 ".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 ".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 ".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 ".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 ".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 ".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 ".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: 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! + """ diff --git a/features/star.feature b/features/star.feature new file mode 100644 index 000000000..f01880564 --- /dev/null +++ b/features/star.feature @@ -0,0 +1,35 @@ +Feature: Starring entries + + Scenario Outline: Starring an entry will mark it in the journal file + Given we use the config ".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 ".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!" diff --git a/features/starring.feature b/features/starring.feature deleted file mode 100644 index 18113dc32..000000000 --- a/features/starring.feature +++ /dev/null @@ -1,20 +0,0 @@ -Feature: Starring entries - - Scenario: Starring an entry will mark it in the journal file - Given we use the config "basic.yaml" - When we run "jrnl 20 july 2013 *: Best day of my life!" - Then we should see the message "Entry added" - and the journal should contain "[2013-07-20 09:00] Best day of my life! *" - - Scenario: Filtering by starred entries - Given we use the config "basic.yaml" - When we run "jrnl -starred" - Then the output should be - """ - """ - 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! - """ diff --git a/features/steps/core.py b/features/steps/core.py index f82cf8cd0..8b49cbb27 100644 --- a/features/steps/core.py +++ b/features/steps/core.py @@ -64,7 +64,26 @@ def delete_password(self, servicename, username): raise keyring.errors.NoKeyringError -# set the keyring for keyring lib +class FailedKeyring(keyring.backend.KeyringBackend): + """ + A keyring that simulates an environment with a keyring that has passwords, but fails + to return them. + """ + + priority = 2 + keys = defaultdict(dict) + + def set_password(self, servicename, username, password): + self.keys[servicename][username] = password + + def get_password(self, servicename, username): + raise keyring.errors.NoKeyringError + + def delete_password(self, servicename, username): + self.keys[servicename][username] = None + + +# set a default keyring keyring.set_keyring(TestKeyring()) @@ -93,16 +112,48 @@ def open_journal(journal_name="default"): return Journal.open_journal(journal_name, config) +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 + t, value = string.split(":") + value = {"bool": lambda v: v.lower() == "true", "int": int, "str": str}[t](value) + return value + + @given('we use the config "{config_file}"') def set_config(context, config_file): full_path = os.path.join("features/configs", config_file) + install.CONFIG_FILE_PATH = os.path.abspath(full_path) - if config_file.endswith("yaml"): + if config_file.endswith("yaml") and os.path.exists(full_path): # Add jrnl version to file for 2.x journals with open(install.CONFIG_FILE_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") +def set_keyring(context): + keyring.set_keyring(TestKeyring()) + + +@given("we do not have a keyring") +def disable_keyring(context): + keyring.core.set_keyring(NoKeyring()) + + @when('we change directory to "{path}"') def move_up_dir(context, path): os.chdir(path) @@ -122,7 +173,7 @@ def open_editor_and_enter(context, method, text=""): else: file_method = "r+" - def _mock_editor_function(command): + def _mock_editor(command): context.editor_command = command tmpfile = command[-1] with open(tmpfile, file_method) as f: @@ -130,19 +181,36 @@ def _mock_editor_function(command): 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_function), \ + 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) \ : + context.editor = mock_editor + context.getpass = mock_getpass cli(["--edit"]) # 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): - assert len(context.editor_command) == int(num) +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}"') @@ -156,25 +224,32 @@ def contains_editor_arg(context, arg): @then('one editor argument should match "{regex}"') def matches_editor_arg(context, regex): args = context.editor_command - matches = list(filter(lambda x: re.match(regex, x), args)) + 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)}" def _mock_getpass(inputs): - def prompt_return(prompt="Password: "): - print(prompt) - return next(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=""): - val = next(inputs) - print(prompt, val) - return val + try: + val = next(inputs) + print(prompt, val) + return val + except StopIteration: + raise KeyboardInterrupt return prompt_return @@ -192,12 +267,24 @@ def run_with_input(context, command, inputs=""): args = ushlex(command)[1:] + def _mock_editor(command): + context.editor_command = command + tmpfile = command[-1] + context.editor_file = tmpfile + 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(text)) as mock_getpass, \ - patch("sys.stdin.read", side_effect=text) as mock_read \ + 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 \ : try: cli(args or []) @@ -205,26 +292,56 @@ def run_with_input(context, command, inputs=""): except SystemExit as e: context.exit_status = e.code - # at least one of the mocked input methods got called - assert mock_input.called or mock_getpass.called or mock_read.called - # all inputs were used - try: - next(text) - assert False, "Not all inputs were consumed" - except StopIteration: - pass + # 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}"') -@when('we run "{command}" with cache directory "{cache_dir}"') -def run(context, command, text="", cache_dir=None): +def run(context, command, text=""): text = text or context.text or "" - if cache_dir is not None: - cache_dir = os.path.join("features", "cache", cache_dir) + 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) args = ushlex(command) @@ -232,12 +349,23 @@ def run(context, command, text="", cache_dir=None): def _mock_editor(command): context.editor_command = command + if "password" in context: + password = context.password + else: + password = iter(text) + try: - with patch("sys.argv", args), patch( - "subprocess.call", side_effect=_mock_editor - ), patch("sys.stdin.read", side_effect=lambda: text): + # fmt: off + # see: https://github.com/psf/black/issues/664 + with \ + patch("sys.argv", args), \ + patch("getpass.getpass", side_effect=_mock_getpass(password)), \ + patch("subprocess.call", side_effect=_mock_editor), \ + patch("sys.stdin.read", side_effect=lambda: text) \ + : cli(args[1:]) context.exit_status = 0 + # fmt: on except SystemExit as e: context.exit_status = e.code @@ -249,16 +377,11 @@ def load_template(context, filename): plugins.__exporter_types[exporter.names[0]] = exporter -@when('we set the keychain password of "{journal}" to "{password}"') -def set_keychain(context, journal, password): +@when('we set the keyring password of "{journal}" to "{password}"') +def set_keyring_password(context, journal, password): keyring.set_password("jrnl", journal, password) -@when("we disable the keychain") -def disable_keychain(context): - keyring.core.set_keyring(NoKeyring()) - - @then("we should get an error") def has_error(context): assert context.exit_status != 0, context.exit_status @@ -269,10 +392,33 @@ 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).strip().splitlines() + 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) @@ -316,7 +462,27 @@ def check_output_inline(context, text=None, text2=None): def check_error_output_inline(context, text=None, text2=None): text = text or context.text out = context.stderr_capture.getvalue() - assert text in out or text2 in out, text or text2 + 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}"') @@ -326,6 +492,7 @@ def check_output_not_inline(context, text): @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] @@ -351,33 +518,48 @@ def check_not_journal_content(context, text, journal_name="default"): 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"): - with open(install.CONFIG_FILE_PATH) as config_file: - config = yaml.load(config_file, Loader=yaml.FullLoader) + config = load_config(install.CONFIG_FILE_PATH) + journal_path = config["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"): + config = load_config(install.CONFIG_FILE_PATH) + + journal_path = config["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): - if not value[0] == "{": - t, value = value.split(":") - value = {"bool": lambda v: v.lower() == "true", "int": int, "str": str}[t]( - value - ) - else: - # Handle value being a dictionary - value = ast.literal_eval(value) - +def config_var(context, key, value="", journal=None): + value = read_value_from_string(value or context.text or "") config = load_config(install.CONFIG_FILE_PATH) + if journal: config = config["journals"][journal] + assert key in config assert config[key] == value +@then('the config for journal "{journal}" should not have "{key}" set') +def config_no_var(context, key, value="", journal=None): + config = load_config(install.CONFIG_FILE_PATH) + + if journal: + config = config["journals"][journal] + + assert key not in config + + @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') @@ -397,21 +579,6 @@ def list_journal_directory(context, journal="default"): print(os.path.join(root, file)) -@then("the Python version warning should appear if our version is below {version}") -def check_python_warning_if_version_low_enough(context, version): - import platform - - import packaging.version - - if packaging.version.parse(platform.python_version()) < packaging.version.parse( - version - ): - out = context.stderr_capture.getvalue() - assert "WARNING: Python versions" in out - else: - assert True - - @then("fail") def debug_fail(context): assert False diff --git a/features/steps/export_steps.py b/features/steps/export_steps.py index d75aea64e..9003c1bda 100644 --- a/features/steps/export_steps.py +++ b/features/steps/export_steps.py @@ -1,6 +1,8 @@ import json import os import shutil +import random +import string from xml.etree import ElementTree from behave import given @@ -116,23 +118,32 @@ def assert_xml_output_tags(context, expected_tags_json_list): @given('we create cache directory "{dir_name}"') -def create_directory(context, 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 directory "{dir_name}" should contain the files') -@then( - 'cache directory "{dir_name}" should contain the files {expected_files_json_list}' -) -def assert_dir_contains_files(context, dir_name, expected_files_json_list="[]"): +@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 = json.loads(expected_files) + expected_files = expected_files.split("\n") # sort to deal with inconsistent default file ordering on different OS's actual_files.sort() @@ -142,7 +153,11 @@ def assert_dir_contains_files(context, dir_name, expected_files_json_list="[]"): @then('the content of file "{file_path}" in cache directory "{cache_dir}" should be') -def assert_exported_yaml_file_content(context, file_path, cache_dir): +@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) diff --git a/features/tag.feature b/features/tag.feature new file mode 100644 index 000000000..b7b687b53 --- /dev/null +++ b/features/tag.feature @@ -0,0 +1,53 @@ +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 ".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 ".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 ".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 | diff --git a/features/tagging.feature b/features/tagging.feature deleted file mode 100644 index c96273c5c..000000000 --- a/features/tagging.feature +++ /dev/null @@ -1,121 +0,0 @@ -Feature: Tagging - - Scenario: Displaying tags - Given we use the config "tags.yaml" - When we run "jrnl --tags" - Then we should get no error - and the output should be - """ - @idea : 2 - @journal : 1 - @dan : 1 - """ - - Scenario: Filtering journals should also filter tags - Given we use the config "tags.yaml" - When we run "jrnl -from 'may 2013' --tags" - Then we should get no error - and the output should be - """ - @idea : 1 - @dan : 1 - """ - - Scenario: Tags should allow certain special characters - Given we use the config "tags-216.yaml" - When we run "jrnl --tags" - Then we should get no error - and the output should be - """ - @os/2 : 1 - @c++ : 1 - @c# : 1 - """ - Scenario: An email should not be a tag - Given we use the config "tags-237.yaml" - When we run "jrnl --tags" - Then we should get no error - and the output should be - """ - @newline : 1 - @email : 1 - """ - - Scenario: Entry cans start and end with tags - Given we use the config "basic.yaml" - When we run "jrnl today: @foo came over, we went to a @bar" - When we run "jrnl --tags" - Then the output should be - """ - @foo : 1 - @bar : 1 - """ - - Scenario: Excluding a tag should filter it - Given we use the config "basic.yaml" - When we run "jrnl today: @foo came over, we went to a bar" - When we run "jrnl I have decided I did not enjoy that @bar" - When we run "jrnl --tags -not @bar" - Then the output should be - """ - @foo : 1 - """ - - Scenario: Excluding a tag should filter an entry, even if an unfiltered tag is in that entry - Given we use the config "basic.yaml" - When we run "jrnl today: I do @not think this will show up @thought" - When we run "jrnl today: I think this will show up @thought" - When we run "jrnl --tags -not @not" - Then the output should be - """ - @thought : 1 - """ - - Scenario: Excluding multiple tags should filter them - Given we use the config "basic.yaml" - When we run "jrnl today: I do @not think this will show up @thought" - When we run "jrnl today: I think this will show up @thought" - When we run "jrnl today: This should @never show up @thought" - When we run "jrnl today: What a nice day for filtering @thought" - When we run "jrnl --tags -not @not -not @never" - Then the output should be - """ - @thought : 2 - """ - - - Scenario: Printing a journal that has multiline entries with tags - Given we use the config "multiline-tags.yaml" - When we run "jrnl -n 1" - Then we should get no error - and the output should be - """ - 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 - """ - - Scenario: Searching a journal for tags should display entries with that tag. - Given we use the config "tags.yaml" - When we run "jrnl @dan" - Then the output should be - """ - 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 - """ - - Scenario: Searching a journal for multiple tags with -and should display entries with those tags. - Given we use the config "tags.yaml" - When we run "jrnl -and @idea @journal" - Then the output should be - """ - 2013-04-09 15:39 I have an @idea: - | (1) write a command line @journal software - | (2) ??? - | (3) PROFIT! - """ diff --git a/features/upgrade.feature b/features/upgrade.feature index b0a54c160..fda47363b 100644 --- a/features/upgrade.feature +++ b/features/upgrade.feature @@ -3,57 +3,69 @@ Feature: Upgrading Journals from 1.x.x to 2.x.x Scenario: Upgrade and parse journals with square brackets Given we use the config "upgrade_from_195.json" When we run "jrnl -9" and enter "Y" - Then the output should contain - """ - 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". - """ Then the journal should have 2 entries + And the output should contain + """ + 2010-06-10 15:00 A life without chocolate is like a bad analogy. + """ + And the output should contain + """ + 2013-06-10 15:40 He said "[this] is the best time to be alive". + """ Scenario: Upgrading a journal encrypted with jrnl 1.x Given we use the config "encrypted_old.json" When we run "jrnl -n 1" and enter - """ - Y - bad doggie no biscuit - bad doggie no biscuit - """ - Then the output should contain "Password" - and the output should contain "2013-06-10 15:40 Life is good" + """ + Y + bad doggie no biscuit + bad doggie no biscuit + """ + Then we should be prompted for a password + And the output should contain "2013-06-10 15:40 Life is good" Scenario: Upgrading a config without colors to colors Given we use the config "no_colors.yaml" When we run "jrnl -n 1" - Then the config should have "colors" set to "{'date':'none', 'title':'none', 'body':'none', 'tags':'none'}" + Then the config should have "colors" set to + """ + { + 'date':'none', + 'title':'none', + 'body':'none', + 'tags':'none' + } + """ Scenario: Upgrade and parse journals with little endian date format Given we use the config "upgrade_from_195_little_endian_dates.json" When we run "jrnl -9" and enter "Y" - Then the output should contain - """ - 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". - """ Then the journal should have 2 entries + And the output should contain + """ + 10.06.2010 15:00 A life without chocolate is like a bad analogy. + """ + And the output should contain + """ + 10.06.2013 15:40 He said "[this] is the best time to be alive". + """ Scenario: Upgrade with missing journal Given we use the config "upgrade_from_195_with_missing_journal.json" When we run "jrnl -ls" and enter - """" - Y - """ + """" + Y + """ Then the output should contain "Error: features/journals/missing.journal does not exist." And we should get no error Scenario: Upgrade with missing encrypted journal Given we use the config "upgrade_from_195_with_missing_encrypted_journal.json" When we run "jrnl -ls" and enter - """ - Y - bad doggie no biscuit - """ + """ + Y + bad doggie no biscuit + """ Then the output should contain "Error: features/journals/missing.journal does not exist." And the error output should contain "We're all done" And we should get no error diff --git a/features/write.feature b/features/write.feature new file mode 100644 index 000000000..1e6a2d09b --- /dev/null +++ b/features/write.feature @@ -0,0 +1,182 @@ +Feature: Writing new entries. + + Scenario Outline: Multiline entry with punctuation should keep title punctuation + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl This is. the title\\n This is the second line" + And we run "jrnl -n 1" + Then the output should contain "This is. the title" + + Examples: configs + | config_file | + | simple | + | empty_folder | + | dayone | + | encrypted | + + Scenario Outline: Single line entry with period should be split at period + Given we use the config ".yaml" + And we use the password "test" if prompted + When we run "jrnl This is. the title" + And we run "jrnl -1" + Then the output should contain "| the title" + + Examples: configs + | config_file | + | basic_onefile | + | basic_encrypted | + | basic_folder | + | basic_dayone | + + Scenario Outline: Writing an entry from command line should store the entry + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." + Then we should see the message "Entry added" + When we run "jrnl -n 1" + Then the output should contain "2013-07-23 09:00 A cold and stormy day." + + Examples: configs + | config_file | + | simple | + | empty_folder | + | dayone | + | encrypted | + + Scenario Outline: Writing an empty entry from the editor should yield "Nothing saved to file" message + Given we use the config ".yaml" + And we use the password "test" if prompted + When we open the editor and enter nothing + Then the error output should contain "[Nothing saved to file]" + + Examples: configs + | config_file | + | editor | + | editor_empty_folder | + | dayone | + | basic_encrypted | + | basic_onefile | + + @skip_win # @todo This fails only on Travis Windows + Scenario Outline: Writing an empty entry from the command line with no editor should yield nothing + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl" and enter nothing + Then the output should be empty + And the error output should contain "Writing Entry; on a blank line" + And the editor should not have been called + + Examples: configs + | config_file | + | simple | + | empty_folder | + | encrypted | + # | dayone | @todo + + Scenario Outline: Writing an entry does not print the entire journal + # https://github.com/jrnl-org/jrnl/issues/87 + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa." + Then we should see the message "Entry added" + When we run "jrnl -n 1" + Then the output should not contain "Life is good" + + Examples: configs + | config_file | + | editor | + | editor_empty_folder | + | dayone | + | encrypted | + + Scenario Outline: Embedded period stays in title + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic." + Then we should see the message "Entry added" + When we run "jrnl -1" + Then the output should be + """ + 2014-04-24 09:00 Created a new website - empty.com. + | Hope to get a lot of traffic. + """ + + Examples: configs + | config_file | + | simple | + | empty_folder | + | dayone | + | encrypted | + + Scenario Outline: Write and read emoji support + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘" + Then we should see the message "Entry added" + When we run "jrnl -n 1" + Then the output should contain "🌞" + And the output should contain "🐘" + + Examples: configs + | config_file | + | simple | + | empty_folder | + | dayone | + | encrypted | + + Scenario Outline: Writing an entry at the prompt (no editor) should store the entry + Given we use the config ".yaml" + And we use the password "bad doggie no biscuit" if prompted + When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive." + Then we should get no error + When we run "jrnl -on '2013-07-25'" + Then the output should contain "2013-07-25 09:00 I saw Elvis." + And the output should contain "| He's alive." + + Examples: configs + | config_file | + | simple | + | empty_folder | + | encrypted | + + @todo + Scenario: Writing an entry at the prompt (no editor) in DayOne journal + # Need to test DayOne w/out an editor + + Scenario: Writing into Dayone + Given we use the config "dayone.yaml" + When we run "jrnl 01 may 1979: Being born hurts." + And we run "jrnl -until 1980" + Then the output should be "1979-05-01 09:00 Being born hurts." + + Scenario: Writing into Dayone adds extended metadata + Given we use the config "dayone.yaml" + When we run "jrnl 01 may 1979: Being born hurts." + And we run "jrnl --export json" + Then "entries" in the json output should have 5 elements + And the json output should contain entries.0.creator.software_agent + And the json output should contain entries.0.creator.os_agent + And the json output should contain entries.0.creator.host_name + And the json output should contain entries.0.creator.generation_date + And the json output should contain entries.0.creator.device_agent + And "entries.0.creator.software_agent" in the json output should contain "jrnl" + + # fails when system time is UTC (as on Travis-CI) + @skip + Scenario: Title with an embedded period on DayOne journal + Given we use the config "dayone.yaml" + When we run "jrnl 04-24-2014: "Ran 6.2 miles today in 1:02:03. I'm feeling sore because I forgot to stretch."" + Then we should see the message "Entry added" + When we run "jrnl -1" + Then the output should be + """ + 2014-04-24 09:00 Ran 6.2 miles today in 1:02:03. + | I'm feeling sore because I forgot to stretch. + """ + + Scenario: Opening an folder that's not a DayOne folder should treat as folder journal + 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 we run "jrnl -1" + Then the output should be "2013-07-23 09:00 Testing folder journal."