From 5600c01e964e8cac3930441f1653663fa529b70d Mon Sep 17 00:00:00 2001 From: ece-mohammad Date: Sat, 9 Dec 2023 04:08:37 +0200 Subject: [PATCH] Changes: Added basic tests for jinja2cli using `tox`, for python versions 2.7, 3.5+ - Added test cases for supported data formnts: env, ini, querystring, json, hjson, json5, xml, yaml, toml - Added test cases for jinja2 options: format, strict, section, extension, outfile TODO: - test combination of options --- .gitignore | 7 ++ Makefile | 3 +- requirements.txt | 1 + requirements_dev.txt | 9 +++ tests/common.py | 111 +++++++++++++++++++++++++++++++ tests/test_data_input_stdin.py | 26 ++++++++ tests/test_format_env.py | 26 ++++++++ tests/test_format_hjson.py | 67 +++++++++++++++++++ tests/test_format_ini.py | 57 ++++++++++++++++ tests/test_format_json.py | 35 ++++++++++ tests/test_format_json5.py | 61 +++++++++++++++++ tests/test_format_querystring.py | 35 ++++++++++ tests/test_format_toml.py | 35 ++++++++++ tests/test_format_xml.py | 39 +++++++++++ tests/test_format_yaml.py | 38 +++++++++++ tests/test_opt_d_variables.py | 28 ++++++++ tests/test_opt_extensions.py | 49 ++++++++++++++ tests/test_opt_format.py | 28 ++++++++ tests/test_opt_format_auto.py | 28 ++++++++ tests/test_opt_outfile.py | 36 ++++++++++ tests/test_opt_section.py | 34 ++++++++++ tests/test_opt_strict.py | 28 ++++++++ tests/test_parse_qs.py | 21 ------ tox.ini | 45 +++++++++++++ 24 files changed, 825 insertions(+), 22 deletions(-) create mode 100644 requirements.txt create mode 100644 requirements_dev.txt create mode 100644 tests/common.py create mode 100644 tests/test_data_input_stdin.py create mode 100644 tests/test_format_env.py create mode 100644 tests/test_format_hjson.py create mode 100644 tests/test_format_ini.py create mode 100644 tests/test_format_json.py create mode 100644 tests/test_format_json5.py create mode 100644 tests/test_format_querystring.py create mode 100644 tests/test_format_toml.py create mode 100644 tests/test_format_xml.py create mode 100644 tests/test_format_yaml.py create mode 100644 tests/test_opt_d_variables.py create mode 100644 tests/test_opt_extensions.py create mode 100644 tests/test_opt_format.py create mode 100644 tests/test_opt_format_auto.py create mode 100644 tests/test_opt_outfile.py create mode 100644 tests/test_opt_section.py create mode 100644 tests/test_opt_strict.py delete mode 100644 tests/test_parse_qs.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 9f431dd..0c9d7be 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,10 @@ nosetests.xml .pytest_cache dist/ + +.python-version +*.txt +.venv +.vscode +*.code-workspace +.idea diff --git a/Makefile b/Makefile index 08ebf93..5d63e97 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ test: - pytest -v + tox publish: clean python setup.py sdist bdist_wheel @@ -7,5 +7,6 @@ publish: clean clean: rm -rf *.egg-info *.egg dist build .pytest_cache + rm -rf .tox/py* .tox/dist/* .PHONY: test publish clean diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ce973e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Jinja2 diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..27229da --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,9 @@ +-e git+https://github.com/mattrobenolt/jinja2-cli.git#egg=jinja2_cli +pytest +pytest-xdist +schema +toml +pyyaml +xmltodict +json5 +hjson; python_version > '2.7' diff --git a/tests/common.py b/tests/common.py new file mode 100644 index 0000000..22bdddb --- /dev/null +++ b/tests/common.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Common helper classes and functions used by test cases +""" + +import subprocess +import sys + +from jinja2 import nodes +from jinja2.ext import Extension + +from jinja2cli import cli + + +class UpperCaseExtension(Extension): + """A custom jinja2 extension that adds a new tag `upperrcase`, + an upper case block capitalizes all text an variables within + the block. + + example: + ```template.j2 + .. + {% uppercase %}{{foo}}{% enduppercase %} + .. + ``` + + ``` + >>> import jinja2 + >>> from common import UpperCaseExtension + + >>> env = jinja2.Environment(extensions=[UpperCaseExtension]) + >>> loader = jinja2.FileSystemLoader("path/to/templates/dir") + >>> template = loader.load(env, "template.j2") + >>> render = template.render(foo="bar") + >>> print(render) + BAR + ``` + """ + + tags = {"uppercase"} + + def parse(self, parser): + lineno = next(parser.stream).lineno + args = [] # the uppercase tag doesn't require any arguments + body = parser.parse_statements(["name:enduppercase"], drop_needle=True) + ret = nodes.CallBlock( + self.call_method("_uppercase", args), [], [], body + ).set_lineno(lineno) + return ret + + def _uppercase(self, caller=None): + if caller is not None: + return caller().upper() + return "" + + +class CliOpts(object): + """A helper class to mimic jinja2cli.cli options (passed from optparse)""" + + def __init__(self, **opts): + self.format = opts.get("format", None) + self.D = opts.get("D", None) + self.extensions = opts.get("extensions", []) + self.section = opts.get("section", None) + self.outfile = opts.get("outfile", None) + self.strict = opts.get("strict", False) + + +def is_python_version(major, minor=None): + if minor is None: + return sys.version_info.major == major + return sys.version_info[:2] == (major, minor) + + +def to_unicode(string): + if is_python_version(3): + return bytes(string, "utf-8") + else: + return unicode(string) + + +def run_jinja2(template, datafile="", args=None, input_data=""): + """Run jinja2 with the given template, path to data file, input_data and other options, capture the error and output streams and return them""" + + cmd_args = [template] + + if datafile: + cmd_args.append(datafile) + + if args: + cmd_args.extend(list(args)) + + proc = subprocess.Popen( + ["jinja2"] + cmd_args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + if input_data: + out, err = proc.communicate(input=to_unicode(input_data)) + else: + out, err = proc.communicate() + + try: + proc.terminate() + except OSError: + pass + + return cli.force_text(out), cli.force_text(err) diff --git a/tests/test_data_input_stdin.py b/tests/test_data_input_stdin.py new file mode 100644 index 0000000..f9cce61 --- /dev/null +++ b/tests/test_data_input_stdin.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +import pytest + +from jinja2cli import cli + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + + +def test_stdin_implicit_subprocess(): + out, err = run_jinja2(TEMPLATE, input_data="title: foo") + assert "" == err + assert "foo" == out + + +def test_stdin_explicit_subprocess(): + out, err = run_jinja2(TEMPLATE, "-", input_data="title: foo") + assert "" == err + assert "foo" == out diff --git a/tests/test_format_env.py b/tests/test_format_env.py new file mode 100644 index 0000000..9514c84 --- /dev/null +++ b/tests/test_format_env.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + +EnvParserFn, EnvExpectException, EnvRaiseException = cli.get_format("env") + + +@pytest.mark.parametrize( + ("env", "env_data"), + [ + ("", {}), + ("foo=bar", {"foo": "bar"}), + ("foo=", {"foo": ""}), + ("foo=bar\nham=spam", {"foo": "bar", "ham": "spam"}), + ], +) +def test_env(env, env_data): + assert EnvParserFn(env) == env_data + + +def test_env_multiline_value(): + with pytest.raises(EnvExpectException): + EnvParserFn("foo=bar\nham\nspam") diff --git a/tests/test_format_hjson.py b/tests/test_format_hjson.py new file mode 100644 index 0000000..4972c3d --- /dev/null +++ b/tests/test_format_hjson.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli +from .common import is_python_version + +try: + HJsonParserFn, HJsonExpectException, HJsonRaiseException = cli.get_format( + "hjson" + ) +except cli.InvalidDataFormat: + HJsonParserFn = lambda x: x + HJsonExpectException = BaseException + HJsonRaiseException = BaseException + + +HJSON_STR = """{ + // use #, // or /**/ comments, + // omit quotes for keys + key: 1 + // omit quotes for strings + contains: everything on this line + // omit commas at the end of a line + cool: { + foo: 1 + bar: 2 + } + // allow trailing commas + list: [ + 1, + 2, + ] + // and use multiline strings + realist: + ''' + My half empty glass, + I will fill your empty half. + Now you are half full. + ''' +} +""" + +EXPECTED_DATA = { + "key": 1, + "contains": "everything on this line", + "cool": {"foo": 1, "bar": 2}, + "list": [1, 2], + "realist": "My half empty glass,\nI will fill your empty half.\nNow you are half full.", +} + + +@pytest.mark.skipif( + is_python_version(2, 7), + reason="there's no hjson package compatible with Python2.7", +) +@pytest.mark.parametrize( + ("hjson", "expected"), + [ + ("", {}), + ("{}", {}), + (HJSON_STR, EXPECTED_DATA), + ], +) +def test_hjson(hjson, expected): + assert HJsonParserFn(hjson) == expected diff --git a/tests/test_format_ini.py b/tests/test_format_ini.py new file mode 100644 index 0000000..c2ac4f5 --- /dev/null +++ b/tests/test_format_ini.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli +from .common import is_python_version + +IIinParserFn, IniExpectException, IniRaiseException = cli.get_format("ini") + + +@pytest.mark.xfail( + is_python_version(3, 12), + strict=True, + raises=AttributeError, + reason="Jinja2cli uses `configparser.ConfigParser.readfp` that is deprecated in Python3.12", +) +@pytest.mark.parametrize( + ("ini", "ini_data"), + [ + ("", {}), + ("[data]\nfoo=bar", {"data": {"foo": "bar"}}), + ("[data]\nfoo=bar\nham=spam", {"data": {"foo": "bar", "ham": "spam"}}), + ( + "[data1]\nfoo=bar\n[data2]\nham=spam", + {"data1": {"foo": "bar"}, "data2": {"ham": "spam"}}, + ), + pytest.param( + "[data]\nfoo=bar\n[data]\nham=spam", + {"data": {"foo": "bar", "ham": "spam"}}, + marks=pytest.mark.skipif( + not is_python_version(2, 7), + reason="Duplicate data section names are not supported by configparser in python versions > 2.7", + ), + ), + ], +) +def test_ini(ini, ini_data): + assert IIinParserFn(ini) == ini_data + + +@pytest.mark.xfail( + is_python_version(3, 12), + strict=True, + raises=AttributeError, + reason="Jinja2cli uses `configparser.ConfigParser.readfp` that is deprecated in Python3.12", +) +@pytest.mark.parametrize( + ("data"), + [ + ("foo=bar\nham=spam"), + ("[data]foo=\nbar"), + ], +) +def test_ini_errors(data): + with pytest.raises(IniExpectException): + IIinParserFn(data) diff --git a/tests/test_format_json.py b/tests/test_format_json.py new file mode 100644 index 0000000..dc3d135 --- /dev/null +++ b/tests/test_format_json.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + + +import pytest + +from jinja2cli import cli + +JsonParserFn, JsonExpectException, JsonRaiseException = cli.get_format("json") + + +@pytest.mark.parametrize( + ("json", "json_data"), + [ + ("{}", {}), + ('{"foo": "bar"}', {"foo": "bar"}), + ('{"": "bar"}', {"": "bar"}), + ('{"foo": "bar", "ham": "spam"}', {"foo": "bar", "ham": "spam"}), + ], +) +def test_json(json, json_data): + assert JsonParserFn(json) == json_data + + +@pytest.mark.parametrize( + ("data"), + [ + (""), + ('{foo: "bar"}'), + ('{"foo": bar}'), + ], +) +def test_json_errors(data): + with pytest.raises(JsonExpectException): + JsonParserFn(data) diff --git a/tests/test_format_json5.py b/tests/test_format_json5.py new file mode 100644 index 0000000..41f80d8 --- /dev/null +++ b/tests/test_format_json5.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + + +Json5ParserFn, Json5ExpectException, Json5RaiseException = cli.get_format("json5") + + +@pytest.mark.parametrize( + ("json5", "expected"), + [ + ("{}", {}), + ( + "{ // comments\n " + "unquoted: 'and you can quote me on that',\n " + "singleQuotes: 'I can use \"double quotes\" here',\n " + "hexadecimal: 0xdecaf,\n " + "leadingDecimalPoint: .8675309, andTrailing: 8675309.,\n " + "positiveSign: +1,\n " + "trailingComma: 'in objects', andIn: ['arrays',],\n " + "\"backwardsCompatible\": \"with JSON\",\n" + "}\n", + { + "unquoted": "and you can quote me on that", + "singleQuotes": 'I can use "double quotes" here', + "hexadecimal": 0xDECAF, + "leadingDecimalPoint": 0.8675309, + "andTrailing": 8675309.0, + "positiveSign": 1, + "trailingComma": "in objects", + "andIn": [ + "arrays", + ], + "backwardsCompatible": "with JSON", + }, + ), + pytest.param( + '{foo: "bar\nham"}', + {"foo": "bar\nham"}, + marks=pytest.mark.skip( + reason="json5 package doesn't support line breaks in values, may change in the future since hjson" + ), + ), + ], +) +def test_json5(json5, expected): + assert Json5ParserFn(json5) == expected + + +@pytest.mark.parametrize( + ("json5"), + [ + (""), + ], +) +def test_json5_errors(json5): + with pytest.raises(Json5ExpectException): + Json5ParserFn(json5) diff --git a/tests/test_format_querystring.py b/tests/test_format_querystring.py new file mode 100644 index 0000000..90a6dbb --- /dev/null +++ b/tests/test_format_querystring.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + +QSParserFn, QSExpectException, QSRaiseException = cli.get_format("querystring") + + +@pytest.mark.parametrize( + ("qs", "expected"), + [ + ("", {}), + ("foo=bar", {"foo": "bar"}), + ("foo=", {}), + ("foo=bar&ham=spam", {"foo": "bar", "ham": "spam"}), + ( + "foo.bar=ham&ham.spam=eggs", + {"foo": {"bar": "ham"}, "ham": {"spam": "eggs"}}, + ), + ("foo=bar%20ham%20spam", {"foo": "bar ham spam"}), + ("foo=bar%2Eham%2Espam", {"foo": "bar.ham.spam"}), + ( + "foo.bar.ham=spam&foo.bar.spam=eggs", + {"foo": {"bar": {"ham": "spam", "spam": "eggs"}}}, + ), + ( + "foo.bar.ham=spam&foo.baz.ham=spam", + {"foo": {"bar": {"ham": "spam"}, "baz": {"ham": "spam"}}}, + ), + ], +) +def test_qs(qs, expected): + assert expected == QSParserFn(qs) diff --git a/tests/test_format_toml.py b/tests/test_format_toml.py new file mode 100644 index 0000000..7f7d9bc --- /dev/null +++ b/tests/test_format_toml.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + +TomlParserFn, TomlExpectException, TomlRaiseException = cli.get_format("toml") + + +@pytest.mark.parametrize( + ("toml", "toml_data"), + [ + ("", {}), + ("foo=''\n", {"foo": ""}), + ("foo='bar'\n", {"foo": "bar"}), + ("''='bar'\n", {"": "bar"}), + ], +) +def test_toml(toml, toml_data): + assert TomlParserFn(toml) == toml_data + + +@pytest.mark.parametrize( + ("data"), + [ + ("foo"), + ("foo=bar\n"), + ("foo=bar ham=spam\n"), + ("='bar'\n"), + ], +) +def test_toml_errors(data): + with pytest.raises(TomlExpectException): + TomlParserFn(data) diff --git a/tests/test_format_xml.py b/tests/test_format_xml.py new file mode 100644 index 0000000..c113730 --- /dev/null +++ b/tests/test_format_xml.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + +XMLParserFn, XMLExpectException, XMLRaiseException = cli.get_format("xml") + + +@pytest.mark.parametrize( + ("xml", "xml_data"), + [ + ("", {"data": None}), + ("foo", {"data": "foo"}), + ("", {"data": {"foo": None}}), + ("bar", {"data": {"foo": "bar"}}), + ( + "barspam", + {"data": {"foo": "bar", "ham": "spam"}}, + ), + ], +) +def test_xml(xml, xml_data): + assert XMLParserFn(xml) == xml_data + + +@pytest.mark.parametrize( + ("data"), + [ + (""), + (""), + (""), + (""), + ], +) +def test_xml_errors(data): + with pytest.raises(XMLExpectException): + XMLParserFn(data) diff --git a/tests/test_format_yaml.py b/tests/test_format_yaml.py new file mode 100644 index 0000000..f1c8e6c --- /dev/null +++ b/tests/test_format_yaml.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import pytest + +from jinja2cli import cli + +YamlParserFn, YamlExpectException, YamlRaiseException = cli.get_format("yaml") + + +@pytest.mark.parametrize( + ("yaml", "yaml_data"), + [ + ("", None), + ("foo", "foo"), + ("foo: \n", {"foo": None}), + ("foo: bar", {"foo": "bar"}), + ("foo: bar\nham: spam", {"foo": "bar", "ham": "spam"}), + ("foo: |\n bar\n ham\n spam", {"foo": "bar\nham\nspam"}), + ("foo: >\n bar\n ham\n spam", {"foo": "bar ham spam"}), + ("foo: \n- bar\n- ham\n- spam", {"foo": ["bar", "ham", "spam"]}), + ("- foo", ["foo"]), + ], +) +def test_yaml(yaml, yaml_data): + assert YamlParserFn(yaml) == yaml_data + + +@pytest.mark.parametrize( + ("data"), + [ + ("foo: \nbar"), + ("foo: |\nbar"), + ], +) +def test_yaml_errors(data): + with pytest.raises(YamlExpectException): + YamlParserFn(data) diff --git a/tests/test_opt_d_variables.py b/tests/test_opt_d_variables.py new file mode 100644 index 0000000..01219fa --- /dev/null +++ b/tests/test_opt_d_variables.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +import pytest + +from jinja2cli import cli + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + + +def test_d_variables(): + out, err = run_jinja2(TEMPLATE, args=("-D", "title=foo")) + assert "" == err + assert "foo" == out + + +def test_d_variables_overrides_other_data(): + out, err = run_jinja2( + TEMPLATE, args=("-D", "title=foo"), input_data="title: bar" + ) + assert "" == err + assert "foo" == out diff --git a/tests/test_opt_extensions.py b/tests/test_opt_extensions.py new file mode 100644 index 0000000..abd6c26 --- /dev/null +++ b/tests/test_opt_extensions.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +import sys + +import pytest + +from jinja2cli import cli + +from .common import is_python_version, run_jinja2, to_unicode + +TEMPLATE_CONTENT = "{% uppercase %}{{title}}{% enduppercase %}" + + +def test_opt_extensions_short(tmp_path): + template_file = tmp_path / "template.j2" + + if is_python_version(2): + template_file.write_text(unicode(TEMPLATE_CONTENT)) + else: + template_file.write_text(TEMPLATE_CONTENT) + + out, err = run_jinja2( + str(template_file), + args=("-e", "common.UpperCaseExtension"), + input_data="title: foo", + ) + + assert "" == err + assert "FOO" == out + + +def test_opt_extensions_long(tmp_path): + template_file = tmp_path / "template.j2" + + if is_python_version(2): + template_file.write_text(unicode(TEMPLATE_CONTENT)) + else: + template_file.write_text(TEMPLATE_CONTENT) + + out, err = run_jinja2( + str(template_file), + args=("--extension", "common.UpperCaseExtension"), + input_data="title: foo", + ) + + assert "" == err + assert "FOO" == out diff --git a/tests/test_opt_format.py b/tests/test_opt_format.py new file mode 100644 index 0000000..31c0923 --- /dev/null +++ b/tests/test_opt_format.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + + +def test_opt_format_short(tmp_path): + datafile = tmp_path / "datafile.env" + datafile.write_text("title=foo") + + out, err = run_jinja2(TEMPLATE, str(datafile), ("-f", "env")) + assert "" == err + assert "foo" == out + + +def test_opt_format_long(tmp_path): + datafile = tmp_path / "datafile.env" + datafile.write_text("title=foo") + + out, err = run_jinja2(TEMPLATE, str(datafile), ("--format", "env")) + assert "" == err + assert "foo" == out diff --git a/tests/test_opt_format_auto.py b/tests/test_opt_format_auto.py new file mode 100644 index 0000000..7849b88 --- /dev/null +++ b/tests/test_opt_format_auto.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + + +def test_opt_format_auto_implicit(tmp_path): + datafile = tmp_path / "datafile.env" + datafile.write_text("title=foo") + + out, err = run_jinja2(TEMPLATE, str(datafile)) + assert "" == err + assert "foo" == out + + +def test_opt_format_auto_explicit(tmp_path): + datafile = tmp_path / "datafile.env" + datafile.write_text("title=foo") + + out, err = run_jinja2(TEMPLATE, str(datafile), ("-f", "auto")) + assert "" == err + assert "foo" == out diff --git a/tests/test_opt_outfile.py b/tests/test_opt_outfile.py new file mode 100644 index 0000000..78f40d1 --- /dev/null +++ b/tests/test_opt_outfile.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +import pytest + +from jinja2cli import cli + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + + +def test_opt_outfile_short(tmp_path): + outfile = tmp_path / "outfile" + out, err = run_jinja2( + TEMPLATE, args=("-o", str(outfile)), input_data="title: foo" + ) + + assert "" == err + assert "" == out + assert "foo" == outfile.read_text() + + +def test_opt_outfile_long(tmp_path): + outfile = tmp_path / "outfile" + out, err = run_jinja2( + TEMPLATE, args=("--outfile", str(outfile)), input_data="title: foo" + ) + + assert "" == err + assert "" == out + assert "foo" == outfile.read_text() diff --git a/tests/test_opt_section.py b/tests/test_opt_section.py new file mode 100644 index 0000000..cbad1d6 --- /dev/null +++ b/tests/test_opt_section.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +import pytest + +from jinja2cli import cli + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + +DATA_W_SECTIONS = ( + """{"title_data": {"title": "foo"}, "other_data": {"title": "bar"}}""" +) + + +def test_section_short(): + out, err = run_jinja2( + TEMPLATE, args=("-s", "title_data"), input_data=DATA_W_SECTIONS + ) + assert "" == err + assert "foo" == out + + +def test_section_long(): + out, err = run_jinja2( + TEMPLATE, args=("--section", "title_data"), input_data=DATA_W_SECTIONS + ) + assert "" == err + assert "foo" == out diff --git a/tests/test_opt_strict.py b/tests/test_opt_strict.py new file mode 100644 index 0000000..b9a478c --- /dev/null +++ b/tests/test_opt_strict.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +import pytest + +from jinja2cli import cli + +from .common import run_jinja2 + +TEMPLATE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "files/template.j2" +) + +UNDEFINED_ERROR = "jinja2.exceptions.UndefinedError: 'title' is undefined" + + +def test_strict_enabled(): + out, err = run_jinja2(TEMPLATE, args=("--strict",)) + assert UNDEFINED_ERROR in err + assert "" == out + + +def test_strict_disabled(): + out, err = run_jinja2(TEMPLATE) + assert "" == err + assert "" == out diff --git a/tests/test_parse_qs.py b/tests/test_parse_qs.py deleted file mode 100644 index 0ebbb89..0000000 --- a/tests/test_parse_qs.py +++ /dev/null @@ -1,21 +0,0 @@ -import pytest - -from jinja2cli import cli - -QS_PARSER_FN, QS_EXCEPT_EXC, QS_RAISE_EXC = cli.get_format("querystring") - - -@pytest.mark.parametrize( - ("qs", "qs_data"), - [ - ("", dict()), - ("foo=", dict()), - ("foo=bar", dict(foo="bar")), - ("foo=bar&ham=spam", dict(foo="bar", ham="spam")), - ("foo.bar=ham&ham.spam=eggs", dict(foo=dict(bar="ham"), ham=dict(spam="eggs"))), - ("foo=bar%20ham%20spam", dict(foo="bar ham spam")), - ("foo=bar%2Eham%2Espam", dict(foo="bar.ham.spam")), - ], -) -def test_parse_qs(qs, qs_data): - assert QS_PARSER_FN(qs) == qs_data diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..4d9bf5e --- /dev/null +++ b/tox.ini @@ -0,0 +1,45 @@ +[tox] +minversion = 3.28 +requires = + virtualenv<20.22.0 + tox-pyenv-redux==0.1.1 + +env_list = py{27 ,35, 36, 37, 38, 39, 310, 311, 312} + +[testenv] +description = run the tests with pytest +pyenv_discovery = fallback +deps = + -r {toxinidir}/requirements.txt + -r {toxinidir}/requirements_dev.txt + +commands = + pytest {tty:--color=yes} {posargs:-vv tests} + python --version + +[testenv:py27] +basepython = python2.7 + +[testenv:py35] +basepython = python3.5 + +[testenv:py36] +basepython = python3.6 + +[testenv:py37] +basepython = python3.7 + +[testenv:py38] +basepython = python3.8 + +[testenv:py39] +basepython = python3.9 + +[testenv:py310] +basepython = python3.10 + +[testenv:py311] +basepython = python3.11 + +[testenv:py312] +basepython = python3.12