1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
"""CLI test module."""
import argparse
import io
import json
import pytest
from gjson._cli import cli
from gjson.exceptions import GJSONParseError
from .test_init import INPUT_JSON, INPUT_LINES, INPUT_LINES_WITH_ERRORS
def test_cli_help(capsys):
"""It should read the data from stdin and query it."""
with pytest.raises(SystemExit) as exc_info:
cli(['--help'])
assert exc_info.value.args[0] == 0
captured = capsys.readouterr()
assert 'usage: gjson' in captured.out
assert 'See also the full documentation available at' in captured.out
assert not captured.err
def test_cli_stdin(monkeypatch, capsys):
"""It should read the data from stdin and query it."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_JSON))
ret = cli(['-', 'name.first'])
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '"Tom"\n'
assert not captured.err
def test_cli_file(tmp_path, capsys):
"""It should read the data from the provided file and query it."""
data_file = tmp_path / 'input.json'
data_file.write_text(INPUT_JSON)
ret = cli([str(data_file), 'name.first'])
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '"Tom"\n'
assert not captured.err
@pytest.mark.parametrize('query', (
'a\tkey',
'..0.a\tkey',
))
def test_cli_file_with_control_chars(query, tmp_path, capsys):
"""It should read the data from the provided file and query it."""
data_file = tmp_path / 'input.json'
data_file.write_text('{"a\tkey": "a\tvalue"}')
ret = cli(['-vvv', str(data_file), query])
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '"a\\tvalue"\n'
assert not captured.err
@pytest.mark.parametrize('query', (
'a\tkey',
'..0.a\tkey',
))
@pytest.mark.parametrize('lines', (True, False))
def test_cli_stdin_with_control_chars(query, lines, monkeypatch, capsys):
"""It should read the data from stdin and query it."""
monkeypatch.setattr('sys.stdin', io.StringIO('{"a\tkey": "a\tvalue"}'))
params = ['-vvv', '-', query]
if lines:
params.insert(0, '--lines')
ret = cli(params)
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '"a\\tvalue"\n'
assert not captured.err
def test_cli_nonexistent_file(tmp_path, capsys):
"""It should exit with a failure exit code and no output."""
ret = cli([str(tmp_path / 'nonexistent.json'), 'name.first'])
assert ret == 1
captured = capsys.readouterr()
assert not captured.out
assert not captured.err
def test_cli_nonexistent_file_verbosity_1(tmp_path, capsys):
"""It should exit with a failure exit code and print the error message."""
ret = cli(['-v', str(tmp_path / 'nonexistent.json'), 'name.first'])
assert ret == 1
captured = capsys.readouterr()
assert not captured.out
assert captured.err.startswith("ArgumentTypeError: can't open")
assert 'nonexistent.json' in captured.err
def test_cli_nonexistent_file_verbosity_2(tmp_path):
"""It should raise the exception and print the full traceback."""
with pytest.raises(
argparse.ArgumentTypeError, match=r"can't open .*/nonexistent.json.* No such file or directory"):
cli(['-vv', str(tmp_path / 'nonexistent.json'), 'name.first'])
def test_cli_stdin_query_verbosity_1(monkeypatch, capsys):
"""It should exit with a failure exit code and print the error message."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_JSON))
ret = cli(['-v', '-', 'nonexistent'])
assert ret == 1
captured = capsys.readouterr()
assert not captured.out
assert captured.err == ('GJSONParseError: Mapping object does not have key `nonexistent`.\n'
'Query: nonexistent\n-------^\n')
def test_cli_stdin_query_verbosity_2(monkeypatch):
"""It should exit with a failure exit code and print the full traceback."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_JSON))
with pytest.raises(GJSONParseError, match=r'Mapping object does not have key `nonexistent`.'):
cli(['-vv', '-', 'nonexistent'])
def test_cli_lines_ok(monkeypatch, capsys):
"""It should apply the same query to each line."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES))
ret = cli(['--lines', '-', 'name'])
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '"Gilbert"\n"Alexa"\n"May"\n"Deloise"\n'
assert not captured.err
def test_cli_lines_failed_lines_verbosity_0(monkeypatch, capsys):
"""It should keep going with the other lines and just skip the failed line."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
ret = cli(['--lines', '-', 'name'])
assert ret == 1
captured = capsys.readouterr()
assert captured.out == '"Gilbert"\n"Deloise"\n'
assert not captured.err
def test_cli_lines_failed_lines_verbosity_1(monkeypatch, capsys):
"""It should keep going with the other lines printing an error for the failed lines."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
ret = cli(['-v', '--lines', '-', 'name'])
assert ret == 1
captured = capsys.readouterr()
assert captured.out == '"Gilbert"\n"Deloise"\n'
assert captured.err.count('JSONDecodeError') == 2
def test_cli_lines_failed_lines_verbosity_2(monkeypatch):
"""It should interrupt the processing and print the full traceback."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
with pytest.raises(
json.decoder.JSONDecodeError, match=r'Expecting property name enclosed in double quotes'):
cli(['-vv', '--lines', '-', 'name'])
def test_cli_lines_double_dot_query(monkeypatch, capsys):
"""It should encapsulate each line in an array to allow queries."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES))
ret = cli(['--lines', '..#(age>45).name'])
assert ret == 1
captured = capsys.readouterr()
assert captured.out == '"Gilbert"\n"May"\n'
assert not captured.err
def test_cli_double_dot_query_ok(monkeypatch, capsys):
"""It should encapsulate the input in an array and apply the query to the array."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES))
ret = cli(['-', '..#.name'])
assert ret == 0
captured = capsys.readouterr()
assert captured.out == '["Gilbert", "Alexa", "May", "Deloise"]\n'
assert not captured.err
def test_cli_double_dot_query_failed_lines_verbosity_0(monkeypatch, capsys):
"""It should encapsulate the input in an array skipping failing lines."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
ret = cli(['-', '..#.name'])
assert ret == 1
captured = capsys.readouterr()
assert not captured.out
assert not captured.err
def test_cli_double_dot_query_failed_lines_verbosity_1(monkeypatch, capsys):
"""It should encapsulate the input in an array skipping failing lines and printing an error for each failure."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
ret = cli(['-v', '-', '..#.name'])
assert ret == 1
captured = capsys.readouterr()
assert not captured.out
assert captured.err.startswith('JSONDecodeError: Expecting property name enclosed in double quotes')
def test_cli_double_dot_query_failed_lines_verbosity_2(monkeypatch):
"""It should interrupt the execution at the first invalid line and exit printing the traceback."""
monkeypatch.setattr('sys.stdin', io.StringIO(INPUT_LINES_WITH_ERRORS))
with pytest.raises(json.decoder.JSONDecodeError, match=r'Expecting property name enclosed in double quotes'):
cli(['-vv', '-', '..#.name'])
|