jest-test-lineage-reporter 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +252 -0
  2. package/bin/jest-lineage.js +20 -0
  3. package/package.json +14 -5
  4. package/src/MutationTester.js +1154 -0
  5. package/src/__tests__/assertion-test.test.ts +59 -0
  6. package/src/__tests__/calculator.test.ts +30 -0
  7. package/src/__tests__/depth-example.test.ts +237 -0
  8. package/src/__tests__/gc-pressure-example.test.ts +169 -0
  9. package/src/__tests__/performance-example.test.ts +83 -0
  10. package/src/__tests__/quality-example.test.ts +122 -0
  11. package/src/__tests__/survived-mutations-example.test.ts +32 -0
  12. package/src/__tests__/truly-weak-example.test.ts +90 -0
  13. package/src/__tests__/weak-test-example.test.ts +222 -0
  14. package/src/babel-plugin-mutation-tester.js +402 -0
  15. package/src/calculator.ts +12 -0
  16. package/src/cli/commands/analyze.js +91 -0
  17. package/src/cli/commands/mutate.js +89 -0
  18. package/src/cli/commands/query.js +107 -0
  19. package/src/cli/commands/report.js +65 -0
  20. package/src/cli/commands/test.js +56 -0
  21. package/src/cli/index.js +89 -0
  22. package/src/cli/utils/config-loader.js +114 -0
  23. package/src/cli/utils/data-loader.js +118 -0
  24. package/src/cli/utils/jest-runner.js +105 -0
  25. package/src/cli/utils/output-formatter.js +126 -0
  26. package/src/depth-example.ts +66 -0
  27. package/src/gc-pressure-example.ts +158 -0
  28. package/src/global.d.ts +7 -0
  29. package/src/mcp/server.js +469 -0
  30. package/src/performance-example.ts +82 -0
  31. package/src/quality-example.ts +79 -0
  32. package/src/survived-mutations-example.ts +19 -0
  33. package/src/truly-weak-example.ts +37 -0
  34. package/src/weak-test-example.ts +91 -0
