mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 08:38:32 +02:00
Improve handling of mocking logic in pytest (#1382)
* WIP * fix handling of user input (stdin, input, getpass) * take out redundant pytest step * fix handling of 'we should' statements * fix test that doesn't use a config file * fix another test that uses stdin Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com> * remove .tool-versions file per PR feedback * add comment to clarify why disembodied variables are here Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
parent
3518e37087
commit
2ab485de8c
16 changed files with 259 additions and 197 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
.python-version
|
|
||||||
|
|
||||||
# Packages
|
# Packages
|
||||||
*.egg
|
*.egg
|
||||||
|
@ -17,7 +16,10 @@ sdist
|
||||||
develop-eggs
|
develop-eggs
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
lib64
|
lib64
|
||||||
|
|
||||||
|
# Versioning
|
||||||
.python-version
|
.python-version
|
||||||
|
.tool-version
|
||||||
|
|
||||||
# Installer logs
|
# Installer logs
|
||||||
pip-log.txt
|
pip-log.txt
|
||||||
|
|
|
@ -29,7 +29,7 @@ Feature: Multiple journals
|
||||||
Given the config "multiple.yaml" exists
|
Given the config "multiple.yaml" exists
|
||||||
And we use the config "basic_onefile.yaml"
|
And we use the config "basic_onefile.yaml"
|
||||||
When we run "jrnl --cf multiple.yaml work a long day in the office"
|
When we run "jrnl --cf multiple.yaml work a long day in the office"
|
||||||
Then we should see the message "Entry added to work journal"
|
Then the output should contain "Entry added to work journal"
|
||||||
|
|
||||||
Scenario: Write to specified journal with a timestamp using an alternate config
|
Scenario: Write to specified journal with a timestamp using an alternate config
|
||||||
Given the config "multiple.yaml" exists
|
Given the config "multiple.yaml" exists
|
||||||
|
@ -64,7 +64,7 @@ Feature: Multiple journals
|
||||||
Given the config "bug343.yaml" exists
|
Given the config "bug343.yaml" exists
|
||||||
And we use the config "basic_onefile.yaml"
|
And we use the config "basic_onefile.yaml"
|
||||||
When we run "jrnl --cf bug343.yaml a long day in the office"
|
When we run "jrnl --cf bug343.yaml a long day in the office"
|
||||||
Then we should see the message "No default journal configured"
|
Then the output should contain "No default journal configured"
|
||||||
|
|
||||||
Scenario: Don't crash if no file exists for a configured encrypted journal using an alternate config
|
Scenario: Don't crash if no file exists for a configured encrypted journal using an alternate config
|
||||||
Given the config "multiple.yaml" exists
|
Given the config "multiple.yaml" exists
|
||||||
|
@ -73,7 +73,7 @@ Feature: Multiple journals
|
||||||
these three eyes
|
these three eyes
|
||||||
these three eyes
|
these three eyes
|
||||||
n
|
n
|
||||||
Then we should see the message "Encrypted journal 'new_encrypted' created"
|
Then the output should contain "Encrypted journal 'new_encrypted' created"
|
||||||
|
|
||||||
Scenario: Don't overwrite main config when encrypting a journal in an alternate config
|
Scenario: Don't overwrite main config when encrypting a journal in an alternate config
|
||||||
Given the config "basic_onefile.yaml" exists
|
Given the config "basic_onefile.yaml" exists
|
||||||
|
@ -82,11 +82,14 @@ Feature: Multiple journals
|
||||||
these three eyes
|
these three eyes
|
||||||
these three eyes
|
these three eyes
|
||||||
n
|
n
|
||||||
Then we should see the message "Journal encrypted to features/journals/basic_onefile.journal"
|
Then the output should contain "Journal encrypted to features/journals/basic_onefile.journal"
|
||||||
And the config should contain "encrypt: false" # multiple.yaml remains unchanged
|
And the config should contain "encrypt: false"
|
||||||
|
|
||||||
|
|
||||||
Scenario: Don't overwrite main config when decrypting a journal in an alternate config
|
Scenario: Don't overwrite main config when decrypting a journal in an alternate config
|
||||||
Given the config "editor_encrypted.yaml" exists
|
Given the config "editor_encrypted.yaml" exists
|
||||||
|
And we use the password "bad doggie no biscuit" if prompted
|
||||||
And we use the config "basic_encrypted.yaml"
|
And we use the config "basic_encrypted.yaml"
|
||||||
When we run "jrnl --cf editor_encrypted.yaml --decrypt"
|
When we run "jrnl --cf editor_encrypted.yaml --decrypt"
|
||||||
Then the config should contain "encrypt: true" # basic_encrypted remains unchanged
|
Then the config should contain "encrypt: true"
|
||||||
|
And the output should not contain "Wrong password"
|
||||||
|
|
|
@ -4,7 +4,7 @@ Feature: Reading and writing to journal with custom date formats
|
||||||
# https://github.com/jrnl-org/jrnl/issues/117
|
# https://github.com/jrnl-org/jrnl/issues/117
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
When we run "jrnl 2013-11-30 15:42: Project Started."
|
When we run "jrnl 2013-11-30 15:42: Project Started."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -999"
|
When we run "jrnl -999"
|
||||||
Then the output should contain "2013-11-30 15:42 Project Started."
|
Then the output should contain "2013-11-30 15:42 Project Started."
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ Feature: Reading and writing to journal with custom date formats
|
||||||
# https://github.com/jrnl-org/jrnl/issues/185
|
# https://github.com/jrnl-org/jrnl/issues/185
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
When we run "jrnl 26/06/2099: Planet? Earth. Year? 2099."
|
When we run "jrnl 26/06/2099: Planet? Earth. Year? 2099."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -999"
|
When we run "jrnl -999"
|
||||||
Then the output should contain "2099-06-26 09:00 Planet?"
|
Then the output should contain "2099-06-26 09:00 Planet?"
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ Feature: Reading and writing to journal with custom date formats
|
||||||
Scenario Outline: Writing an entry from command line with custom date
|
Scenario Outline: Writing an entry from command line with custom date
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl <command>"
|
When we run "jrnl <command>"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -n 1"
|
When we run "jrnl -n 1"
|
||||||
Then the output should contain "<expected_output>"
|
Then the output should contain "<expected_output>"
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ Feature: Reading and writing to journal with custom date formats
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
And now is "2019-03-12 01:30:32 PM"
|
And now is "2019-03-12 01:30:32 PM"
|
||||||
When we run "jrnl <command>"
|
When we run "jrnl <command>"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
Then the output should contain "<expected_output>"
|
Then the output should contain "<expected_output>"
|
||||||
Then the output should contain the date "<date>"
|
Then the output should contain the date "<date>"
|
||||||
|
@ -109,7 +109,7 @@ Feature: Reading and writing to journal with custom date formats
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
And now is "2019-03-12 01:30:32 PM"
|
And now is "2019-03-12 01:30:32 PM"
|
||||||
When we run "jrnl <command>"
|
When we run "jrnl <command>"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
Then the output should contain "<expected_output>"
|
Then the output should contain "<expected_output>"
|
||||||
Then the output should contain the date "<date>"
|
Then the output should contain the date "<date>"
|
||||||
|
|
|
@ -2,8 +2,9 @@ Feature: Encrypting and decrypting journals
|
||||||
|
|
||||||
Scenario: Decrypting a journal
|
Scenario: Decrypting a journal
|
||||||
Given we use the config "encrypted.yaml"
|
Given we use the config "encrypted.yaml"
|
||||||
|
# And we use the password "bad doggie no biscuit" if prompted
|
||||||
When we run "jrnl --decrypt" and enter "bad doggie no biscuit"
|
When we run "jrnl --decrypt" and enter "bad doggie no biscuit"
|
||||||
Then we should see the message "Journal decrypted"
|
Then the output should contain "Journal decrypted"
|
||||||
And the config for journal "default" should contain "encrypt: false"
|
And the config for journal "default" should contain "encrypt: false"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
|
@ -35,7 +36,7 @@ Feature: Encrypting and decrypting journals
|
||||||
swordfish
|
swordfish
|
||||||
n
|
n
|
||||||
Then we should get no error
|
Then we should get no error
|
||||||
And we should see the message "Journal encrypted"
|
And the output should contain "Journal encrypted"
|
||||||
And the config for journal "default" should contain "encrypt: true"
|
And the config for journal "default" should contain "encrypt: true"
|
||||||
When we run "jrnl -n 1" and enter "swordfish"
|
When we run "jrnl -n 1" and enter "swordfish"
|
||||||
Then we should be prompted for a password
|
Then we should be prompted for a password
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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
|
Scenario: Adding entries to a Folder journal should generate date files
|
||||||
Given we use the config "empty_folder.yaml"
|
Given we use the config "empty_folder.yaml"
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
When we run "jrnl 23 July 2013: Testing folder journal."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
And the journal directory should contain
|
And the journal directory should contain
|
||||||
2013/07/23.txt
|
2013/07/23.txt
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ Feature: Journals iteracting with the file system in a way that users can see
|
||||||
Given we use the config "empty_folder.yaml"
|
Given we use the config "empty_folder.yaml"
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
When we run "jrnl 23 July 2013: Testing folder journal."
|
||||||
And we run "jrnl 3/7/2014: Second entry of journal."
|
And we run "jrnl 3/7/2014: Second entry of journal."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
And the journal directory should contain
|
And the journal directory should contain
|
||||||
2013/07/23.txt
|
2013/07/23.txt
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ Feature: Journals iteracting with the file system in a way that users can see
|
||||||
Then the output should contain "This is a new entry in my journal"
|
Then the output should contain "This is a new entry in my journal"
|
||||||
|
|
||||||
Scenario: Creating journal with relative path should update to absolute path
|
Scenario: Creating journal with relative path should update to absolute path
|
||||||
|
Given we use no config
|
||||||
When we run "jrnl hello world" and enter
|
When we run "jrnl hello world" and enter
|
||||||
test.txt
|
test.txt
|
||||||
n
|
n
|
||||||
|
|
|
@ -34,7 +34,7 @@ Feature: Multiple journals
|
||||||
Scenario: Tell user which journal was used
|
Scenario: Tell user which journal was used
|
||||||
Given we use the config "multiple.yaml"
|
Given we use the config "multiple.yaml"
|
||||||
When we run "jrnl work a long day in the office"
|
When we run "jrnl work a long day in the office"
|
||||||
Then we should see the message "Entry added to work journal"
|
Then the output should contain "Entry added to work journal"
|
||||||
|
|
||||||
Scenario: Write to specified journal with a timestamp
|
Scenario: Write to specified journal with a timestamp
|
||||||
Given we use the config "multiple.yaml"
|
Given we use the config "multiple.yaml"
|
||||||
|
|
|
@ -3,9 +3,12 @@ Feature: Implementing Runtime Overrides for Select Configuration Keys
|
||||||
Scenario: Override configured editor with built-in input === editor:''
|
Scenario: Override configured editor with built-in input === editor:''
|
||||||
Given we use the config "basic_encrypted.yaml"
|
Given we use the config "basic_encrypted.yaml"
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --config-override editor ''"
|
When we run "jrnl --config-override editor ''" and enter
|
||||||
|
This is a journal entry
|
||||||
Then the stdin prompt should have been called
|
Then the stdin prompt should have been called
|
||||||
And the editor should not have been called
|
And the editor should not have been called
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "This is a journal entry"
|
||||||
|
|
||||||
|
|
||||||
Scenario: Postconfig commands with overrides
|
Scenario: Postconfig commands with overrides
|
||||||
|
@ -61,7 +64,7 @@ Feature: Implementing Runtime Overrides for Select Configuration Keys
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --config-override journals.default features/journals/simple.journal 20 Mar 2000: The rain in Spain comes from clouds"
|
When we run "jrnl --config-override journals.default features/journals/simple.journal 20 Mar 2000: The rain in Spain comes from clouds"
|
||||||
Then we should get no error
|
Then we should get no error
|
||||||
And we should see the message "Entry added"
|
And the output should contain "Entry added"
|
||||||
When we run "jrnl -3 --config-override journals.default features/journals/simple.journal"
|
When we run "jrnl -3 --config-override journals.default features/journals/simple.journal"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2000-03-20 09:00 The rain in Spain comes from clouds
|
2000-03-20 09:00 The rain in Spain comes from clouds
|
||||||
|
@ -78,7 +81,7 @@ Feature: Implementing Runtime Overrides for Select Configuration Keys
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp Sep 06 1969: @say Ni"
|
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp Sep 06 1969: @say Ni"
|
||||||
Then we should get no error
|
Then we should get no error
|
||||||
And we should see the message "Entry added"
|
And the output should contain "Entry added"
|
||||||
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp -3"
|
When we run "jrnl --config-override journals.temp features/journals/simple.journal temp -3"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
1969-09-06 09:00 @say Ni
|
1969-09-06 09:00 @say Ni
|
||||||
|
|
|
@ -55,7 +55,7 @@ Feature: Using the installed keyring
|
||||||
this password will not be saved in keyring
|
this password will not be saved in keyring
|
||||||
this password will not be saved in keyring
|
this password will not be saved in keyring
|
||||||
y
|
y
|
||||||
Then we should see the message "Failed to retrieve keyring"
|
Then the output should contain "Failed to retrieve keyring"
|
||||||
And we should get no error
|
And we should get no error
|
||||||
And we should be prompted for a password
|
And we should be prompted for a password
|
||||||
And the config for journal "default" should contain "encrypt: true"
|
And the config for journal "default" should contain "encrypt: true"
|
||||||
|
@ -69,7 +69,7 @@ Feature: Using the installed keyring
|
||||||
Then the error output should contain "Failed to retrieve keyring"
|
Then the error output should contain "Failed to retrieve keyring"
|
||||||
And we should get no error
|
And we should get no error
|
||||||
And we should be prompted for a password
|
And we should be prompted for a password
|
||||||
And we should see the message "Journal decrypted"
|
And the output should contain "Journal decrypted"
|
||||||
And the config for journal "default" should contain "encrypt: false"
|
And the config for journal "default" should contain "encrypt: false"
|
||||||
When we run "jrnl --short"
|
When we run "jrnl --short"
|
||||||
Then we should not be prompted for a password
|
Then we should not be prompted for a password
|
||||||
|
@ -96,7 +96,7 @@ Feature: Using the installed keyring
|
||||||
swordfish
|
swordfish
|
||||||
sordfish
|
sordfish
|
||||||
Then we should be prompted for a password
|
Then we should be prompted for a password
|
||||||
And we should see the message "Passwords did not match"
|
And the output should contain "Passwords did not match"
|
||||||
And the config for journal "default" should not contain "encrypt: true"
|
And the config for journal "default" should not contain "encrypt: true"
|
||||||
When we run "jrnl --short"
|
When we run "jrnl --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
|
@ -113,8 +113,8 @@ Feature: Using the installed keyring
|
||||||
swordfish
|
swordfish
|
||||||
n
|
n
|
||||||
Then we should be prompted for a password
|
Then we should be prompted for a password
|
||||||
And we should see the message "Passwords did not match"
|
And the output should contain "Passwords did not match"
|
||||||
And we should see the message "Journal encrypted"
|
And the output should contain "Journal encrypted"
|
||||||
And the config for journal "default" should contain "encrypt: true"
|
And the config for journal "default" should contain "encrypt: true"
|
||||||
When we run "jrnl -1" and enter "swordfish"
|
When we run "jrnl -1" and enter "swordfish"
|
||||||
Then we should be prompted for a password
|
Then we should be prompted for a password
|
||||||
|
|
|
@ -3,7 +3,7 @@ Feature: Searching in a journal
|
||||||
Scenario Outline: Displaying entries using -on today should display entries created today
|
Scenario Outline: Displaying entries using -on today should display entries created today
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl today: Adding an entry right now."
|
When we run "jrnl today: Adding an entry right now."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -on today"
|
When we run "jrnl -on today"
|
||||||
Then the output should contain "Adding an entry right now."
|
Then the output should contain "Adding an entry right now."
|
||||||
But the output should not contain "Everything is alright"
|
But the output should not contain "Everything is alright"
|
||||||
|
@ -18,11 +18,11 @@ Feature: Searching in a journal
|
||||||
Scenario Outline: Displaying entries using -from day should display correct entries
|
Scenario Outline: Displaying entries using -from day should display correct entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl yesterday: This thing happened yesterday"
|
When we run "jrnl yesterday: This thing happened yesterday"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl tomorrow: A future entry."
|
When we run "jrnl tomorrow: A future entry."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -from today"
|
When we run "jrnl -from today"
|
||||||
Then the output should contain "Adding an entry right now."
|
Then the output should contain "Adding an entry right now."
|
||||||
And the output should contain "A future entry."
|
And the output should contain "A future entry."
|
||||||
|
@ -37,11 +37,11 @@ Feature: Searching in a journal
|
||||||
Scenario Outline: Displaying entries using -from and -to day should display correct entries
|
Scenario Outline: Displaying entries using -from and -to day should display correct entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl yesterday: This thing happened yesterday"
|
When we run "jrnl yesterday: This thing happened yesterday"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl tomorrow: A future entry."
|
When we run "jrnl tomorrow: A future entry."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -from yesterday -to today"
|
When we run "jrnl -from yesterday -to today"
|
||||||
Then the output should contain "This thing happened yesterday"
|
Then the output should contain "This thing happened yesterday"
|
||||||
And the output should contain "Adding an entry right now."
|
And the output should contain "Adding an entry right now."
|
||||||
|
@ -118,9 +118,9 @@ Feature: Searching in a journal
|
||||||
Scenario: Out of order entries to a Folder journal should be listed in date order
|
Scenario: Out of order entries to a Folder journal should be listed in date order
|
||||||
Given we use the config "empty_folder.yaml"
|
Given we use the config "empty_folder.yaml"
|
||||||
When we run "jrnl 3/7/2014 4:37pm: Second entry of journal."
|
When we run "jrnl 3/7/2014 4:37pm: Second entry of journal."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl 23 July 2013: Testing folder journal."
|
When we run "jrnl 23 July 2013: Testing folder journal."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -2"
|
When we run "jrnl -2"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2013-07-23 09:00 Testing folder journal.
|
2013-07-23 09:00 Testing folder journal.
|
||||||
|
|
|
@ -3,7 +3,7 @@ Feature: Starring entries
|
||||||
Scenario Outline: Starring an entry will mark it in the journal file
|
Scenario Outline: Starring an entry will mark it in the journal file
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl 20 july 2013 *: Best day of my life!"
|
When we run "jrnl 20 july 2013 *: Best day of my life!"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -on 2013-07-20 -starred"
|
When we run "jrnl -on 2013-07-20 -starred"
|
||||||
Then the output should contain "2013-07-20 09:00 Best day of my life!"
|
Then the output should contain "2013-07-20 09:00 Best day of my life!"
|
||||||
|
|
||||||
|
@ -30,6 +30,6 @@ Feature: Starring entries
|
||||||
Scenario: Starring an entry will mark it in an encrypted journal
|
Scenario: Starring an entry will mark it in an encrypted journal
|
||||||
Given we use the config "encrypted.yaml"
|
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"
|
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"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -on 2013-07-20 -starred" and enter "bad doggie no biscuit"
|
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!"
|
Then the output should contain "2013-07-20 09:00 Best day of my life!"
|
||||||
|
|
|
@ -46,7 +46,7 @@ Feature: Writing new entries.
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "bad doggie no biscuit" if prompted
|
And we use the password "bad doggie no biscuit" if prompted
|
||||||
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
|
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -n 1"
|
When we run "jrnl -n 1"
|
||||||
Then the output should contain "2013-07-23 09:00 A cold and stormy day."
|
Then the output should contain "2013-07-23 09:00 A cold and stormy day."
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Feature: Writing new entries.
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl this is a partial --edit"
|
When we run "jrnl this is a partial --edit"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
Then the editor should have been called
|
Then the editor should have been called
|
||||||
And the editor file content should be
|
And the editor file content should be
|
||||||
this is a partial
|
this is a partial
|
||||||
|
@ -110,7 +110,7 @@ Feature: Writing new entries.
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "bad doggie no biscuit" if prompted
|
And we use the password "bad doggie no biscuit" if prompted
|
||||||
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
|
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -n 1"
|
When we run "jrnl -n 1"
|
||||||
Then the output should not contain "Life is good"
|
Then the output should not contain "Life is good"
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ Feature: Writing new entries.
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "bad doggie no biscuit" if prompted
|
And we use the password "bad doggie no biscuit" if prompted
|
||||||
When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic."
|
When we run "jrnl 04-24-2014: Created a new website - empty.com. Hope to get a lot of traffic."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2014-04-24 09:00 Created a new website - empty.com.
|
2014-04-24 09:00 Created a new website - empty.com.
|
||||||
|
@ -142,7 +142,7 @@ Feature: Writing new entries.
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "bad doggie no biscuit" if prompted
|
And we use the password "bad doggie no biscuit" if prompted
|
||||||
When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘"
|
When we run "jrnl 23 july 2013: 🌞 sunny day. Saw an 🐘"
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -n 1"
|
When we run "jrnl -n 1"
|
||||||
Then the output should contain "🌞"
|
Then the output should contain "🌞"
|
||||||
And the output should contain "🐘"
|
And the output should contain "🐘"
|
||||||
|
@ -199,7 +199,7 @@ Feature: Writing new entries.
|
||||||
Scenario: Title with an embedded period on DayOne journal
|
Scenario: Title with an embedded period on DayOne journal
|
||||||
Given we use the config "dayone.yaml"
|
Given we use the config "dayone.yaml"
|
||||||
When we run "jrnl 04-24-2014: Ran 6.2 miles today in 1:02:03. I am feeling sore because I forgot to stretch."
|
When we run "jrnl 04-24-2014: Ran 6.2 miles today in 1:02:03. I am feeling sore because I forgot to stretch."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2014-04-24 09:00 Ran 6.2 miles today in 1:02:03.
|
2014-04-24 09:00 Ran 6.2 miles today in 1:02:03.
|
||||||
|
@ -208,7 +208,7 @@ Feature: Writing new entries.
|
||||||
Scenario: Opening an folder that's not a DayOne folder should treat as folder journal
|
Scenario: Opening an folder that's not a DayOne folder should treat as folder journal
|
||||||
Given we use the config "empty_folder.yaml"
|
Given we use the config "empty_folder.yaml"
|
||||||
When we run "jrnl 23 july 2013: Testing folder journal."
|
When we run "jrnl 23 july 2013: Testing folder journal."
|
||||||
Then we should see the message "Entry added"
|
Then the output should contain "Entry added"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
Then the output should be "2013-07-23 09:00 Testing folder journal."
|
Then the output should be "2013-07-23 09:00 Testing folder journal."
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,19 @@ import tempfile
|
||||||
|
|
||||||
from keyring import backend
|
from keyring import backend
|
||||||
from keyring import errors
|
from keyring import errors
|
||||||
from keyring import set_keyring
|
|
||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
|
from unittest.mock import patch
|
||||||
|
from .helpers import get_fixture
|
||||||
import toml
|
import toml
|
||||||
|
|
||||||
from jrnl.config import load_config
|
from jrnl.config import load_config
|
||||||
|
from jrnl.os_compat import split_args
|
||||||
|
|
||||||
|
|
||||||
# --- Keyring --- #
|
# --- Keyring --- #
|
||||||
@fixture
|
@fixture
|
||||||
def keyring():
|
def keyring():
|
||||||
set_keyring(NoKeyring())
|
return NoKeyring()
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
|
@ -75,13 +77,90 @@ class FailedKeyring(backend.KeyringBackend):
|
||||||
|
|
||||||
# ----- Misc ----- #
|
# ----- Misc ----- #
|
||||||
@fixture
|
@fixture
|
||||||
def cli_run():
|
def cli_run(
|
||||||
return {"status": 0, "stdout": None, "stderr": None}
|
mock_factories,
|
||||||
|
mock_args,
|
||||||
|
mock_is_tty,
|
||||||
|
mock_config_path,
|
||||||
|
mock_editor,
|
||||||
|
mock_user_input,
|
||||||
|
mock_overrides,
|
||||||
|
mock_password,
|
||||||
|
):
|
||||||
|
# Check if we need more mocks
|
||||||
|
mock_factories.update(mock_args)
|
||||||
|
mock_factories.update(mock_is_tty)
|
||||||
|
mock_factories.update(mock_overrides)
|
||||||
|
mock_factories.update(mock_editor)
|
||||||
|
mock_factories.update(mock_config_path)
|
||||||
|
mock_factories.update(mock_user_input)
|
||||||
|
mock_factories.update(mock_password)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": 0,
|
||||||
|
"stdout": None,
|
||||||
|
"stderr": None,
|
||||||
|
"mocks": {},
|
||||||
|
"mock_factories": mock_factories,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def mocks():
|
def mock_factories():
|
||||||
return dict()
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def mock_args(cache_dir, request):
|
||||||
|
def _mock_args():
|
||||||
|
command = get_fixture(request, "command", "")
|
||||||
|
|
||||||
|
if cache_dir["exists"]:
|
||||||
|
command = command.format(cache_dir=cache_dir["path"])
|
||||||
|
|
||||||
|
args = split_args(command)
|
||||||
|
|
||||||
|
return patch("sys.argv", ["jrnl"] + args)
|
||||||
|
|
||||||
|
return {"args": _mock_args}
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def mock_is_tty(is_tty):
|
||||||
|
return {"is_tty": lambda: patch("sys.stdin.isatty", return_value=is_tty)}
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def mock_overrides(config_in_memory):
|
||||||
|
from jrnl.override import apply_overrides
|
||||||
|
|
||||||
|
def my_overrides(*args, **kwargs):
|
||||||
|
result = apply_overrides(*args, **kwargs)
|
||||||
|
config_in_memory["overrides"] = result
|
||||||
|
return result
|
||||||
|
|
||||||
|
return {
|
||||||
|
"overrides": lambda: patch(
|
||||||
|
"jrnl.jrnl.apply_overrides", side_effect=my_overrides
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def mock_config_path(request):
|
||||||
|
config_path = get_fixture(request, "config_path")
|
||||||
|
|
||||||
|
if not config_path:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"config_path_install": lambda: patch(
|
||||||
|
"jrnl.install.get_config_path", return_value=config_path
|
||||||
|
),
|
||||||
|
"config_path_config": lambda: patch(
|
||||||
|
"jrnl.config.get_config_path", return_value=config_path
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
|
@ -94,12 +173,6 @@ def working_dir(request):
|
||||||
return os.path.join(request.config.rootpath, "tests")
|
return os.path.join(request.config.rootpath, "tests")
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def config_path(temp_dir):
|
|
||||||
os.chdir(temp_dir.name)
|
|
||||||
return temp_dir.name + "/jrnl.yaml"
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def toml_version(working_dir):
|
def toml_version(working_dir):
|
||||||
pyproject = os.path.join(working_dir, "..", "pyproject.toml")
|
pyproject = os.path.join(working_dir, "..", "pyproject.toml")
|
||||||
|
@ -108,8 +181,23 @@ def toml_version(working_dir):
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def password():
|
def mock_password(request):
|
||||||
return ""
|
def _mock_password():
|
||||||
|
password = get_fixture(request, "password")
|
||||||
|
user_input = get_fixture(request, "user_input")
|
||||||
|
|
||||||
|
if password:
|
||||||
|
password = password.splitlines()
|
||||||
|
|
||||||
|
elif user_input:
|
||||||
|
password = user_input.splitlines()
|
||||||
|
|
||||||
|
if not password:
|
||||||
|
password = Exception("Unexpected call for password")
|
||||||
|
|
||||||
|
return patch("getpass.getpass", side_effect=password)
|
||||||
|
|
||||||
|
return {"getpass": _mock_password}
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
|
@ -127,19 +215,36 @@ def str_value():
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
|
||||||
def command():
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def should_not():
|
def should_not():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def user_input():
|
def mock_user_input(request, is_tty):
|
||||||
return ""
|
def _generator(target):
|
||||||
|
def _mock_user_input():
|
||||||
|
user_input = get_fixture(request, "user_input", None)
|
||||||
|
|
||||||
|
if user_input is None:
|
||||||
|
user_input = Exception("Unexpected call for user input")
|
||||||
|
else:
|
||||||
|
user_input = user_input.splitlines() if is_tty else [user_input]
|
||||||
|
|
||||||
|
return patch(target, side_effect=user_input)
|
||||||
|
|
||||||
|
return _mock_user_input
|
||||||
|
|
||||||
|
return {
|
||||||
|
"stdin": _generator("sys.stdin.read"),
|
||||||
|
"input": _generator("builtins.input"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def is_tty(input_method):
|
||||||
|
assert input_method in ["", "enter", "pipe"]
|
||||||
|
return input_method != "pipe"
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
|
@ -187,7 +292,7 @@ def editor_state():
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def editor(editor_state):
|
def mock_editor(editor_state):
|
||||||
def _mock_editor(editor_command):
|
def _mock_editor(editor_command):
|
||||||
tmpfile = editor_command[-1]
|
tmpfile = editor_command[-1]
|
||||||
|
|
||||||
|
@ -203,4 +308,4 @@ def editor(editor_state):
|
||||||
file_content = f.read()
|
file_content = f.read()
|
||||||
editor_state["tmpfile"]["content"] = file_content
|
editor_state["tmpfile"]["content"] = file_content
|
||||||
|
|
||||||
return _mock_editor
|
return {"editor": lambda: patch("subprocess.call", side_effect=_mock_editor)}
|
||||||
|
|
|
@ -11,7 +11,6 @@ from unittest.mock import MagicMock
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
from keyring import set_keyring
|
|
||||||
from pytest_bdd import given
|
from pytest_bdd import given
|
||||||
from pytest_bdd.parsers import parse
|
from pytest_bdd.parsers import parse
|
||||||
|
|
||||||
|
@ -20,6 +19,7 @@ from jrnl.time import __get_pdt_calendar
|
||||||
|
|
||||||
from .fixtures import FailedKeyring
|
from .fixtures import FailedKeyring
|
||||||
from .fixtures import TestKeyring
|
from .fixtures import TestKeyring
|
||||||
|
from .helpers import get_fixture
|
||||||
|
|
||||||
|
|
||||||
@given(parse("we {editor_method} to the editor if opened\n{editor_input}"))
|
@given(parse("we {editor_method} to the editor if opened\n{editor_input}"))
|
||||||
|
@ -36,9 +36,8 @@ def we_enter_editor(editor_method, editor_input, editor_state):
|
||||||
editor_state["intent"] = {"method": file_method, "input": editor_input}
|
editor_state["intent"] = {"method": file_method, "input": editor_input}
|
||||||
|
|
||||||
|
|
||||||
@given(parse('now is "<date_str>"'))
|
|
||||||
@given(parse('now is "{date_str}"'))
|
@given(parse('now is "{date_str}"'))
|
||||||
def now_is_str(date_str, mocks):
|
def now_is_str(date_str, mock_factories):
|
||||||
class DatetimeMagicMock(MagicMock):
|
class DatetimeMagicMock(MagicMock):
|
||||||
# needed because jrnl does some reflection on datetime
|
# needed because jrnl does some reflection on datetime
|
||||||
def __instancecheck__(self, subclass):
|
def __instancecheck__(self, subclass):
|
||||||
|
@ -63,8 +62,8 @@ def now_is_str(date_str, mocks):
|
||||||
date_str_input, mocked_now()
|
date_str_input, mocked_now()
|
||||||
)
|
)
|
||||||
|
|
||||||
mocks["datetime"] = patch("datetime.datetime", new=datetime_mock)
|
mock_factories["datetime"] = lambda: patch("datetime.datetime", new=datetime_mock)
|
||||||
mocks["calendar_parse"] = patch(
|
mock_factories["calendar_parse"] = lambda: patch(
|
||||||
"jrnl.time.__get_pdt_calendar", return_value=calendar_mock
|
"jrnl.time.__get_pdt_calendar", return_value=calendar_mock
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -73,17 +72,22 @@ def now_is_str(date_str, mocks):
|
||||||
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
|
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
|
||||||
def we_have_type_of_keyring(keyring_type):
|
def we_have_type_of_keyring(keyring_type):
|
||||||
if keyring_type == "failed":
|
if keyring_type == "failed":
|
||||||
set_keyring(FailedKeyring())
|
return FailedKeyring()
|
||||||
else:
|
else:
|
||||||
set_keyring(TestKeyring())
|
return TestKeyring()
|
||||||
|
|
||||||
|
|
||||||
@given(parse('we use the config "{config_file}"'), target_fixture="config_path")
|
@given(parse('we use the config "{config_file}"'), target_fixture="config_path")
|
||||||
@given('we use the config "<config_file>"', target_fixture="config_path")
|
@given(parse("we use no config"), target_fixture="config_path")
|
||||||
def we_use_the_config(config_file, temp_dir, working_dir):
|
def we_use_the_config(request, temp_dir, working_dir):
|
||||||
|
config_file = get_fixture(request, "config_file")
|
||||||
|
|
||||||
# Move into temp dir as cwd
|
# Move into temp dir as cwd
|
||||||
os.chdir(temp_dir.name)
|
os.chdir(temp_dir.name)
|
||||||
|
|
||||||
|
if not config_file:
|
||||||
|
return os.path.join(temp_dir.name, "non_existing_config.yaml")
|
||||||
|
|
||||||
# Copy the config file over
|
# Copy the config file over
|
||||||
config_source = os.path.join(working_dir, "data", "configs", config_file)
|
config_source = os.path.join(working_dir, "data", "configs", config_file)
|
||||||
config_dest = os.path.join(temp_dir.name, config_file)
|
config_dest = os.path.join(temp_dir.name, config_file)
|
||||||
|
@ -106,7 +110,6 @@ def we_use_the_config(config_file, temp_dir, working_dir):
|
||||||
|
|
||||||
|
|
||||||
@given(parse('the config "{config_file}" exists'), target_fixture="config_path")
|
@given(parse('the config "{config_file}" exists'), target_fixture="config_path")
|
||||||
@given('the config "<config_file>" exists', target_fixture="config_path")
|
|
||||||
def config_exists(config_file, temp_dir, working_dir):
|
def config_exists(config_file, temp_dir, working_dir):
|
||||||
config_source = os.path.join(working_dir, "data", "configs", config_file)
|
config_source = os.path.join(working_dir, "data", "configs", config_file)
|
||||||
config_dest = os.path.join(temp_dir.name, config_file)
|
config_dest = os.path.join(temp_dir.name, config_file)
|
||||||
|
|
|
@ -49,3 +49,24 @@ def get_nested_val(dictionary, path, *default):
|
||||||
if default:
|
if default:
|
||||||
return default[0]
|
return default[0]
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# @see: https://stackoverflow.com/a/41599695/569146
|
||||||
|
def spy_wrapper(wrapped_function):
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
mock = mock.MagicMock()
|
||||||
|
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
mock(*args, **kwargs)
|
||||||
|
return wrapped_function(self, *args, **kwargs)
|
||||||
|
|
||||||
|
wrapper.mock = mock
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def get_fixture(request, name, default=None):
|
||||||
|
result = default
|
||||||
|
if name in request.node.fixturenames:
|
||||||
|
result = request.getfixturevalue(name)
|
||||||
|
return result
|
||||||
|
|
|
@ -30,38 +30,47 @@ def output_should_match(regex, cli_run):
|
||||||
assert matches, f"\nRegex didn't match:\n{regex}\n{str(out)}\n{str(matches)}"
|
assert matches, f"\nRegex didn't match:\n{regex}\n{str(out)}\n{str(matches)}"
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should contain\n{expected_output}"))
|
@then(parse("the output {should_or_should_not} contain\n{expected_output}"))
|
||||||
@then(parse('the output should contain "{expected_output}"'))
|
@then(parse('the output {should_or_should_not} contain "{expected_output}"'))
|
||||||
@then('the output should contain "<expected_output>"')
|
@then(
|
||||||
@then(parse("the {which_output_stream} output should contain\n{expected_output}"))
|
parse(
|
||||||
@then(parse('the {which_output_stream} output should contain "{expected_output}"'))
|
"the {which_output_stream} output {should_or_should_not} contain\n{expected_output}"
|
||||||
def output_should_contain(expected_output, which_output_stream, cli_run):
|
)
|
||||||
|
)
|
||||||
|
@then(
|
||||||
|
parse(
|
||||||
|
'the {which_output_stream} output {should_or_should_not} contain "{expected_output}"'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
def output_should_contain(
|
||||||
|
expected_output, which_output_stream, cli_run, should_or_should_not
|
||||||
|
):
|
||||||
|
we_should = parse_should_or_should_not(should_or_should_not)
|
||||||
|
|
||||||
assert expected_output
|
assert expected_output
|
||||||
if which_output_stream is None:
|
if which_output_stream is None:
|
||||||
assert (expected_output in cli_run["stdout"]) or (
|
assert ((expected_output in cli_run["stdout"]) == we_should) or (
|
||||||
expected_output in cli_run["stderr"]
|
(expected_output in cli_run["stderr"]) == we_should
|
||||||
)
|
)
|
||||||
|
|
||||||
elif which_output_stream == "standard":
|
elif which_output_stream == "standard":
|
||||||
assert expected_output in cli_run["stdout"]
|
assert (expected_output in cli_run["stdout"]) == we_should
|
||||||
|
|
||||||
elif which_output_stream == "error":
|
elif which_output_stream == "error":
|
||||||
assert expected_output in cli_run["stderr"]
|
assert (expected_output in cli_run["stderr"]) == we_should
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert expected_output in cli_run[which_output_stream]
|
assert (expected_output in cli_run[which_output_stream]) == we_should
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should not contain\n{expected_output}"))
|
@then(parse("the output should not contain\n{expected_output}"))
|
||||||
@then(parse('the output should not contain "{expected_output}"'))
|
@then(parse('the output should not contain "{expected_output}"'))
|
||||||
@then('the output should not contain "<expected_output>"')
|
|
||||||
def output_should_not_contain(expected_output, cli_run):
|
def output_should_not_contain(expected_output, cli_run):
|
||||||
assert expected_output not in cli_run["stdout"]
|
assert expected_output not in cli_run["stdout"]
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the output should be\n{expected_output}"))
|
@then(parse("the output should be\n{expected_output}"))
|
||||||
@then(parse('the output should be "{expected_output}"'))
|
@then(parse('the output should be "{expected_output}"'))
|
||||||
@then('the output should be "<expected_output>"')
|
|
||||||
def output_should_be(expected_output, cli_run):
|
def output_should_be(expected_output, cli_run):
|
||||||
actual = cli_run["stdout"].strip()
|
actual = cli_run["stdout"].strip()
|
||||||
expected = expected_output.strip()
|
expected = expected_output.strip()
|
||||||
|
@ -75,7 +84,6 @@ def output_should_be_empty(cli_run):
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the output should contain the date "{date}"'))
|
@then(parse('the output should contain the date "{date}"'))
|
||||||
@then('the output should contain the date "<date>"')
|
|
||||||
def output_should_contain_date(date, cli_run):
|
def output_should_contain_date(date, cli_run):
|
||||||
assert date and date in cli_run["stdout"]
|
assert date and date in cli_run["stdout"]
|
||||||
|
|
||||||
|
@ -94,12 +102,6 @@ def output_should_be_columns_wide(cli_run, width):
|
||||||
assert len(line) <= width
|
assert len(line) <= width
|
||||||
|
|
||||||
|
|
||||||
@then(parse('we should see the message "{text}"'))
|
|
||||||
def should_see_the_message(text, cli_run):
|
|
||||||
out = cli_run["stderr"]
|
|
||||||
assert text in out, [text, out]
|
|
||||||
|
|
||||||
|
|
||||||
@then(
|
@then(
|
||||||
parse(
|
parse(
|
||||||
'the config for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"'
|
'the config for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"'
|
||||||
|
@ -126,10 +128,7 @@ def config_var_on_disk(config_on_disk, journal_name, should_or_should_not, some_
|
||||||
# `expected` objects formatted in yaml only compare one level deep
|
# `expected` objects formatted in yaml only compare one level deep
|
||||||
actual_slice = {key: actual.get(key, None) for key in expected.keys()}
|
actual_slice = {key: actual.get(key, None) for key in expected.keys()}
|
||||||
|
|
||||||
if we_should:
|
assert (expected == actual_slice) == we_should
|
||||||
assert expected == actual_slice
|
|
||||||
else:
|
|
||||||
assert expected != actual_slice
|
|
||||||
|
|
||||||
|
|
||||||
@then(
|
@then(
|
||||||
|
@ -160,10 +159,7 @@ def config_var_in_memory(
|
||||||
# `expected` objects formatted in yaml only compare one level deep
|
# `expected` objects formatted in yaml only compare one level deep
|
||||||
actual_slice = {key: get_nested_val(actual, key) for key in expected.keys()}
|
actual_slice = {key: get_nested_val(actual, key) for key in expected.keys()}
|
||||||
|
|
||||||
if we_should:
|
assert (expected == actual_slice) == we_should
|
||||||
assert expected == actual_slice
|
|
||||||
else:
|
|
||||||
assert expected != actual_slice
|
|
||||||
|
|
||||||
|
|
||||||
@then("we should be prompted for a password")
|
@then("we should be prompted for a password")
|
||||||
|
@ -355,10 +351,7 @@ def count_elements(number, item, cli_run):
|
||||||
def count_editor_args(num_args, cli_run, editor_state, should_or_should_not):
|
def count_editor_args(num_args, cli_run, editor_state, should_or_should_not):
|
||||||
we_should = parse_should_or_should_not(should_or_should_not)
|
we_should = parse_should_or_should_not(should_or_should_not)
|
||||||
|
|
||||||
if we_should:
|
assert cli_run["mocks"]["editor"].called == we_should
|
||||||
assert cli_run["mocks"]["editor"].called
|
|
||||||
else:
|
|
||||||
assert not cli_run["mocks"]["editor"].called
|
|
||||||
|
|
||||||
if isinstance(num_args, int):
|
if isinstance(num_args, int):
|
||||||
assert len(editor_state["command"]) == int(num_args)
|
assert len(editor_state["command"]) == int(num_args)
|
||||||
|
@ -368,10 +361,7 @@ def count_editor_args(num_args, cli_run, editor_state, should_or_should_not):
|
||||||
def stdin_prompt_called(cli_run, should_or_should_not):
|
def stdin_prompt_called(cli_run, should_or_should_not):
|
||||||
we_should = parse_should_or_should_not(should_or_should_not)
|
we_should = parse_should_or_should_not(should_or_should_not)
|
||||||
|
|
||||||
if we_should:
|
assert cli_run["mocks"]["stdin"].called == we_should
|
||||||
assert cli_run["mocks"]["stdin"].called
|
|
||||||
else:
|
|
||||||
assert not cli_run["mocks"]["stdin"].called
|
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the editor filename should end with "{suffix}"'))
|
@then(parse('the editor filename should end with "{suffix}"'))
|
||||||
|
|
|
@ -3,14 +3,12 @@
|
||||||
|
|
||||||
from contextlib import ExitStack
|
from contextlib import ExitStack
|
||||||
import os
|
import os
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from pytest_bdd import parsers
|
|
||||||
from pytest_bdd import when
|
from pytest_bdd import when
|
||||||
from pytest_bdd.parsers import parse
|
from pytest_bdd.parsers import parse
|
||||||
|
from pytest_bdd.parsers import re
|
||||||
|
|
||||||
from jrnl.cli import cli
|
from jrnl.cli import cli
|
||||||
from jrnl.os_compat import split_args
|
|
||||||
|
|
||||||
|
|
||||||
@when(parse('we change directory to "{directory_name}"'))
|
@when(parse('we change directory to "{directory_name}"'))
|
||||||
|
@ -21,103 +19,38 @@ def when_we_change_directory(directory_name):
|
||||||
os.chdir(directory_name)
|
os.chdir(directory_name)
|
||||||
|
|
||||||
|
|
||||||
|
# These variables are used in the `@when(re(...))` section below
|
||||||
|
command = '(?P<command>[^"]+)'
|
||||||
|
input_method = "(?P<input_method>enter|pipe)"
|
||||||
|
user_input = '(?P<user_input>[^"]+)'
|
||||||
|
|
||||||
|
|
||||||
@when(parse('we run "jrnl {command}" and {input_method}\n{user_input}'))
|
@when(parse('we run "jrnl {command}" and {input_method}\n{user_input}'))
|
||||||
@when(
|
@when(re(f'we run "jrnl {command}" and {input_method} "{user_input}"'))
|
||||||
parsers.re(
|
@when(re(f'we run "jrnl" and {input_method} "{user_input}"'))
|
||||||
'we run "jrnl (?P<command>[^"]+)" and (?P<input_method>enter|pipe) "(?P<user_input>[^"]+)"'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@when(parse('we run "jrnl" and {input_method} "{user_input}"'))
|
|
||||||
@when(parse('we run "jrnl {command}"'))
|
@when(parse('we run "jrnl {command}"'))
|
||||||
@when('we run "jrnl <command>"')
|
|
||||||
@when('we run "jrnl"')
|
@when('we run "jrnl"')
|
||||||
def we_run(
|
def we_run_jrnl(cli_run, capsys, keyring):
|
||||||
command,
|
from keyring import set_keyring
|
||||||
config_path,
|
|
||||||
config_in_memory,
|
|
||||||
user_input,
|
|
||||||
cli_run,
|
|
||||||
capsys,
|
|
||||||
password,
|
|
||||||
cache_dir,
|
|
||||||
editor,
|
|
||||||
keyring,
|
|
||||||
input_method,
|
|
||||||
mocks,
|
|
||||||
):
|
|
||||||
assert input_method in ["", "enter", "pipe"]
|
|
||||||
is_tty = input_method != "pipe"
|
|
||||||
|
|
||||||
if cache_dir["exists"]:
|
set_keyring(keyring)
|
||||||
command = command.format(cache_dir=cache_dir["path"])
|
|
||||||
|
|
||||||
args = split_args(command)
|
|
||||||
status = 0
|
|
||||||
|
|
||||||
if user_input:
|
|
||||||
user_input = user_input.splitlines() if is_tty else [user_input]
|
|
||||||
|
|
||||||
if password:
|
|
||||||
password = password.splitlines()
|
|
||||||
|
|
||||||
if not password and user_input:
|
|
||||||
password = user_input
|
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
# Always mock
|
mocks = cli_run["mocks"]
|
||||||
from jrnl.override import apply_overrides
|
factories = cli_run["mock_factories"]
|
||||||
|
|
||||||
def my_overrides(*args, **kwargs):
|
for id in factories:
|
||||||
result = apply_overrides(*args, **kwargs)
|
mocks[id] = stack.enter_context(factories[id]())
|
||||||
config_in_memory["overrides"] = result
|
|
||||||
return result
|
|
||||||
|
|
||||||
stack.enter_context(
|
|
||||||
patch("jrnl.jrnl.apply_overrides", side_effect=my_overrides)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Conditionally mock
|
|
||||||
stack.enter_context(patch("sys.argv", ["jrnl"] + args))
|
|
||||||
|
|
||||||
mock_stdin = stack.enter_context(
|
|
||||||
patch("sys.stdin.read", side_effect=user_input)
|
|
||||||
)
|
|
||||||
stack.enter_context(patch("sys.stdin.isatty", return_value=is_tty))
|
|
||||||
mock_input = stack.enter_context(
|
|
||||||
patch("builtins.input", side_effect=user_input)
|
|
||||||
)
|
|
||||||
mock_getpass = stack.enter_context(
|
|
||||||
patch("getpass.getpass", side_effect=password)
|
|
||||||
)
|
|
||||||
|
|
||||||
if "datetime" in mocks:
|
|
||||||
stack.enter_context(mocks["datetime"])
|
|
||||||
stack.enter_context(mocks["calendar_parse"])
|
|
||||||
|
|
||||||
stack.enter_context(
|
|
||||||
patch("jrnl.install.get_config_path", return_value=config_path)
|
|
||||||
)
|
|
||||||
stack.enter_context(
|
|
||||||
patch("jrnl.config.get_config_path", return_value=config_path)
|
|
||||||
)
|
|
||||||
mock_editor = stack.enter_context(patch("subprocess.call", side_effect=editor))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cli(args)
|
cli()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
# This happens when input is expected, but don't have any input left
|
# This happens when input is expected, but don't have any input left
|
||||||
pass
|
pass
|
||||||
except SystemExit as e:
|
except SystemExit as e:
|
||||||
status = e.code
|
cli_run["status"] = e.code
|
||||||
|
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
cli_run["status"] = status
|
|
||||||
cli_run["stdout"] = captured.out
|
cli_run["stdout"] = captured.out
|
||||||
cli_run["stderr"] = captured.err
|
cli_run["stderr"] = captured.err
|
||||||
cli_run["mocks"] = {
|
|
||||||
"stdin": mock_stdin,
|
|
||||||
"input": mock_input,
|
|
||||||
"getpass": mock_getpass,
|
|
||||||
"editor": mock_editor,
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue