Coverage for tests / unit / parsers / test_oxfmt_parser.py: 100%
84 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"""Unit tests for oxfmt parser."""
3from __future__ import annotations
5import pytest
6from assertpy import assert_that
8from lintro.parsers.oxfmt.oxfmt_parser import parse_oxfmt_output
11@pytest.mark.parametrize(
12 "output",
13 [
14 None,
15 "",
16 ],
17 ids=["none", "empty"],
18)
19def test_parse_oxfmt_output_returns_empty_for_no_content(
20 output: str | None,
21) -> None:
22 """Parse empty or None output returns empty list.
24 Args:
25 output: The oxfmt output to parse.
26 """
27 result = parse_oxfmt_output(output)
28 assert_that(result).is_empty()
31def test_parse_oxfmt_output_single_file() -> None:
32 """Parse single file path into one issue."""
33 output = "src/file1.js"
34 result = parse_oxfmt_output(output)
35 assert_that(result).is_length(1)
36 assert_that(result[0].file).is_equal_to("src/file1.js")
37 assert_that(result[0].line).is_equal_to(1)
38 assert_that(result[0].column).is_equal_to(1)
39 assert_that(result[0].message).is_equal_to("File is not formatted")
40 assert_that(result[0].code).is_equal_to("FORMAT")
43def test_parse_oxfmt_output_multiple_files() -> None:
44 """Parse multiple file paths into multiple issues."""
45 output = """src/file1.js
46src/file2.ts
47src/components/Button.tsx"""
48 result = parse_oxfmt_output(output)
49 assert_that(result).is_length(3)
50 assert_that(result[0].file).is_equal_to("src/file1.js")
51 assert_that(result[1].file).is_equal_to("src/file2.ts")
52 assert_that(result[2].file).is_equal_to("src/components/Button.tsx")
55def test_parse_oxfmt_output_empty_lines_handling() -> None:
56 """Empty lines are ignored."""
57 output = """src/a.js
59src/b.js
61"""
62 result = parse_oxfmt_output(output)
63 assert_that(result).is_length(2)
64 assert_that(result[0].file).is_equal_to("src/a.js")
65 assert_that(result[1].file).is_equal_to("src/b.js")
68def test_parse_oxfmt_output_whitespace_handling() -> None:
69 """Whitespace around file paths is stripped."""
70 output = """ src/file1.js
71 src/file2.ts
72 src/file3.jsx """
73 result = parse_oxfmt_output(output)
74 assert_that(result).is_length(3)
75 assert_that(result[0].file).is_equal_to("src/file1.js")
76 assert_that(result[1].file).is_equal_to("src/file2.ts")
77 assert_that(result[2].file).is_equal_to("src/file3.jsx")
80def test_parse_oxfmt_output_whitespace_only_lines() -> None:
81 """Lines with only whitespace are ignored."""
82 output = """src/file.js
85src/other.js"""
86 result = parse_oxfmt_output(output)
87 assert_that(result).is_length(2)
90def test_parse_oxfmt_output_ansi_escape_codes_stripped() -> None:
91 """ANSI escape codes are stripped from output."""
92 output = "\x1b[33msrc/file.js\x1b[39m"
93 result = parse_oxfmt_output(output)
94 assert_that(result).is_length(1)
95 assert_that(result[0].file).is_equal_to("src/file.js")
98def test_parse_oxfmt_output_default_line_and_column() -> None:
99 """Default line and column are 1."""
100 output = "src/file.js"
101 result = parse_oxfmt_output(output)
102 assert_that(result[0].line).is_equal_to(1)
103 assert_that(result[0].column).is_equal_to(1)
106def test_parse_oxfmt_output_deeply_nested_path() -> None:
107 """Handle deeply nested file paths."""
108 deep_path = "a/b/c/d/e/f/g/h/i/j/component.tsx"
109 result = parse_oxfmt_output(deep_path)
110 assert_that(result).is_length(1)
111 assert_that(result[0].file).is_equal_to(deep_path)
114def test_parse_oxfmt_output_various_extensions() -> None:
115 """Handle various JavaScript/TypeScript/Vue file extensions."""
116 output = """file.js
117file.mjs
118file.cjs
119file.jsx
120file.ts
121file.mts
122file.cts
123file.tsx
124file.vue"""
125 result = parse_oxfmt_output(output)
126 assert_that(result).is_length(9)
127 extensions = [issue.file.split(".")[-1] for issue in result]
128 assert_that(extensions).contains(
129 "js",
130 "mjs",
131 "cjs",
132 "jsx",
133 "ts",
134 "mts",
135 "cts",
136 "tsx",
137 "vue",
138 )
141def test_parse_oxfmt_output_file_with_spaces_in_name() -> None:
142 """Handle file paths with spaces in name."""
143 output = "src/my component.js"
144 result = parse_oxfmt_output(output)
145 assert_that(result).is_length(1)
146 assert_that(result[0].file).is_equal_to("src/my component.js")
149def test_parse_oxfmt_output_filters_error_messages() -> None:
150 """Error messages from oxfmt are filtered out."""
151 output = """Expected at least one target file
152src/file.js
153error: Something went wrong
154src/other.ts"""
155 result = parse_oxfmt_output(output)
156 assert_that(result).is_length(2)
157 assert_that(result[0].file).is_equal_to("src/file.js")
158 assert_that(result[1].file).is_equal_to("src/other.ts")
161def test_parse_oxfmt_output_filters_non_supported_extensions() -> None:
162 """Files with unsupported extensions are filtered out."""
163 output = """src/file.js
164src/styles.css
165src/config.json
166src/readme.md
167src/component.tsx"""
168 result = parse_oxfmt_output(output)
169 # Only .js and .tsx in the test data are valid oxfmt extensions (.css, .json, .md are not)
170 assert_that(result).is_length(2)
171 assert_that(result[0].file).is_equal_to("src/file.js")
172 assert_that(result[1].file).is_equal_to("src/component.tsx")
175def test_parse_oxfmt_output_filters_warning_messages() -> None:
176 """Warning messages from oxfmt are filtered out."""
177 output = """WARNING: Some warning
178src/file.ts
179Warning: Another warning
180warning: lowercase warning"""
181 result = parse_oxfmt_output(output)
182 assert_that(result).is_length(1)
183 assert_that(result[0].file).is_equal_to("src/file.ts")