@@ -0,0 +1,59 @@
1
+ import { directFunction } from '../depth-example';
2
+
3
+ describe('Assertion Counting Test', () => {
4
+ test('should count multiple expect statements correctly', () => {
5
+ // This test has many expect statements to test assertion counting
6
+
7
+ const result1 = directFunction(5);
8
+ expect(result1).toBe(10);
9
+ expect(result1).toBeGreaterThan(5);
10
+ expect(result1).toBeLessThan(20);
11
+
12
+ const result2 = directFunction(0);
13
+ expect(result2).toBe(0);
14
+ expect(result2).toEqual(0);
15
+ expect(result2).not.toBe(1);
16
+
17
+ const result3 = directFunction(-5);
18
+ expect(result3).toBe(-10);
19
+ expect(result3).toBeLessThan(0);
20
+ expect(result3).toBeGreaterThan(-20);
21
+
22
+ // Test arrays and objects
23
+ const results = [result1, result2, result3];
24
+ expect(results).toHaveLength(3);
25
+ expect(results).toContain(10);
26
+ expect(results).toContain(0);
27
+ expect(results).toContain(-10);
28
+
29
+ // Test properties
30
+ const obj = { value: result1 };
31
+ expect(obj).toHaveProperty('value');
32
+ expect(obj).toHaveProperty('value', 10);
33
+
34
+ // Test null/undefined
35
+ expect(result1).toBeDefined();
36
+ expect(result1).not.toBeNull();
37
+ expect(result1).not.toBeUndefined();
38
+
39
+ // Test truthiness
40
+ expect(result1).toBeTruthy();
41
+ expect(result2).toBeFalsy();
42
+
43
+ // Test error handling
44
+ expect(() => {
45
+ if (result1 < 0) {
46
+ throw new Error('Should not be negative');
47
+ }
48
+ }).not.toThrow();
49
+
50
+ // This test should show:
51
+ // - 22+ expect statements (high assertion count)
52
+ // - Error handling with expect().not.toThrow()
53
+ // - Property testing with toHaveProperty()
54
+ // - Array testing with toContain() and toHaveLength()
55
+ // - Boundary testing with toBeGreaterThan/toBeLessThan
56
+ // - Null/undefined testing
57
+ // - Truthiness testing
58
+ });
59
+ });
@@ -0,0 +1,30 @@
1
+ import { add, subtract, multiply } from '../calculator';
2
+
3
+ describe('Calculator', () => {
4
+ it('should correctly add two numbers', () => {
5
+ expect(add(1, 2)).toBe(3);
6
+ });
7
+
8
+ it('should subtract a smaller number from a larger one', () => {
9
+ expect(subtract(5, 2)).toBe(3); // This will hit line 9
10
+ });
11
+
12
+ it('should subtract a larger number from a smaller one and return a positive result', () => {
13
+ expect(subtract(2, 5)).toBe(3); // This will hit line 7
14
+ });
15
+
16
+ // This test covers the same line as the first subtraction test, which our report will show.
17
+ it('should handle zero correctly in subtraction', () => {
18
+ expect(subtract(10, 0)).toBe(10); // This will also hit line 9
19
+ });
20
+
21
+ // This test ONLY calls multiply, so it will show different coverage
22
+ it('should multiply two numbers correctly', () => {
23
+ expect(multiply(3, 4)).toBe(12); // This will ONLY hit line 13 (multiply function)
24
+ });
25
+
26
+ // This test ONLY calls add, so it will show different coverage
27
+ it('should add negative numbers', () => {
28
+ expect(add(-5, -3)).toBe(-8); // This will ONLY hit lines 2-3 (add function)
29
+ });
30
+ });
@@ -0,0 +1,237 @@
1
+ import {
2
+ directFunction,
3
+ oneLevel,
4
+ twoLevels,
5
+ threeLevels,
6
+ complexFunction,
7
+ recursiveFunction,
8
+ memoryLeakFunction,
9
+ clearMemoryLeaks,
10
+ getMemoryLeakCount
11
+ } from '../depth-example';
12
+
13
+ describe('Call Depth Tracking Examples', () => {
14
+ test('should call directFunction directly (depth 1)', () => {
15
+ const result = directFunction(5);
16
+ expect(result).toBe(10);
17
+ });
18
+
19
+ test('should call directFunction through oneLevel (depth 2)', () => {
20
+ const result = oneLevel(5);
21
+ expect(result).toBe(11);
22
+ });
23
+
24
+ test('should call directFunction through twoLevels (depth 3)', () => {
25
+ const result = twoLevels(5);
26
+ expect(result).toBe(12);
27
+ });
28
+
29
+ test('should call directFunction through threeLevels (depth 4)', () => {
30
+ const result = threeLevels(5);
31
+ expect(result).toBe(13);
32
+ });
33
+
34
+ test('should call directFunction at multiple depths in complexFunction', () => {
35
+ const result = complexFunction(5);
36
+ expect(result).toBe(33); // 10 + 11 + 12 = 33
37
+ });
38
+
39
+ test('should call directFunction through recursive calls (very deep)', () => {
40
+ const result = recursiveFunction(5);
41
+ expect(result).toBe(13); // 10 + 1 + 1 + 1 = 13
42
+ });
43
+
44
+ test('should demonstrate memory leak detection with large allocations', () => {
45
+ // This test intentionally creates memory leaks to demonstrate tracking
46
+ const largeArrays = [];
47
+
48
+ // Create multiple large arrays (each >1MB) to trigger memory leak detection
49
+ for (let i = 0; i < 3; i++) {
50
+ // Allocate ~2MB array (will trigger 🚨LEAK alert)
51
+ const largeArray = new Array(500000).fill(0).map((_, index) => ({
52
+ id: index,
53
+ data: `Large data string for item ${index} with extra padding to increase memory usage`,
54
+ timestamp: Date.now(),
55
+ metadata: {
56
+ created: new Date(),
57
+ processed: false,
58
+ tags: ['memory', 'test', 'large', 'allocation']
59
+ }
60
+ }));
61
+
62
+ largeArrays.push(largeArray);
63
+
64
+ // Call our function to track memory usage at different call depths
65
+ const result = directFunction(i);
66
+ expect(result).toBe(i * 2);
67
+ }
68
+
69
+ // Verify we created the expected number of arrays
70
+ expect(largeArrays).toHaveLength(3);
71
+ expect(largeArrays[0]).toHaveLength(500000);
72
+
73
+ // Test edge cases with memory allocation
74
+ expect(largeArrays[0][0]).toHaveProperty('id', 0);
75
+ expect(largeArrays[0][0]).toHaveProperty('data');
76
+ expect(largeArrays[0][0].metadata).toHaveProperty('tags');
77
+ expect(largeArrays[0][0].metadata.tags).toContain('memory');
78
+
79
+ // Test error conditions
80
+ expect(() => {
81
+ if (largeArrays.length === 0) {
82
+ throw new Error('No arrays created');
83
+ }
84
+ }).not.toThrow();
85
+
86
+ // Test boundary conditions
87
+ expect(largeArrays[2][499999]).toHaveProperty('id', 499999);
88
+
89
+ // This should show high memory usage, multiple assertions, and good error handling
90
+ // Expected quality metrics:
91
+ // - High assertion count (8+ expect statements)
92
+ // - Error handling (try/catch equivalent with expect().not.toThrow())
93
+ // - Edge case testing (boundary values, null checks)
94
+ // - Memory leak detection (large allocations)
95
+ });
96
+
97
+ test('should demonstrate GC pressure with many small allocations', () => {
98
+ const smallObjects = [];
99
+
100
+ // Create many small objects to trigger GC pressure detection
101
+ for (let i = 0; i < 1000; i++) {
102
+ // Small allocations (<1KB each) to trigger 🗑️GC alert
103
+ const smallObj = {
104
+ id: i,
105
+ value: Math.random(),
106
+ processed: false
107
+ };
108
+ smallObjects.push(smallObj);
109
+
110
+ // Call function at different depths to test performance impact
111
+ if (i % 100 === 0) {
112
+ const result = oneLevel(i);
113
+ expect(result).toBeGreaterThan(i);
114
+ }
115
+ }
116
+
117
+ expect(smallObjects).toHaveLength(1000);
118
+ expect(smallObjects[999]).toHaveProperty('id', 999);
119
+
120
+ // This should show GC pressure but smaller memory footprint
121
+ });
122
+
123
+ test('should demonstrate slow execution patterns', () => {
124
+ const results = [];
125
+
126
+ // Create intentionally variable performance to trigger slow execution detection
127
+ for (let i = 0; i < 5; i++) {
128
+ const startTime = Date.now();
129
+
130
+ // Sometimes do heavy work, sometimes light work (creates performance variance)
131
+ if (i % 2 === 0) {
132
+ // Heavy work - should be slower
133
+ let heavyResult = 0;
134
+ for (let j = 0; j < 10000; j++) {
135
+ heavyResult += Math.sin(j) * Math.cos(j);
136
+ }
137
+ results.push(heavyResult);
138
+ } else {
139
+ // Light work - should be faster
140
+ results.push(i * 2);
141
+ }
142
+
143
+ const result = directFunction(i);
144
+ expect(result).toBe(i * 2);
145
+
146
+ const endTime = Date.now();
147
+ expect(endTime).toBeGreaterThanOrEqual(startTime);
148
+ }
149
+
150
+ expect(results).toHaveLength(5);
151
+
152
+ // This should show performance variance and trigger 🐌SLOW alert
153
+ });
154
+
155
+ test('should create actual memory leaks with large objects', () => {
156
+ // Clear any existing leaks first
157
+ const initialCount = getMemoryLeakCount();
158
+ expect(initialCount).toBeGreaterThanOrEqual(0);
159
+
160
+ // Create multiple memory leaks with large objects
161
+ for (let i = 0; i < 3; i++) {
162
+ // Each call creates ~1MB of leaked memory (1000 items * 1KB each)
163
+ const result = memoryLeakFunction(1000);
164
+ expect(result).toBe(1000 * 2); // directFunction returns x * 2
165
+
166
+ // Verify memory leak count is increasing
167
+ const currentCount = getMemoryLeakCount();
168
+ expect(currentCount).toBe(initialCount + i + 1);
169
+ }
170
+
171
+ // Verify we have created 3 memory leaks
172
+ const finalCount = getMemoryLeakCount();
173
+ expect(finalCount).toBe(initialCount + 3);
174
+
175
+ // This test should show:
176
+ // - High memory usage (3MB+ leaked)
177
+ // - 🚨LEAK alerts in console
178
+ // - Multiple expect() statements (good assertion count)
179
+ // - Error handling with expect().toBe() validations
180
+ });
181
+
182
+ test('should create massive memory leak for testing', () => {
183
+ // Create a very large memory leak to ensure detection
184
+ const initialMemoryCount = getMemoryLeakCount();
185
+
186
+ // Create 5 large objects (each ~2MB)
187
+ for (let i = 0; i < 5; i++) {
188
+ const result = memoryLeakFunction(2000); // 2000 items * ~1KB each = ~2MB
189
+ expect(result).toBe(2000 * 2);
190
+
191
+ // Verify the leak is growing
192
+ expect(getMemoryLeakCount()).toBeGreaterThan(initialMemoryCount + i);
193
+ }
194
+
195
+ // Verify total memory leaks
196
+ const totalLeaks = getMemoryLeakCount();
197
+ expect(totalLeaks).toBeGreaterThanOrEqual(initialMemoryCount + 5);
198
+
199
+ // Test edge cases
200
+ expect(() => memoryLeakFunction(0)).not.toThrow();
201
+ expect(memoryLeakFunction(0)).toBe(0);
202
+
203
+ // Test error conditions
204
+ expect(() => {
205
+ if (totalLeaks < 0) {
206
+ throw new Error('Invalid leak count');
207
+ }
208
+ }).not.toThrow();
209
+
210
+ // This should create ~10MB of leaked memory and trigger multiple 🚨LEAK alerts
211
+ // Quality metrics should show:
212
+ // - High assertion count (8+ expect statements)
213
+ // - Good error handling (expect().not.toThrow())
214
+ // - Edge case testing (zero values, negative checks)
215
+ // - Boundary testing (memory thresholds)
216
+ });
217
+
218
+ test('should demonstrate memory cleanup', () => {
219
+ // Create some leaks first
220
+ const result1 = memoryLeakFunction(500);
221
+ const result2 = memoryLeakFunction(500);
222
+
223
+ expect(result1).toBe(1000);
224
+ expect(result2).toBe(1000);
225
+ expect(getMemoryLeakCount()).toBeGreaterThanOrEqual(2);
226
+
227
+ // Clear all memory leaks
228
+ const clearedCount = clearMemoryLeaks();
229
+ expect(clearedCount).toBeGreaterThanOrEqual(2);
230
+ expect(getMemoryLeakCount()).toBe(0);
231
+
232
+ // Verify cleanup worked
233
+ expect(getMemoryLeakCount()).toBe(0);
234
+
235
+ // This test shows proper cleanup and should have fewer memory issues
236
+ });
237
+ });
@@ -0,0 +1,169 @@
1
+ import {
2
+ badGCPressureFunction,
3
+ goodGCPressureFunction,
4
+ badStringConcatenation,
5
+ goodStringConcatenation,
6
+ badArrayOperations,
7
+ goodArrayOperations,
8
+ objectPoolExample
9
+ } from '../gc-pressure-example';
10
+
11
+ describe.skip('GC Pressure Examples', () => {
12
+ test.skip('should demonstrate BAD GC pressure with many small objects', () => {
13
+ // This test creates many small objects and should trigger 🗑️GC alerts
14
+
15
+ const result1 = badGCPressureFunction(1000); // Creates 2000+ small objects
16
+ expect(result1).toBeGreaterThan(0);
17
+ expect(typeof result1).toBe('number');
18
+
19
+ const result2 = badGCPressureFunction(500); // Creates 1000+ small objects
20
+ expect(result2).toBeGreaterThan(0);
21
+ expect(result2).toBeLessThan(result1);
22
+
23
+ // Test edge cases
24
+ expect(badGCPressureFunction(0)).toBe(0);
25
+ expect(badGCPressureFunction(1)).toBeGreaterThan(0);
26
+
27
+ // This should show:
28
+ // - 🗑️GC alerts due to many small object allocations
29
+ // - High memory churn but relatively small total memory
30
+ // - Multiple expect statements for good test quality
31
+ });
32
+
33
+ test('should demonstrate GOOD GC behavior with object reuse', () => {
34
+ // This test reuses objects and should have minimal GC pressure
35
+
36
+ const result1 = goodGCPressureFunction(1000); // Reuses same objects
37
+ expect(result1).toBeGreaterThan(0);
38
+ expect(typeof result1).toBe('number');
39
+
40
+ const result2 = goodGCPressureFunction(500);
41
+ expect(result2).toBeGreaterThan(0);
42
+ expect(result2).toBeLessThan(result1);
43
+
44
+ // Test edge cases
45
+ expect(goodGCPressureFunction(0)).toBe(0);
46
+ expect(goodGCPressureFunction(1)).toBeGreaterThan(0);
47
+
48
+ // This should show:
49
+ // - Minimal or no 🗑️GC alerts
50
+ // - Lower memory usage than the bad example
51
+ // - Better performance consistency
52
+ });
53
+
54
+ test('should demonstrate BAD string concatenation GC pressure', () => {
55
+ // String concatenation in loops creates many temporary strings
56
+
57
+ const items = Array.from({ length: 1000 }, (_, i) => `item${i}`);
58
+
59
+ const result = badStringConcatenation(items);
60
+ expect(result).toContain('item0');
61
+ expect(result).toContain('item999');
62
+ expect(result.split(', ')).toHaveLength(1001); // 1000 items + empty string at end
63
+
64
+ // Test with smaller arrays
65
+ const smallItems = ['a', 'b', 'c'];
66
+ const smallResult = badStringConcatenation(smallItems);
67
+ expect(smallResult).toBe('a, b, c, ');
68
+
69
+ // This should trigger 🗑️GC due to many temporary string objects
70
+ });
71
+
72
+ test('should demonstrate GOOD string concatenation', () => {
73
+ // Array.join() creates only one final string
74
+
75
+ const items = Array.from({ length: 1000 }, (_, i) => `item${i}`);
76
+
77
+ const result = goodStringConcatenation(items);
78
+ expect(result).toContain('item0');
79
+ expect(result).toContain('item999');
80
+ expect(result.split(', ')).toHaveLength(1000);
81
+
82
+ // Test with smaller arrays
83
+ const smallItems = ['a', 'b', 'c'];
84
+ const smallResult = goodStringConcatenation(smallItems);
85
+ expect(smallResult).toBe('a, b, c');
86
+
87
+ // This should have minimal GC pressure
88
+ });
89
+
90
+ test('should demonstrate BAD array operations with multiple allocations', () => {
91
+ // Chained array operations create many intermediate arrays
92
+
93
+ const numbers = Array.from({ length: 1000 }, (_, i) => i);
94
+
95
+ const result = badArrayOperations(numbers);
96
+ expect(Array.isArray(result)).toBe(true);
97
+ expect(result.length).toBeGreaterThan(0);
98
+ expect(result.every(x => x % 2 === 0)).toBe(true);
99
+ expect(result.every(x => x > 10)).toBe(true);
100
+
101
+ // Test edge cases
102
+ expect(badArrayOperations([])).toEqual([]);
103
+ expect(badArrayOperations([1, 2, 3])).toEqual([]);
104
+ expect(badArrayOperations([10, 20, 30])).toEqual([22, 42, 62]);
105
+
106
+ // This should trigger 🗑️GC due to multiple intermediate arrays
107
+ });
108
+
109
+ test('should demonstrate GOOD array operations with single allocation', () => {
110
+ // Single reduce operation creates only one final array
111
+
112
+ const numbers = Array.from({ length: 1000 }, (_, i) => i);
113
+
114
+ const result = goodArrayOperations(numbers);
115
+ expect(Array.isArray(result)).toBe(true);
116
+ expect(result.length).toBeGreaterThan(0);
117
+ expect(result.every(x => x % 2 === 0)).toBe(true);
118
+ expect(result.every(x => x > 10)).toBe(true);
119
+
120
+ // Test edge cases
121
+ expect(goodArrayOperations([])).toEqual([]);
122
+ expect(goodArrayOperations([1, 2, 3])).toEqual([]);
123
+ expect(goodArrayOperations([10, 20, 30])).toEqual([22, 42, 62]);
124
+
125
+ // This should have minimal GC pressure
126
+ });
127
+
128
+ test('should demonstrate object pooling for optimal GC behavior', () => {
129
+ // Object pooling reuses pre-allocated objects
130
+
131
+ const result1 = objectPoolExample(1000);
132
+ expect(result1).toBeGreaterThan(0);
133
+ expect(typeof result1).toBe('number');
134
+
135
+ const result2 = objectPoolExample(500);
136
+ expect(result2).toBeGreaterThan(0);
137
+ expect(result2).toBeLessThan(result1);
138
+
139
+ // Test edge cases
140
+ expect(objectPoolExample(0)).toBe(0);
141
+ expect(objectPoolExample(1)).toBeGreaterThan(0);
142
+
143
+ // This should have the best GC behavior - minimal allocations
144
+ });
145
+
146
+ test('should compare all GC pressure patterns', () => {
147
+ // Compare all patterns to show the difference
148
+
149
+ const testSize = 100;
150
+
151
+ const badResult = badGCPressureFunction(testSize);
152
+ const goodResult = goodGCPressureFunction(testSize);
153
+ const poolResult = objectPoolExample(testSize);
154
+
155
+ // All should produce similar numerical results
156
+ expect(badResult).toBeGreaterThan(0);
157
+ expect(goodResult).toBeGreaterThan(0);
158
+ expect(poolResult).toBeGreaterThan(0);
159
+
160
+ // But GC behavior should be very different:
161
+ // - badResult: High 🗑️GC pressure
162
+ // - goodResult: Medium 🗑️GC pressure
163
+ // - poolResult: Minimal 🗑️GC pressure
164
+
165
+ expect(typeof badResult).toBe('number');
166
+ expect(typeof goodResult).toBe('number');
167
+ expect(typeof poolResult).toBe('number');
168
+ });
169
+ });
@@ -0,0 +1,83 @@
1
+ import {
2
+ lightweightFunction,
3
+ mediumFunction,
4
+ heavyFunction,
5
+ memoryIntensiveFunction,
6
+ recursiveFunction,
7
+ nestedCallsFunction,
8
+ mixedPerformanceFunction,
9
+ performanceVariableFunction
10
+ } from '../performance-example';
11
+
12
+ describe.skip('Performance Tracking Examples', () => {
13
+ test('should track lightweight function performance', () => {
14
+ // This should show minimal CPU cycles
15
+ const result = lightweightFunction(5);
16
+ expect(result).toBe(6);
17
+ });
18
+
19
+ test('should track medium function performance', () => {
20
+ // This should show moderate CPU cycles
21
+ const result = mediumFunction(4);
22
+ expect(result).toBeGreaterThan(0);
23
+ });
24
+
25
+ test('should track heavy function performance', () => {
26
+ // This should show high CPU cycles
27
+ const result = heavyFunction(2);
28
+ expect(result).toBeGreaterThan(0);
29
+ });
30
+
31
+ test('should track memory intensive function', () => {
32
+ // This should show memory allocation patterns
33
+ const result = memoryIntensiveFunction(1000);
34
+ expect(result).toHaveLength(1000);
35
+ });
36
+
37
+ test('should track recursive function with exponential complexity', () => {
38
+ // This should show very high CPU cycles due to recursion
39
+ const result = recursiveFunction(5);
40
+ expect(result).toBeGreaterThan(0);
41
+ });
42
+
43
+ test('should track nested calls with different depths', () => {
44
+ // This should show performance at different call depths
45
+ const result = nestedCallsFunction(10);
46
+ expect(result).toBeGreaterThan(0);
47
+ });
48
+
49
+ test('should track mixed performance patterns', () => {
50
+ // This should show variable performance within one test
51
+ const result = mixedPerformanceFunction(10);
52
+ expect(result).toBeGreaterThan(0);
53
+ });
54
+
55
+ test('should track fast mode performance', () => {
56
+ // Fast execution path
57
+ const result = performanceVariableFunction('fast');
58
+ expect(result).toBe(43);
59
+ });
60
+
61
+ test('should track medium mode performance', () => {
62
+ // Medium execution path
63
+ const result = performanceVariableFunction('medium');
64
+ expect(result).toBeGreaterThan(0);
65
+ });
66
+
67
+ test('should track slow mode performance', () => {
68
+ // Slow execution path
69
+ const result = performanceVariableFunction('slow');
70
+ expect(result).toBeGreaterThan(0);
71
+ });
72
+
73
+ test('should demonstrate performance hotspot', () => {
74
+ // Call heavy function multiple times to create hotspot
75
+ let total = 0;
76
+ let i = 0;
77
+ while (i < 3) {
78
+ total += heavyFunction(i);
79
+ i++;
80
+ }
81
+ expect(total).toBeGreaterThan(0);
82
+ });
83
+ });
@@ -0,0 +1,122 @@
1
+ import {
2
+ simpleFunction,
3
+ complexFunction,
4
+ asyncFunction,
5
+ errorProneFunction,
6
+ wellTestedFunction,
7
+ Calculator
8
+ } from '../quality-example';
9
+
10
+ describe('Test Quality Examples', () => {
11
+ // High quality test - good assertions, error handling, edge cases
12
+ test('wellTestedFunction should handle all edge cases properly', async () => {
13
+ // Test normal cases
14
+ expect(wellTestedFunction(5, 3)).toBe(8);
15
+ expect(wellTestedFunction(0, 0)).toBe(0);
16
+ expect(wellTestedFunction(1.5, 2.5)).toBe(4);
17
+
18
+ // Test error cases
19
+ expect(() => wellTestedFunction(null as any, 5)).toThrow('Parameter a is required');
20
+ expect(() => wellTestedFunction(5, undefined as any)).toThrow('Parameter b is required');
21
+ expect(() => wellTestedFunction('5' as any, 3)).toThrow('Both parameters must be numbers');
22
+ expect(() => wellTestedFunction(-1, 5)).toThrow('Parameters must be non-negative');
23
+ expect(() => wellTestedFunction(5, -1)).toThrow('Parameters must be non-negative');
24
+
25
+ // Test boundary cases
26
+ expect(wellTestedFunction(Number.MAX_SAFE_INTEGER, 0)).toBe(Number.MAX_SAFE_INTEGER);
27
+ expect(wellTestedFunction(0.1, 0.2)).toBeCloseTo(0.3);
28
+ });
29
+
30
+ // Medium quality test - some assertions, basic testing
31
+ test('complexFunction should handle different data types', () => {
32
+ expect(complexFunction('hello')).toBe('HELLO');
33
+ expect(complexFunction(5)).toBe(25);
34
+ expect(complexFunction(-3)).toBe(3);
35
+ expect(complexFunction(0)).toBe(1);
36
+ expect(complexFunction([1, 2, 3])).toEqual([2, 4, 6]);
37
+ expect(complexFunction({ key: 'value' })).toBe('{"key":"value"}');
38
+
39
+ // Test error cases
40
+ expect(() => complexFunction(null)).toThrow('Data is required');
41
+ expect(() => complexFunction(undefined)).toThrow('Data is required');
42
+ });
43
+
44
+ // Low quality test - minimal assertions, no error handling
45
+ test('simpleFunction basic test', () => {
46
+ expect(simpleFunction(5)).toBe(10);
47
+ });
48
+
49
+ // Async test with proper error handling
50
+ test('asyncFunction should handle async operations correctly', async () => {
51
+ const result = await asyncFunction(10);
52
+ expect(result).toBe('Completed after 10ms');
53
+
54
+ // Test error case
55
+ await expect(asyncFunction(-1)).rejects.toThrow('Delay cannot be negative');
56
+ });
57
+
58
+ // Poor quality test - no error handling for error-prone function
59
+ test('errorProneFunction test', () => {
60
+ expect(errorProneFunction('hello')).toBe('HELLO');
61
+ expect(errorProneFunction(123)).toBe('123');
62
+ // Missing: null/undefined tests that would reveal bugs
63
+ });
64
+
65
+ // Test with mocking (affects isolation score)
66
+ test('Calculator with mocking', () => {
67
+ const calculator = new Calculator();
68
+ const spy = jest.spyOn(calculator, 'add');
69
+
70
+ calculator.add(2, 3);
71
+ expect(spy).toHaveBeenCalledWith(2, 3);
72
+ expect(calculator.getHistory()).toEqual([5]);
73
+
74
+ spy.mockRestore();
75
+ });
76
+
77
+ // Long test (test smell)
78
+ test('long test with many assertions', () => {
79
+ const calc = new Calculator();
80
+
81
+ // Too many assertions in one test
82
+ expect(calc.add(1, 1)).toBe(2);
83
+ expect(calc.add(2, 2)).toBe(4);
84
+ expect(calc.add(3, 3)).toBe(6);
85
+ expect(calc.add(4, 4)).toBe(8);
86
+ expect(calc.add(5, 5)).toBe(10);
87
+ expect(calc.add(6, 6)).toBe(12);
88
+ expect(calc.add(7, 7)).toBe(14);
89
+ expect(calc.add(8, 8)).toBe(16);
90
+ expect(calc.add(9, 9)).toBe(18);
91
+ expect(calc.add(10, 10)).toBe(20);
92
+ expect(calc.add(11, 11)).toBe(22);
93
+ expect(calc.add(12, 12)).toBe(24);
94
+
95
+ expect(calc.getHistory()).toHaveLength(12);
96
+ calc.clearHistory();
97
+ expect(calc.getHistory()).toHaveLength(0);
98
+ });
99
+
100
+ // Test with complex control flow (high complexity)
101
+ test('complex control flow test', () => {
102
+ let result = 0;
103
+
104
+ for (let i = 0; i < 10; i++) {
105
+ if (i % 2 === 0) {
106
+ if (i % 4 === 0) {
107
+ result += complexFunction(i);
108
+ } else {
109
+ result += simpleFunction(i);
110
+ }
111
+ } else {
112
+ if (i > 5) {
113
+ result -= i;
114
+ } else {
115
+ result += i;
116
+ }
117
+ }
118
+ }
119
+
120
+ expect(result).toBeGreaterThan(0);
121
+ });
122
+ });