Address code review

make the test perform actual qualification

make format

update other test as well

remove unnecessary mock

reset .gitignore to e6c0a16342

delete pretty.yaml

remove launch.json

reorder mocks

convert scenario to scenario outline for behavioral coverage

fix scenario syntax

comment out problematic step; add password handling

reorder import

meld conditional code

rework melded export logic

update code to be exercised in test
This commit is contained in:
Suhas 2021-02-27 17:52:24 -05:00
parent edc8cd93e3
commit 0a6e5f94c0
8 changed files with 44 additions and 127 deletions

5
.gitignore vendored
View file

@ -54,8 +54,3 @@ exp/
_extras/ _extras/
*.sublime-* *.sublime-*
site/ site/
.coverage
.vscode/settings.json
coverage.xml
.vscode/launch.json

31
.vscode/launch.json vendored
View file

@ -1,31 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "behave",
"type": "python",
"request": "launch",
"program": "behave", // adjust as needed for virtualenv
"args": [
"features/upgrade.feature",
"--stop",
"-n",
"without colors to colors"
],
"justMyCode": true,
"console": "integratedTerminal"
},
{
"name": "Jrnl",
"type": "python",
"request": "launch",
"program": "jrnl", //adjust as needed for virtualenv
"args": [],
"justMyCode": false,
"console": "integratedTerminal"
}
],
}

View file

@ -1,19 +0,0 @@
default_hour: 9
default_minute: 0
editor: "vim"
encrypt: false
highlight: true
journals:
default: features/journals/simple.journal
linewrap: 80
tagsymbols: "@"
template: false
timeformat: "%Y-%m-%d %H:%M"
indent_character: "|"
colors:
body: green
title: blue
date: red
tags: magenta

View file

@ -1,16 +1,30 @@
Feature: Custom formats Feature: Custom formats
Scenario: Short printing via --format flag Scenario Outline: Short printing via --format flag
Given We use the config "pretty.yaml" Given We use the config "<config>.yaml"
And we use the password "test" if prompted
When we run "jrnl --format short -3" When we run "jrnl --format short -3"
Then we should get no error Then we should get no error
And the output should be pretty printed
Scenario: Pretty Printing aka the Default Examples: configs
Given We use the config "pretty.yaml" | config |
| basic_onefile |
| basic_encrypted |
| basic_folder |
| basic_dayone |
Scenario Outline: Pretty Printing aka the Default
Given We use the config "<config>.yaml"
And we use the password "test" if prompted
When we run "jrnl --format pretty -3" When we run "jrnl --format pretty -3"
Then we should get no error Then we should get no error
And the output should be pretty printed
Examples: configs
| config |
| basic_onefile |
| basic_encrypted |
| basic_folder |
| basic_dayone |
Scenario Outline: JSON format Scenario Outline: JSON format
Given we use the config "<config>.yaml" Given we use the config "<config>.yaml"

View file

@ -430,7 +430,6 @@ def run(context, command, text=""):
patch("sys.stdin.read", side_effect=lambda: text), \ patch("sys.stdin.read", side_effect=lambda: text), \
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \ patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \ patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
patch("jrnl.install.load_or_install_jrnl",wraps=jrnl.install.load_or_install_jrnl), \
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \ patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
: :
context.editor = mock_editor context.editor = mock_editor

View file

@ -8,48 +8,8 @@ import shutil
import random import random
import string import string
from xml.etree import ElementTree from xml.etree import ElementTree
from colorama import Fore, Style
from behave import given from behave import given
from behave import then from behave import then
import colorama
def style_text(to_bold: bool, text_color: Fore, text_to_print: str):
"""Generate colorized and styled text for expected output. Its purpose is the same as Entry.colorize
:param to_bold: Flag whether the text should be bolded
:type to_bold: bool
:param text_color: Valid colorama.Fore color for the text
:type text_color: colorama.Fore
:param text_to_print: Message contents
:type text_to_print: str
:return: Styled and colored output
:rtype: str
"""
if to_bold:
text_style = Style.BRIGHT
else:
text_style = Style.NORMAL
text_color = getattr(colorama.Fore, text_color.upper(), None)
return text_style + text_color + text_to_print + Style.RESET_ALL
@then("the output should be pretty printed")
def check_export_pretty(context):
out = context.stdout_capture.getvalue()
lines = out.splitlines()
# As per the configuration,
expected_colorized_title = (
style_text(
True, context.jrnl_config["colors"]["date"].upper(), "2013-06-09 15:39"
)
+ " "
+ style_text(
True, context.jrnl_config["colors"]["title"].upper(), "My first entry."
)
)
assert lines[0] == expected_colorized_title
@then("the output should be parsable as json") @then("the output should be parsable as json")

View file

