Coverage for tests / test_npath / test_typescript.py: 100%
81 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-08 15:04 -0800
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-08 15:04 -0800
1"""Tests for NPath complexity (TypeScript)."""
3from analyzers.typescript import analyze_source
6def _npath(code: str) -> int:
7 """Return NPath of the first function in code."""
8 result = analyze_source(code)
9 assert result.functions, f"No functions found in:\n{code}"
10 return result.functions[0].npath
13def _npaths(code: str) -> dict[str, int]:
14 """Return {name: npath} for all functions in code."""
15 result = analyze_source(code)
16 return {f.name: f.npath for f in result.functions}
19# --- Simple ---
21def test_simple_function():
22 assert _npath("function f() {}") == 1
25def test_empty_source():
26 result = analyze_source("")
27 assert len(result.functions) == 0
30# --- If statements ---
32def test_if_only():
33 code = """
34function f(x: boolean) {
35 if (x) {
36 return 1;
37 }
38}
39"""
40 assert _npath(code) == 2
43def test_if_else():
44 code = """
45function f(x: boolean) {
46 if (x) {
47 return 1;
48 } else {
49 return 2;
50 }
51}
52"""
53 assert _npath(code) == 2
56def test_if_elif_else():
57 code = """
58function f(x: number) {
59 if (x > 0) {
60 return 1;
61 } else if (x < 0) {
62 return -1;
63 } else {
64 return 0;
65 }
66}
67"""
68 assert _npath(code) == 3
71def test_if_elif_no_else():
72 code = """
73function f(x: number) {
74 if (x > 0) {
75 return 1;
76 } else if (x < 0) {
77 return -1;
78 }
79}
80"""
81 assert _npath(code) == 3 # +1 for no terminal else
84# --- Bool ops ---
86def test_bool_ops_in_if():
87 code = """
88function f(a: boolean, b: boolean) {
89 if (a && b) {
90 return 1;
91 }
92}
93"""
94 assert _npath(code) == 3 # 1 + 1 + 1 bool op
97def test_two_bool_ops():
98 code = """
99function f(a: boolean, b: boolean, c: boolean) {
100 if (a && b || c) {
101 return 1;
102 }
103}
104"""
105 assert _npath(code) == 4 # 1 + 1 + 2 bool ops
108# --- Loops ---
110def test_for_loop():
111 code = """
112function f() {
113 for (let i = 0; i < 10; i++) {
114 console.log(i);
115 }
116}
117"""
118 assert _npath(code) == 2
121def test_while_loop():
122 code = """
123function f(x: boolean) {
124 while (x) {
125 break;
126 }
127}
128"""
129 assert _npath(code) == 2
132def test_while_with_bool_cond():
133 code = """
134function f(a: boolean, b: boolean) {
135 while (a && b) {
136 break;
137 }
138}
139"""
140 assert _npath(code) == 3
143def test_do_while():
144 code = """
145function f(x: boolean) {
146 do {
147 break;
148 } while (x);
149}
150"""
151 assert _npath(code) == 2
154def test_do_while_with_bool_cond():
155 code = """
156function f(a: boolean, b: boolean) {
157 do {
158 break;
159 } while (a || b);
160}
161"""
162 assert _npath(code) == 3
165# --- Try/catch ---
167def test_try_catch():
168 code = """
169function f() {
170 try {
171 foo();
172 } catch (e) {
173 bar();
174 }
175}
176"""
177 assert _npath(code) == 2
180# --- Switch ---
182def test_switch_three_cases():
183 code = """
184function f(x: number) {
185 switch (x) {
186 case 1: break;
187 case 2: break;
188 case 3: break;
189 }
190}
191"""
192 assert _npath(code) == 4 # 1+1+1 + 1 (no default)
195def test_switch_with_default():
196 code = """
197function f(x: number) {
198 switch (x) {
199 case 1: break;
200 case 2: break;
201 default: break;
202 }
203}
204"""
205 assert _npath(code) == 3 # 1+1+1, has default
208# --- Ternary ---
210def test_ternary():
211 code = """
212function f(c: boolean, x: number, y: number) {
213 return c ? x : y;
214}
215"""
216 assert _npath(code) == 2
219def test_nested_ternary():
220 code = """
221function f(c1: boolean, c2: boolean) {
222 return c1 ? 1 : (c2 ? 2 : 3);
223}
224"""
225 assert _npath(code) == 3
228# --- Sequential ifs (multiplicative) ---
230def test_sequential_ifs():
231 code = """
232function f(a: boolean, b: boolean) {
233 if (a) { foo(); }
234 if (b) { bar(); }
235}
236"""
237 assert _npath(code) == 4
240# --- Nested if ---
242def test_nested_if():
243 code = """
244function f(a: boolean, b: boolean) {
245 if (a) {
246 if (b) {
247 foo();
248 }
249 }
250}
251"""
252 assert _npath(code) == 3
255# --- Arrow functions ---
257def test_named_arrow():
258 code = """
259const f = (x: boolean) => {
260 if (x) {
261 return 1;
262 }
263 return 0;
264};
265"""
266 assert _npath(code) == 2
269def test_nested_named_arrow():
270 code = """
271function outer(x: boolean) {
272 if (x) { foo(); }
273 const inner = (y: boolean) => {
274 if (y) { bar(); }
275 };
276}
277"""
278 npaths = _npaths(code)
279 assert npaths["outer"] == 2 # inner arrow counts as 1
280 assert npaths["inner"] == 2
283# --- Method definition ---
285def test_method_definition():
286 code = """
287class Foo {
288 bar(x: boolean) {
289 if (x) {
290 return 1;
291 }
292 }
293}
294"""
295 assert _npath(code) == 2
298# --- For-in loop ---
300def test_for_in_loop():
301 code = """
302function f(obj: any) {
303 for (const key in obj) {
304 console.log(key);
305 }
306}
307"""
308 assert _npath(code) == 2