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

1"""Unit tests for oxfmt parser.""" 

2 

3from __future__ import annotations 

4 

5import pytest 

6from assertpy import assert_that 

7 

8from lintro.parsers.oxfmt.oxfmt_parser import parse_oxfmt_output 

9 

10 

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. 

23 

24 Args: 

25 output: The oxfmt output to parse. 

26 """ 

27 result = parse_oxfmt_output(output) 

28 assert_that(result).is_empty() 

29 

30 

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") 

41 

42 

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") 

53 

54 

55def test_parse_oxfmt_output_empty_lines_handling() -> None: 

56 """Empty lines are ignored.""" 

57 output = """src/a.js 

58 

59src/b.js 

60 

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") 

66 

67 

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") 

78 

79 

80def test_parse_oxfmt_output_whitespace_only_lines() -> None: 

81 """Lines with only whitespace are ignored.""" 

82 output = """src/file.js 

83 

84 

85src/other.js""" 

86 result = parse_oxfmt_output(output) 

87 assert_that(result).is_length(2) 

88 

89 

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") 

96 

97 

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) 

104 

105 

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) 

112 

113 

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 ) 

139 

140 

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") 

147 

148 

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") 

159 

160 

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") 

173 

174 

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")