@ -1,6 +1,7 @@
# Copyright (C) 2012-2021 jrnl contributors # Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html # License: https://www.gnu.org/licenses/gpl-3.0.html
from argparse import Namespace
import logging import logging
import sys import sys
@ -316,14 +317,18 @@ def _delete_search_results(journal, old_entries, **kwargs):
def _display_search_results(args, journal, **kwargs): def _display_search_results(args, journal, **kwargs):
if args.short: if args.short or args.export == "short":
print(journal.pprint(short=True)) print(journal.pprint(short=True))
elif args.export == "pretty":
print(journal.pprint())
elif args.tags: elif args.tags:
print(plugins.get_exporter("tags").export(journal)) print(plugins.get_exporter("tags").export(journal))
elif args.export: elif args.export:
_export_journal(args, journal) _export_journal(args, journal)
elif kwargs["config"].get("display_format"): elif kwargs["config"].get("display_format"):
exporter = plugins.get_exporter(kwargs["config"]["display_format"]) exporter = plugins.get_exporter(kwargs["config"]["display_format"])
print(exporter.export(journal, args.filename)) print(exporter.export(journal, args.filename))
@ -331,9 +336,6 @@ def _display_search_results(args, journal, **kwargs):
print(journal.pprint()) print(journal.pprint())
from argparse import Namespace
def _export_journal(args: Namespace, journal: Journal): def _export_journal(args: Namespace, journal: Journal):
"""Export journal using supplied export format """Export journal using supplied export format
Export formats "short" and "pretty" are shorthands for pre-configured Export formats "short" and "pretty" are shorthands for pre-configured
@ -344,10 +346,7 @@ def _export_journal(args: Namespace, journal: Journal):
:param journal: journal under use :param journal: journal under use
:type journal: Journal :type journal: Journal
""" """
if args.export == "pretty": # There are no exporter 'plugins' for pretty and short. We shouldn't expect this to be called for those two export formats.
print(journal.pprint(short=False)) assert args.export and args.export not in ("pretty", "short")
elif args.export == "short":
print(journal.pprint(short=True))
else:
exporter = plugins.get_exporter(args.export) exporter = plugins.get_exporter(args.export)
print(exporter.export(journal, args.filename)) print(exporter.export(journal, args.filename))

View file

@ -2,41 +2,41 @@ import argparse
import jrnl import jrnl
import pytest import pytest
from unittest import mock from unittest import mock
from jrnl.jrnl import _export_journal from jrnl.jrnl import _display_search_results, _export_journal
# fmt: off # fmt: off
# see: https://github.com/psf/black/issues/664 # see: https://github.com/psf/black/issues/664
@pytest.mark.parametrize("export_format", [ "pretty", "short",]) @pytest.mark.parametrize("export_format", [ "pretty", "short",])
#fmt: on #fmt: on
@mock.patch.object(argparse, "Namespace", return_value={"export": None, "filename": None}) @mock.patch.object(argparse, "Namespace", return_value={"export": "markdown", "filename": "irrele.vant"})
def test_export_format(mock_args, export_format): def test_export_format(mock_args, export_format):
test_journal = jrnl.Journal.Journal test_journal = jrnl.Journal.Journal
mock_args.export = export_format mock_args.export = export_format
# fmt: off #fmt: off
# see: https://github.com/psf/black/issues/664 # see: https://github.com/psf/black/issues/664
with mock.patch("builtins.print") as print_spy, mock.patch("jrnl.Journal.Journal.pprint") as mock_pprint: with mock.patch("builtins.print") as mock_spy_print, \
_export_journal(mock_args, test_journal) mock.patch('jrnl.Journal.Journal.pprint') as mock_pprint:
print_spy.call_args_list = mock_pprint _display_search_results(mock_args, test_journal)
# fmt: on mock_spy_print.assert_called_once_with(mock_pprint())
#fmt: on
@mock.patch.object(argparse, "Namespace", return_value={"export": None, "filename": None}) @mock.patch.object(argparse, "Namespace", return_value={"export": "markdown", "filename": "foo.jrnl"})
def test_export_plugin(mock_args): def test_export_plugin(mock_args):
export_format = "markdown" export_format = mock_args.return_value["export"]
test_journal = jrnl.Journal.Journal test_journal = jrnl.Journal.Journal
mock_args.export = export_format mock_args.export = export_format
mock_args.filename = "foo.jrnl" mock_args.filename = mock_args.return_value['filename']
# fmt: off # fmt: off
# see: https://github.com/psf/black/issues/664 # see: https://github.com/psf/black/issues/664
with mock.patch("builtins.print") as print_spy, \ with mock.patch("builtins.print") as print_spy, \
mock.patch("jrnl.plugins.get_exporter") as mock_get_exporter, \ mock.patch("jrnl.plugins.get_exporter") as mock_get_exporter, \
mock.patch("jrnl.Journal.Journal.pprint") as mock_pprint: mock.patch("jrnl.Journal.Journal.pprint") :
_export_journal(mock_args, test_journal) _export_journal(mock_args, test_journal)
# fmt: on # fmt: on
print_spy.call_args_list = mock_pprint
mock_get_exporter.assert_called_once_with(export_format) mock_get_exporter.assert_called_once_with(export_format)
print_spy.assert_called_once_with(mock_get_exporter().export(test_journal,mock_args.filename))