Coverage for tests / unit / utils / native_parsers / test_jsonc_comments.py: 100%
92 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 strip_jsonc_comments function."""
3from __future__ import annotations
5import json
6from unittest.mock import patch
8import pytest
9from assertpy import assert_that
11from lintro.utils.jsonc import strip_jsonc_comments as _strip_jsonc_comments
14def test_strip_jsonc_comments_no_comments() -> None:
15 """Return unchanged content when no comments are present."""
16 content = '{"key": "value", "num": 42}'
17 result = _strip_jsonc_comments(content)
18 assert_that(result).is_equal_to(content)
21def test_strip_jsonc_comments_line_comment() -> None:
22 """Strip single-line // comments from the end of lines."""
23 content = '{"key": "value"} // this is a comment'
24 result = _strip_jsonc_comments(content)
25 assert_that(result.strip()).is_equal_to('{"key": "value"}')
28def test_strip_jsonc_comments_line_comment_on_own_line() -> None:
29 """Strip full-line // comments appearing at the start of lines."""
30 content = '// comment at start\n{"key": "value"}'
31 result = _strip_jsonc_comments(content)
32 parsed = json.loads(result)
33 assert_that(parsed["key"]).is_equal_to("value")
36def test_strip_jsonc_comments_block_comment() -> None:
37 """Strip /* */ block comments from content."""
38 content = '{"key": /* comment */ "value"}'
39 result = _strip_jsonc_comments(content)
40 parsed = json.loads(result)
41 assert_that(parsed["key"]).is_equal_to("value")
44def test_strip_jsonc_comments_multiline_block_comment() -> None:
45 """Strip multi-line /* */ block comments spanning multiple lines."""
46 content = '{\n/* this is\na multi-line\ncomment */\n"key": "value"\n}'
47 result = _strip_jsonc_comments(content)
48 parsed = json.loads(result)
49 assert_that(parsed["key"]).is_equal_to("value")
52@pytest.mark.parametrize(
53 ("content", "expected_key", "expected_value"),
54 [
55 (
56 '{"url": "https://example.com", "pattern": "/* glob */"}',
57 "url",
58 "https://example.com",
59 ),
60 (
61 '{"url": "https://example.com", "pattern": "/* glob */"}',
62 "pattern",
63 "/* glob */",
64 ),
65 ],
66 ids=["preserve_url_with_slashes", "preserve_glob_pattern_in_string"],
67)
68def test_strip_jsonc_comments_preserve_comment_like_strings(
69 content: str,
70 expected_key: str,
71 expected_value: str,
72) -> None:
73 """Preserve // and /* patterns that appear inside string values.
75 Args:
76 content: JSONC content with comment-like patterns in strings.
77 expected_key: Key to check in the parsed result.
78 expected_value: Expected value for the key.
79 """
80 result = _strip_jsonc_comments(content)
81 parsed = json.loads(result)
82 assert_that(parsed[expected_key]).is_equal_to(expected_value)
85def test_strip_jsonc_comments_escape_sequence_in_string() -> None:
86 """Handle escaped quotes in strings without treating them as string ends."""
87 content = '{"message": "He said \\"hello\\""}'
88 result = _strip_jsonc_comments(content)
89 parsed = json.loads(result)
90 assert_that(parsed["message"]).is_equal_to('He said "hello"')
93def test_strip_jsonc_comments_backslash_in_string() -> None:
94 """Handle backslash escape sequences in strings correctly."""
95 content = '{"path": "C:\\\\Users\\\\test"}'
96 result = _strip_jsonc_comments(content)
97 parsed = json.loads(result)
98 assert_that(parsed["path"]).is_equal_to("C:\\Users\\test")
101def test_strip_jsonc_comments_unclosed_block_comment_warning() -> None:
102 """Warn when a block comment is not properly closed."""
103 content = '{"key": "value"} /* unclosed'
104 with patch("lintro.utils.jsonc.logger") as mock_logger:
105 _strip_jsonc_comments(content)
106 mock_logger.warning.assert_called_once()
109def test_strip_jsonc_comments_empty_content() -> None:
110 """Handle empty content gracefully by returning empty string."""
111 result = _strip_jsonc_comments("")
112 assert_that(result).is_empty()
115def test_strip_jsonc_comments_complex_jsonc() -> None:
116 """Parse complex JSONC with multiple comment types and nested structures."""
117 content = """{
118 // Configuration
119 "name": "test",
120 /*
121 * Multi-line
122 * description
123 */
124 "settings": {
125 "enabled": true // inline comment
126 }
127}"""
128 result = _strip_jsonc_comments(content)
129 parsed = json.loads(result)
130 assert_that(parsed["name"]).is_equal_to("test")
131 assert_that(parsed["settings"]["enabled"]).is_true()
134def test_strip_jsonc_comments_unicode_content() -> None:
135 """Handle Unicode characters in JSON content."""
136 content = '{"message": "日本語テスト", "emoji": "🚀"}'
137 result = _strip_jsonc_comments(content)
138 parsed = json.loads(result)
139 assert_that(parsed["message"]).is_equal_to("日本語テスト")
140 assert_that(parsed["emoji"]).is_equal_to("🚀")
143def test_strip_jsonc_comments_very_long_content() -> None:
144 """Handle very long JSON content."""
145 long_value = "x" * 10000
146 content = f'{{"key": "{long_value}"}}'
147 result = _strip_jsonc_comments(content)
148 parsed = json.loads(result)
149 assert_that(len(parsed["key"])).is_equal_to(10000)
152def test_strip_jsonc_comments_nested_comments() -> None:
153 """Handle nested block comment patterns (only outer is stripped)."""
154 content = '{"key": "value"} /* outer /* inner */ still comment */'
155 result = _strip_jsonc_comments(content)
156 # The inner "/*" should be consumed by the outer comment
157 assert_that('{"key": "value"}' in result).is_true()
160def test_strip_jsonc_comments_consecutive_comments() -> None:
161 """Handle consecutive block comments."""
162 content = '/* first */ {"key": "value"} /* second */'
163 result = _strip_jsonc_comments(content)
164 parsed = json.loads(result)
165 assert_that(parsed["key"]).is_equal_to("value")
168def test_strip_jsonc_comments_mixed_quotes() -> None:
169 """Handle content with different quote styles in strings."""
170 content = (
171 """{"single": "has 'single' quotes", "double": "has \\"double\\" quotes"}"""
172 )
173 result = _strip_jsonc_comments(content)
174 parsed = json.loads(result)
175 assert_that(parsed["single"]).contains("single")
178def test_strip_jsonc_comments_only_whitespace() -> None:
179 """Handle content that is only whitespace."""
180 result = _strip_jsonc_comments(" \n\t \n ")
181 assert_that(result.strip()).is_empty()
184def test_strip_jsonc_comments_deeply_nested_json() -> None:
185 """Handle deeply nested JSON structures."""
186 content = '{"a": {"b": {"c": {"d": {"e": "deep"}}}}} // comment'
187 result = _strip_jsonc_comments(content)
188 parsed = json.loads(result)
189 assert_that(parsed["a"]["b"]["c"]["d"]["e"]).is_equal_to("deep")