Coverage for tests / unit / parsers / streaming / test_json_lines.py: 100%
44 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for stream_json_lines function."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
7import pytest
8from assertpy import assert_that
10from lintro.parsers.streaming import stream_json_lines
12if TYPE_CHECKING:
13 from collections.abc import Callable
15 from tests.unit.parsers.streaming.conftest import SimpleIssue
18def test_parses_string(
19 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
20) -> None:
21 """Parse newline-separated JSON objects from string.
23 Args:
24 parse_test_item: Fixture providing a parser function for test items.
25 """
26 output = (
27 '{"file": "a.py", "message": "error1"}\n{"file": "b.py", "message": "error2"}\n'
28 )
29 results = list(stream_json_lines(output, parse_test_item))
31 assert_that(results).is_length(2)
32 assert_that(results[0].file).is_equal_to("a.py")
33 assert_that(results[1].file).is_equal_to("b.py")
36def test_parses_iterable(
37 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
38) -> None:
39 """Parse JSON objects from line iterable.
41 Args:
42 parse_test_item: Fixture providing a parser function for test items.
43 """
44 lines = [
45 '{"file": "c.py", "message": "msg1"}',
46 '{"file": "d.py", "message": "msg2"}',
47 ]
48 results = list(stream_json_lines(lines, parse_test_item))
50 assert_that(results).is_length(2)
51 assert_that(results[0].file).is_equal_to("c.py")
52 assert_that(results[1].file).is_equal_to("d.py")
55def test_skips_empty_lines(
56 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
57) -> None:
58 """Skip empty lines in output.
60 Args:
61 parse_test_item: Fixture providing a parser function for test items.
62 """
63 output = '{"file": "a.py"}\n\n\n{"file": "b.py"}\n'
64 results = list(stream_json_lines(output, parse_test_item))
66 assert_that(results).is_length(2)
69def test_skips_non_json_lines(
70 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
71) -> None:
72 """Skip lines that don't start with opening brace.
74 Args:
75 parse_test_item: Fixture providing a parser function for test items.
76 """
77 output = 'some info\n{"file": "a.py"}\nmore text\n'
78 results = list(stream_json_lines(output, parse_test_item))
80 assert_that(results).is_length(1)
81 assert_that(results[0].file).is_equal_to("a.py")
84def test_handles_invalid_json(
85 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
86) -> None:
87 """Handle invalid JSON gracefully without raising.
89 Args:
90 parse_test_item: Fixture providing a parser function for test items.
91 """
92 output = '{"file": "a.py"}\n{invalid json}\n{"file": "b.py"}\n'
93 results = list(stream_json_lines(output, parse_test_item))
95 assert_that(results).is_length(2)
98@pytest.mark.parametrize(
99 "output",
100 [
101 "",
102 "\n",
103 "\n\n\n",
104 ],
105)
106def test_empty_output_yields_nothing(
107 output: str,
108 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
109) -> None:
110 """Empty or whitespace-only output yields no results.
112 Args:
113 output: Parameterized output string to parse.
114 parse_test_item: Fixture providing a parser function for test items.
115 """
116 results = list(stream_json_lines(output, parse_test_item))
118 assert_that(results).is_empty()
121def test_skips_items_where_parser_returns_none(
122 parse_test_item: Callable[[dict[str, object]], SimpleIssue | None],
123) -> None:
124 """Skip items when parse function returns None.
126 Args:
127 parse_test_item: Fixture providing a parser function for test items.
128 """
130 def selective_parser(item: dict[str, object]) -> SimpleIssue | None:
131 if item.get("skip"):
132 return None
133 return parse_test_item(item)
135 output = '{"file": "a.py"}\n{"file": "b.py", "skip": true}\n{"file": "c.py"}\n'
136 results = list(stream_json_lines(output, selective_parser))
138 assert_that(results).is_length(2)
139 assert_that(results[0].file).is_equal_to("a.py")
140 assert_that(results[1].file).is_equal_to("c.py")