mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-07-07 00:36:13 +02:00
Merge branch 'develop' of https://github.com/jrnl-org/jrnl into dayone2
This commit is contained in:
commit
d86bbaf861
26 changed files with 439 additions and 200 deletions
|
@ -41,6 +41,14 @@ Feature: Basic reading and writing to a journal
|
|||
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."
|
||||
|
|
12
features/data/configs/bug780.yaml
Normal file
12
features/data/configs/bug780.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
default_hour: 9
|
||||
default_minute: 0
|
||||
editor: ''
|
||||
encrypt: false
|
||||
highlight: true
|
||||
journals:
|
||||
default: features/journals/bug780.dayone
|
||||
linewrap: 80
|
||||
tagsymbols: '@'
|
||||
template: false
|
||||
timeformat: '%Y-%m-%d %H:%M'
|
||||
indent_character: "|"
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Activity</key>
|
||||
<string>Stationary</string>
|
||||
<key>Creation Date</key>
|
||||
<date>2019-12-30T21:28:54Z</date>
|
||||
<key>Entry Text</key>
|
||||
<string></string>
|
||||
<key>Starred</key>
|
||||
<false />
|
||||
<key>UUID</key>
|
||||
<string>48A25033B34047C591160A4480197D8B</string>
|
||||
<key>Creator</key>
|
||||
<dict>
|
||||
<key>Device Agent</key>
|
||||
<string>PC</string>
|
||||
<key>Generation Date</key>
|
||||
<date>2019-12-30T21:28:54Z</date>
|
||||
<key>Host Name</key>
|
||||
<string>LE-TREPORT</string>
|
||||
<key>OS Agent</key>
|
||||
<string>Microsoft Windows/10 Home</string>
|
||||
<key>Software Agent</key>
|
||||
<string>Journaley/2.1</string>
|
||||
</dict>
|
||||
<key>Tags</key>
|
||||
<array>
|
||||
<string>i_have_no_body</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,7 +1,5 @@
|
|||
Feature: Dayone specific implementation details.
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
@skip
|
||||
Scenario: Loading a DayOne Journal
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl -from 'feb 2013'"
|
||||
|
@ -15,7 +13,7 @@ Feature: Dayone specific implementation details.
|
|||
2013-07-17 11:38 This entry is starred!
|
||||
"""
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
# broken still
|
||||
@skip
|
||||
Scenario: Entries without timezone information will be interpreted as in the current timezone
|
||||
Given we use the config "dayone.yaml"
|
||||
|
@ -23,7 +21,6 @@ Feature: Dayone specific implementation details.
|
|||
Then we should get no error
|
||||
and the output should contain "2013-01-17T18:37Z" in the local time
|
||||
|
||||
@skip
|
||||
Scenario: Writing into Dayone
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl 01 may 1979: Being born hurts."
|
||||
|
@ -33,8 +30,6 @@ Feature: Dayone specific implementation details.
|
|||
1979-05-01 09:00 Being born hurts.
|
||||
"""
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
@skip
|
||||
Scenario: Loading tags from a DayOne Journal
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl --tags"
|
||||
|
@ -44,8 +39,6 @@ Feature: Dayone specific implementation details.
|
|||
@play : 1
|
||||
"""
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
@skip
|
||||
Scenario: Saving tags from a DayOne Journal
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl A hard day at @work"
|
||||
|
@ -56,8 +49,6 @@ Feature: Dayone specific implementation details.
|
|||
@play : 1
|
||||
"""
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
@skip
|
||||
Scenario: Filtering by tags from a DayOne Journal
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl @work"
|
||||
|
@ -66,8 +57,6 @@ Feature: Dayone specific implementation details.
|
|||
2013-05-17 11:39 This entry has tags!
|
||||
"""
|
||||
|
||||
# fails when system time is UTC (as on Travis-CI)
|
||||
@skip
|
||||
Scenario: Exporting dayone to json
|
||||
Given we use the config "dayone.yaml"
|
||||
When we run "jrnl --export json"
|
||||
|
|
|
@ -24,7 +24,6 @@ Feature: Zapped Dayone bugs stay dead!
|
|||
| I'm feeling sore because I forgot to stretch.
|
||||
"""
|
||||
|
||||
@skip_win
|
||||
Scenario: Opening an folder that's not a DayOne folder gives a nice error message
|
||||
Given we use the config "empty_folder.yaml"
|
||||
When we run "jrnl Herro"
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
Then we should see the message "Journal decrypted"
|
||||
And the journal should have 2 entries
|
||||
|
||||
@skip_win
|
||||
Scenario: Encrypting a journal
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl --encrypt" and enter
|
||||
|
@ -27,7 +26,6 @@
|
|||
Then the output should contain "Password"
|
||||
And the output should contain "2013-06-10 15:40 Life is good"
|
||||
|
||||
@skip_win
|
||||
Scenario: Mistyping your password
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl --encrypt" and enter
|
||||
|
@ -45,7 +43,6 @@
|
|||
Then the output should contain "Password"
|
||||
And the output should contain "2013-06-10 15:40 Life is good"
|
||||
|
||||
@skip_win
|
||||
Scenario: Storing a password in Keychain
|
||||
Given we use the config "multiple.yaml"
|
||||
When we run "jrnl simple --encrypt" and enter
|
||||
|
|
|
@ -4,21 +4,20 @@ Feature: Exporting a Journal
|
|||
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 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"
|
||||
|
||||
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 we should get no error
|
||||
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"
|
||||
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"
|
||||
|
@ -83,3 +82,57 @@ Feature: Exporting a Journal
|
|||
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"]
|
||||
|
||||
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 created a directory named "exported_journal"
|
||||
When we run "jrnl --export yaml -o exported_journal"
|
||||
Then "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 exported yaml "exported_journal/2013-04-09_i-have-an-idea.md" should be
|
||||
"""
|
||||
title: I have an @idea:
|
||||
date: 2013-04-09 15:39
|
||||
stared: False
|
||||
tags: idea, journal
|
||||
|
||||
(1) write a command line @journal software
|
||||
(2) ???
|
||||
(3) PROFIT!
|
||||
"""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Feature: Zapped bugs should stay dead.
|
||||
|
||||
Scenario: Writing an entry does not print the entire journal
|
||||
# https://github.com/maebert/jrnl/issues/87
|
||||
# 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"
|
||||
|
@ -9,21 +9,14 @@ Feature: Zapped bugs should stay dead.
|
|||
Then the output should not contain "Life is good"
|
||||
|
||||
Scenario: Date with time should be parsed correctly
|
||||
# https://github.com/maebert/jrnl/issues/117
|
||||
# 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: Date in the future should be parsed correctly
|
||||
# https://github.com/maebert/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: Loading entry with ambiguous time stamp
|
||||
#https://github.com/maebert/jrnl/issues/153
|
||||
#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
|
||||
|
@ -32,6 +25,19 @@ Feature: Zapped bugs should stay dead.
|
|||
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."
|
||||
|
|
|
@ -3,7 +3,6 @@ from unittest.mock import patch
|
|||
from behave import given, when, then
|
||||
from jrnl import cli, install, Journal, util, plugins
|
||||
from jrnl import __version__
|
||||
from dateutil import parser as date_parser
|
||||
from collections import defaultdict
|
||||
|
||||
try:
|
||||
|
@ -185,53 +184,6 @@ def no_error(context):
|
|||
assert context.exit_status == 0, context.exit_status
|
||||
|
||||
|
||||
@then("the output should be parsable as json")
|
||||
def check_output_json(context):
|
||||
out = context.stdout_capture.getvalue()
|
||||
assert json.loads(out), out
|
||||
|
||||
|
||||
@then('"{field}" in the json output should have {number:d} elements')
|
||||
@then('"{field}" in the json output should have 1 element')
|
||||
def check_output_field(context, field, number=1):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json, [field, out_json]
|
||||
assert len(out_json[field]) == number, len(out_json[field])
|
||||
|
||||
|
||||
@then('"{field}" in the json output should not contain "{key}"')
|
||||
def check_output_field_not_key(context, field, key):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json
|
||||
assert key not in out_json[field]
|
||||
|
||||
|
||||
@then('"{field}" in the json output should contain "{key}"')
|
||||
def check_output_field_key(context, field, key):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json
|
||||
assert key in out_json[field]
|
||||
|
||||
|
||||
@then('the json output should contain {path} = "{value}"')
|
||||
def check_json_output_path(context, path, value):
|
||||
""" E.g.
|
||||
the json output should contain entries.0.title = "hello"
|
||||
"""
|
||||
out = context.stdout_capture.getvalue()
|
||||
struct = json.loads(out)
|
||||
|
||||
for node in path.split("."):
|
||||
try:
|
||||
struct = struct[int(node)]
|
||||
except ValueError:
|
||||
struct = struct[node]
|
||||
assert struct == value, struct
|
||||
|
||||
|
||||
@then("the output should be")
|
||||
@then('the output should be "{text}"')
|
||||
def check_output(context, text=None):
|
||||
|
|
124
features/steps/export_steps.py
Normal file
124
features/steps/export_steps.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
import json
|
||||
import os
|
||||
import shutil
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from behave import then, given
|
||||
|
||||
|
||||
@then("the output should be parsable as json")
|
||||
def check_output_json(context):
|
||||
out = context.stdout_capture.getvalue()
|
||||
assert json.loads(out), out
|
||||
|
||||
|
||||
@then('"{field}" in the json output should have {number:d} elements')
|
||||
@then('"{field}" in the json output should have 1 element')
|
||||
def check_output_field(context, field, number=1):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json, [field, out_json]
|
||||
assert len(out_json[field]) == number, len(out_json[field])
|
||||
|
||||
|
||||
@then('"{field}" in the json output should not contain "{key}"')
|
||||
def check_output_field_not_key(context, field, key):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json
|
||||
assert key not in out_json[field]
|
||||
|
||||
|
||||
@then('"{field}" in the json output should contain "{key}"')
|
||||
def check_output_field_key(context, field, key):
|
||||
out = context.stdout_capture.getvalue()
|
||||
out_json = json.loads(out)
|
||||
assert field in out_json
|
||||
assert key in out_json[field]
|
||||
|
||||
|
||||
@then('the json output should contain {path} = "{value}"')
|
||||
def check_json_output_path(context, path, value):
|
||||
""" E.g.
|
||||
the json output should contain entries.0.title = "hello"
|
||||
"""
|
||||
out = context.stdout_capture.getvalue()
|
||||
struct = json.loads(out)
|
||||
|
||||
for node in path.split("."):
|
||||
try:
|
||||
struct = struct[int(node)]
|
||||
except ValueError:
|
||||
struct = struct[node]
|
||||
assert struct == value, struct
|
||||
|
||||
|
||||
@then("the output should be a valid XML string")
|
||||
def assert_valid_xml_string(context):
|
||||
output = context.stdout_capture.getvalue()
|
||||
xml_tree = ElementTree.fromstring(output)
|
||||
assert xml_tree, output
|
||||
|
||||
|
||||
@then('"entries" node in the xml output should have {number:d} elements')
|
||||
def assert_xml_output_entries_count(context, number):
|
||||
output = context.stdout_capture.getvalue()
|
||||
xml_tree = ElementTree.fromstring(output)
|
||||
|
||||
xml_tags = (node.tag for node in xml_tree)
|
||||
assert "entries" in xml_tags, str(list(xml_tags))
|
||||
|
||||
actual_entry_count = len(xml_tree.find("entries"))
|
||||
assert actual_entry_count == number, actual_entry_count
|
||||
|
||||
|
||||
@then('"tags" in the xml output should contain {expected_tags_json_list}')
|
||||
def assert_xml_output_tags(context, expected_tags_json_list):
|
||||
output = context.stdout_capture.getvalue()
|
||||
xml_tree = ElementTree.fromstring(output)
|
||||
|
||||
xml_tags = (node.tag for node in xml_tree)
|
||||
assert "tags" in xml_tags, str(list(xml_tags))
|
||||
|
||||
expected_tags = json.loads(expected_tags_json_list)
|
||||
actual_tags = set(t.attrib["name"] for t in xml_tree.find("tags"))
|
||||
assert actual_tags == set(expected_tags), [actual_tags, set(expected_tags)]
|
||||
|
||||
|
||||
@given('we created a directory named "{dir_name}"')
|
||||
def create_directory(context, dir_name):
|
||||
if os.path.exists(dir_name):
|
||||
shutil.rmtree(dir_name)
|
||||
os.mkdir(dir_name)
|
||||
|
||||
|
||||
@then('"{dir_name}" should contain the files {expected_files_json_list}')
|
||||
def assert_dir_contains_files(context, dir_name, expected_files_json_list):
|
||||
actual_files = os.listdir(dir_name)
|
||||
expected_files = json.loads(expected_files_json_list)
|
||||
assert actual_files == expected_files, [actual_files, expected_files]
|
||||
|
||||
|
||||
@then('the content of exported yaml "{file_path}" should be')
|
||||
def assert_exported_yaml_file_content(context, file_path):
|
||||
expected_content = context.text.strip().splitlines()
|
||||
|
||||
with open(file_path, "r") as f:
|
||||
actual_content = f.read().strip().splitlines()
|
||||
|
||||
for actual_line, expected_line in zip(actual_content, expected_content):
|
||||
if actual_line.startswith("tags: ") and expected_line.startswith("tags: "):
|
||||
assert_equal_tags_ignoring_order(actual_line, expected_line)
|
||||
else:
|
||||
assert actual_line.strip() == expected_line.strip(), [
|
||||
actual_line.strip(),
|
||||
expected_line.strip(),
|
||||
]
|
||||
|
||||
|
||||
def assert_equal_tags_ignoring_order(actual_line, expected_line):
|
||||
actual_tags = set(tag.strip() for tag in actual_line[len("tags: ") :].split(","))
|
||||
expected_tags = set(
|
||||
tag.strip() for tag in expected_line[len("tags: ") :].split(",")
|
||||
)
|
||||
assert actual_tags == expected_tags, [actual_tags, expected_tags]
|
|
@ -1,6 +1,5 @@
|
|||
Feature: Upgrading Journals from 1.x.x to 2.x.x
|
||||
|
||||
@skip_win
|
||||
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"
|
||||
|
@ -12,7 +11,6 @@ Feature: Upgrading Journals from 1.x.x to 2.x.x
|
|||
"""
|
||||
Then the journal should have 2 entries
|
||||
|
||||
@skip_win
|
||||
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
|
||||
|
@ -24,7 +22,6 @@ Feature: Upgrading Journals from 1.x.x to 2.x.x
|
|||
Then the output should contain "Password"
|
||||
and the output should contain "2013-06-10 15:40 Life is good"
|
||||
|
||||
@skip_win
|
||||
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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue