@boyingliu01/xp-gate 0.12.10 → 0.12.13
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.
- package/adapters/iac.sh +51 -24
- package/adapters/typescript.sh +87 -10
- package/bin/xp-gate.js +2 -2
- package/gate-3.sh +1 -1
- package/hooks/adapter-common.sh +13 -18
- package/hooks/pre-commit +166 -27
- package/hooks/pre-push +231 -18
- package/lib/__tests__/sprint-discovery.test.ts +5 -4
- package/lib/__tests__/sprint-status.test.ts +5 -4
- package/lib/__tests__/tsconfig.json +8 -0
- package/lib/init.js +97 -3
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
- package/principles/AGENTS.md +3 -3
- package/principles/__tests__/baseline-storage.test.ts +3 -2
- package/principles/__tests__/baseline.test.ts +16 -14
- package/principles/__tests__/types.test.ts +1 -0
- package/principles/adapters/__tests__/base.test.ts +8 -8
- package/principles/adapters/__tests__/cpp.test.ts +26 -26
- package/principles/adapters/__tests__/dart.test.ts +11 -11
- package/principles/adapters/__tests__/go.test.ts +9 -9
- package/principles/adapters/__tests__/java.test.ts +9 -9
- package/principles/adapters/__tests__/kotlin.test.ts +10 -10
- package/principles/adapters/__tests__/objectivec.test.ts +27 -27
- package/principles/adapters/__tests__/python.test.ts +11 -11
- package/principles/adapters/__tests__/swift.test.ts +9 -9
- package/principles/adapters/__tests__/typescript.test.ts +13 -13
- package/principles/rules/__tests__/clean-code/large-file.test.ts +4 -3
- package/skills/delphi-review/AGENTS.md +3 -3
- package/skills/sprint-flow/AGENTS.md +3 -3
- package/skills/test-specification-alignment/AGENTS.md +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { JavaAdapter } from '../java';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -10,7 +10,7 @@ import { readFileSync } from 'fs';
|
|
|
10
10
|
|
|
11
11
|
describe('JavaAdapter', () => {
|
|
12
12
|
it('should implement the Adapter interface', () => {
|
|
13
|
-
(readFileSync as
|
|
13
|
+
(readFileSync as Mock).mockReturnValue('public class Test {\n public void testFn() {}\n}');
|
|
14
14
|
const adapter = new JavaAdapter('Test.java');
|
|
15
15
|
|
|
16
16
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -21,24 +21,24 @@ describe('JavaAdapter', () => {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it('should detect language as java for .java files', () => {
|
|
24
|
-
(readFileSync as
|
|
24
|
+
(readFileSync as Mock).mockReturnValue('public class Test {}');
|
|
25
25
|
const adapter = new JavaAdapter('Test.java');
|
|
26
26
|
const detected = adapter.detectLanguage();
|
|
27
27
|
expect(detected).toBe('java');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should parse Java file AST correctly', () => {
|
|
31
|
-
(readFileSync as
|
|
31
|
+
(readFileSync as Mock).mockReturnValue('public class Test {\n public void testFn() {}\n}');
|
|
32
32
|
const adapter = new JavaAdapter('Test.java');
|
|
33
33
|
const ast = adapter.parseAST();
|
|
34
34
|
expect(ast).toHaveProperty('content');
|
|
35
35
|
expect(ast).toHaveProperty('language');
|
|
36
36
|
expect(ast).toHaveProperty('filePath');
|
|
37
|
-
expect(ast.language).toBe('java');
|
|
37
|
+
expect((ast as { language: unknown }).language).toBe('java');
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('should extract methods from Java AST', () => {
|
|
41
|
-
(readFileSync as
|
|
41
|
+
(readFileSync as Mock).mockReturnValue('public class Test {\n public void testFn() {}\n}');
|
|
42
42
|
const adapter = new JavaAdapter('Test.java');
|
|
43
43
|
const functions = adapter.extractFunctions();
|
|
44
44
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -46,7 +46,7 @@ describe('JavaAdapter', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should extract classes from Java AST', () => {
|
|
49
|
-
(readFileSync as
|
|
49
|
+
(readFileSync as Mock).mockReturnValue('public class Test {\n public void testFn() {}\n}');
|
|
50
50
|
const adapter = new JavaAdapter('Test.java');
|
|
51
51
|
const classes = adapter.extractClasses();
|
|
52
52
|
expect(Array.isArray(classes)).toBe(true);
|
|
@@ -54,14 +54,14 @@ describe('JavaAdapter', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('should count Java file physical lines', () => {
|
|
57
|
-
(readFileSync as
|
|
57
|
+
(readFileSync as Mock).mockReturnValue('public class Test {\n}\nclass Test2 {}');
|
|
58
58
|
const adapter = new JavaAdapter('Test.java');
|
|
59
59
|
const lineCount = adapter.countLines();
|
|
60
60
|
expect(lineCount).toBe(3);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it('should fall back to super.detectLanguage for non-java extensions', () => {
|
|
64
|
-
(readFileSync as
|
|
64
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
65
65
|
const adapter = new JavaAdapter('test.ts');
|
|
66
66
|
expect(adapter.detectLanguage()).toBe('typescript');
|
|
67
67
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { KotlinAdapter } from '../kotlin';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -10,7 +10,7 @@ import { readFileSync } from 'fs';
|
|
|
10
10
|
|
|
11
11
|
describe('KotlinAdapter', () => {
|
|
12
12
|
it('should implement the Adapter interface', () => {
|
|
13
|
-
(readFileSync as
|
|
13
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}\nclass TestClass');
|
|
14
14
|
const adapter = new KotlinAdapter('test.kt');
|
|
15
15
|
|
|
16
16
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -21,24 +21,24 @@ describe('KotlinAdapter', () => {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it('should detect language as kotlin for .kt files', () => {
|
|
24
|
-
(readFileSync as
|
|
24
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}');
|
|
25
25
|
const adapter = new KotlinAdapter('test.kt');
|
|
26
26
|
const detected = adapter.detectLanguage();
|
|
27
27
|
expect(detected).toBe('kotlin');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should parse Kotlin file AST correctly', () => {
|
|
31
|
-
(readFileSync as
|
|
31
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}\nclass TestClass');
|
|
32
32
|
const adapter = new KotlinAdapter('test.kt');
|
|
33
33
|
const ast = adapter.parseAST();
|
|
34
34
|
expect(ast).toHaveProperty('content');
|
|
35
35
|
expect(ast).toHaveProperty('language');
|
|
36
36
|
expect(ast).toHaveProperty('filePath');
|
|
37
|
-
expect(ast.language).toBe('kotlin');
|
|
37
|
+
expect((ast as { language: unknown }).language).toBe('kotlin');
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('should extract functions from Kotlin AST', () => {
|
|
41
|
-
(readFileSync as
|
|
41
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}\nclass TestClass');
|
|
42
42
|
const adapter = new KotlinAdapter('test.kt');
|
|
43
43
|
const functions = adapter.extractFunctions();
|
|
44
44
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -46,7 +46,7 @@ describe('KotlinAdapter', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should extract classes from Kotlin AST', () => {
|
|
49
|
-
(readFileSync as
|
|
49
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}\nclass TestClass');
|
|
50
50
|
const adapter = new KotlinAdapter('test.kt');
|
|
51
51
|
const classes = adapter.extractClasses();
|
|
52
52
|
expect(Array.isArray(classes)).toBe(true);
|
|
@@ -54,20 +54,20 @@ describe('KotlinAdapter', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('should count Kotlin file physical lines', () => {
|
|
57
|
-
(readFileSync as
|
|
57
|
+
(readFileSync as Mock).mockReturnValue('fun testFn() {}\nfun testFn2() {}');
|
|
58
58
|
const adapter = new KotlinAdapter('test.kt');
|
|
59
59
|
const lineCount = adapter.countLines();
|
|
60
60
|
expect(lineCount).toBe(2);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it('should fall back to super.detectLanguage for non-kotlin extensions', () => {
|
|
64
|
-
(readFileSync as
|
|
64
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
65
65
|
const adapter = new KotlinAdapter('test.ts');
|
|
66
66
|
expect(adapter.detectLanguage()).toBe('typescript');
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
it('should handle suspend functions in Kotlin', () => {
|
|
70
|
-
(readFileSync as
|
|
70
|
+
(readFileSync as Mock).mockReturnValue('suspend fun fetchData(): String { return "data" }');
|
|
71
71
|
const adapter = new KotlinAdapter('test.kt');
|
|
72
72
|
const functions = adapter.extractFunctions();
|
|
73
73
|
const suspendFns = functions.filter(fn => (fn as {type: string}).type === 'suspend_function');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { ObjectiveCAdapter } from '../objectivec';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -20,7 +20,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
20
20
|
* @covers AC-QG-001-05
|
|
21
21
|
*/
|
|
22
22
|
it('should implement the Adapter interface', () => {
|
|
23
|
-
(readFileSync as
|
|
23
|
+
(readFileSync as Mock).mockReturnValue('@implementation Test @end');
|
|
24
24
|
const adapter = new ObjectiveCAdapter('test.m');
|
|
25
25
|
|
|
26
26
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -34,7 +34,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
34
34
|
* @covers AC-QG-001-08
|
|
35
35
|
*/
|
|
36
36
|
it('should detect language as objectivec for .m files', () => {
|
|
37
|
-
(readFileSync as
|
|
37
|
+
(readFileSync as Mock).mockReturnValue('@implementation Test @end');
|
|
38
38
|
const adapter = new ObjectiveCAdapter('test.m');
|
|
39
39
|
const detected = adapter.detectLanguage();
|
|
40
40
|
expect(detected).toBe('objectivec');
|
|
@@ -45,7 +45,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
45
45
|
* @covers AC-QG-001-08
|
|
46
46
|
*/
|
|
47
47
|
it('should detect language as objectivec for .mm files (Objective-C++)', () => {
|
|
48
|
-
(readFileSync as
|
|
48
|
+
(readFileSync as Mock).mockReturnValue('@implementation Test @end');
|
|
49
49
|
const adapter = new ObjectiveCAdapter('test.mm');
|
|
50
50
|
const detected = adapter.detectLanguage();
|
|
51
51
|
expect(detected).toBe('objectivec');
|
|
@@ -56,13 +56,13 @@ describe('ObjectiveCAdapter', () => {
|
|
|
56
56
|
* @covers AC-QG-001-06
|
|
57
57
|
*/
|
|
58
58
|
it('should parse Objective-C file AST correctly', () => {
|
|
59
|
-
(readFileSync as
|
|
59
|
+
(readFileSync as Mock).mockReturnValue('@implementation Test @end');
|
|
60
60
|
const adapter = new ObjectiveCAdapter('test.m');
|
|
61
61
|
const ast = adapter.parseAST();
|
|
62
62
|
expect(ast).toHaveProperty('content');
|
|
63
63
|
expect(ast).toHaveProperty('language');
|
|
64
64
|
expect(ast).toHaveProperty('filePath');
|
|
65
|
-
expect(ast.language).toBe('objectivec');
|
|
65
|
+
expect((ast as { language: unknown }).language).toBe('objectivec');
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -70,7 +70,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
70
70
|
* @covers AC-QG-001-06
|
|
71
71
|
*/
|
|
72
72
|
it('should extract Objective-C instance methods', () => {
|
|
73
|
-
(readFileSync as
|
|
73
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
74
74
|
@implementation Calculator
|
|
75
75
|
- (int)add:(int)a to:(int)b {
|
|
76
76
|
return a + b;
|
|
@@ -91,7 +91,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
91
91
|
* @covers AC-QG-001-06
|
|
92
92
|
*/
|
|
93
93
|
it('should extract Objective-C class methods', () => {
|
|
94
|
-
(readFileSync as
|
|
94
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
95
95
|
@implementation StringUtils
|
|
96
96
|
+ (NSString *)trim:(NSString *)str {
|
|
97
97
|
return [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
@@ -111,7 +111,7 @@ describe('ObjectiveCAdapter', () => {
|
|
|
111
111
|
* @covers AC-QG-001-06
|
|
112
112
|
*/
|
|
113
113
|
it('should extract C functions from Objective-C file', () => {
|
|
114
|
-
(readFileSync as
|
|
114
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
115
115
|
int helperFunction(int x) {
|
|
116
116
|
return x * 2;
|
|
117
117
|
}
|
|
@@ -137,7 +137,7 @@ void logDebug(const char *msg) {
|
|
|
137
137
|
* @covers AC-QG-001-06
|
|
138
138
|
*/
|
|
139
139
|
it('should extract @implementation declarations', () => {
|
|
140
|
-
(readFileSync as
|
|
140
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
141
141
|
@implementation MyClass
|
|
142
142
|
- (void)doSomething {}
|
|
143
143
|
@end
|
|
@@ -154,7 +154,7 @@ void logDebug(const char *msg) {
|
|
|
154
154
|
* @covers AC-QG-001-06
|
|
155
155
|
*/
|
|
156
156
|
it('should extract @interface declarations', () => {
|
|
157
|
-
(readFileSync as
|
|
157
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
158
158
|
@interface MyProtocol
|
|
159
159
|
- (void)requiredMethod;
|
|
160
160
|
@end
|
|
@@ -171,7 +171,7 @@ void logDebug(const char *msg) {
|
|
|
171
171
|
* @covers AC-QG-001-06
|
|
172
172
|
*/
|
|
173
173
|
it('should handle multiple @implementation blocks', () => {
|
|
174
|
-
(readFileSync as
|
|
174
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
175
175
|
@implementation FirstClass
|
|
176
176
|
- (void)method1 {}
|
|
177
177
|
@end
|
|
@@ -191,7 +191,7 @@ void logDebug(const char *msg) {
|
|
|
191
191
|
* @covers AC-QG-001-06
|
|
192
192
|
*/
|
|
193
193
|
it('should handle Objective-C inheritance syntax', () => {
|
|
194
|
-
(readFileSync as
|
|
194
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
195
195
|
@interface ChildClass : ParentClass
|
|
196
196
|
- (void)overrideMethod;
|
|
197
197
|
@end
|
|
@@ -207,7 +207,7 @@ void logDebug(const char *msg) {
|
|
|
207
207
|
* @covers AC-QG-001-06
|
|
208
208
|
*/
|
|
209
209
|
it('should handle Objective-C categories', () => {
|
|
210
|
-
(readFileSync as
|
|
210
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
211
211
|
@implementation NSString (Extensions)
|
|
212
212
|
- (NSString *)reversed {
|
|
213
213
|
// implementation
|
|
@@ -224,7 +224,7 @@ void logDebug(const char *msg) {
|
|
|
224
224
|
* @covers AC-QG-001-06
|
|
225
225
|
*/
|
|
226
226
|
it('should handle Objective-C properties', () => {
|
|
227
|
-
(readFileSync as
|
|
227
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
228
228
|
@interface Person
|
|
229
229
|
@property (nonatomic, strong) NSString *name;
|
|
230
230
|
@property (nonatomic) NSInteger age;
|
|
@@ -249,7 +249,7 @@ void logDebug(const char *msg) {
|
|
|
249
249
|
* @covers AC-QG-001-06, AC-QG-001-08
|
|
250
250
|
*/
|
|
251
251
|
it('should handle Objective-C++ (.mm) files with C++ content', () => {
|
|
252
|
-
(readFileSync as
|
|
252
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
253
253
|
#import <Foundation/Foundation.h>
|
|
254
254
|
#include <vector>
|
|
255
255
|
|
|
@@ -274,7 +274,7 @@ void logDebug(const char *msg) {
|
|
|
274
274
|
* @covers AC-QG-001-05
|
|
275
275
|
*/
|
|
276
276
|
it('should count physical lines correctly', () => {
|
|
277
|
-
(readFileSync as
|
|
277
|
+
(readFileSync as Mock).mockReturnValue('@implementation Test\n- (void)method {}\n@end');
|
|
278
278
|
const adapter = new ObjectiveCAdapter('test.m');
|
|
279
279
|
const lineCount = adapter.countLines();
|
|
280
280
|
expect(lineCount).toBe(3);
|
|
@@ -285,7 +285,7 @@ void logDebug(const char *msg) {
|
|
|
285
285
|
* @covers AC-QG-001-06
|
|
286
286
|
*/
|
|
287
287
|
it('should handle empty file', () => {
|
|
288
|
-
(readFileSync as
|
|
288
|
+
(readFileSync as Mock).mockReturnValue('');
|
|
289
289
|
const adapter = new ObjectiveCAdapter('empty.m');
|
|
290
290
|
const functions = adapter.extractFunctions();
|
|
291
291
|
const classes = adapter.extractClasses();
|
|
@@ -298,7 +298,7 @@ void logDebug(const char *msg) {
|
|
|
298
298
|
* @covers AC-QG-001-06
|
|
299
299
|
*/
|
|
300
300
|
it('should handle Objective-C literals and modern syntax', () => {
|
|
301
|
-
(readFileSync as
|
|
301
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
302
302
|
@implementation ModernObjC
|
|
303
303
|
- (NSArray *)getItems {
|
|
304
304
|
return @[ @"one", @"two", @"three" ];
|
|
@@ -321,7 +321,7 @@ void logDebug(const char *msg) {
|
|
|
321
321
|
* @covers AC-QG-001-06
|
|
322
322
|
*/
|
|
323
323
|
it('should handle Objective-C blocks', () => {
|
|
324
|
-
(readFileSync as
|
|
324
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
325
325
|
@implementation BlockUser
|
|
326
326
|
- (void)useBlock {
|
|
327
327
|
void (^myBlock)(void) = ^{
|
|
@@ -341,7 +341,7 @@ void logDebug(const char *msg) {
|
|
|
341
341
|
* @covers AC-QG-001-08
|
|
342
342
|
*/
|
|
343
343
|
it('should handle preprocessor directives', () => {
|
|
344
|
-
(readFileSync as
|
|
344
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
345
345
|
#import <Foundation/Foundation.h>
|
|
346
346
|
#define MAX_SIZE 100
|
|
347
347
|
|
|
@@ -360,7 +360,7 @@ void logDebug(const char *msg) {
|
|
|
360
360
|
* @covers AC-QG-001-05
|
|
361
361
|
*/
|
|
362
362
|
it('should throw error when file cannot be read', () => {
|
|
363
|
-
(readFileSync as
|
|
363
|
+
(readFileSync as Mock).mockImplementation(() => {
|
|
364
364
|
throw new Error('Could not read file');
|
|
365
365
|
});
|
|
366
366
|
|
|
@@ -374,7 +374,7 @@ void logDebug(const char *msg) {
|
|
|
374
374
|
* @covers AC-QG-001-06
|
|
375
375
|
*/
|
|
376
376
|
it('should extract method with multiple parameters', () => {
|
|
377
|
-
(readFileSync as
|
|
377
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
378
378
|
@implementation MultiParam
|
|
379
379
|
- (void)drawRect:(CGRect)rect withColor:(UIColor *)color andAlpha:(float)alpha {
|
|
380
380
|
// drawing code
|
|
@@ -391,7 +391,7 @@ void logDebug(const char *msg) {
|
|
|
391
391
|
* @covers AC-QG-001-05, AC-QG-001-06
|
|
392
392
|
*/
|
|
393
393
|
it('should handle static inline C functions', () => {
|
|
394
|
-
(readFileSync as
|
|
394
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
395
395
|
static inline int fastAdd(int a, int b) {
|
|
396
396
|
return a + b;
|
|
397
397
|
}
|
|
@@ -413,7 +413,7 @@ static inline int fastAdd(int a, int b) {
|
|
|
413
413
|
* @covers AC-QG-001-05
|
|
414
414
|
*/
|
|
415
415
|
it('should extract line number for extracted elements', () => {
|
|
416
|
-
(readFileSync as
|
|
416
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
417
417
|
@implementation LineTest
|
|
418
418
|
- (void)firstMethod {}
|
|
419
419
|
- (void)secondMethod {}
|
|
@@ -429,7 +429,7 @@ static inline int fastAdd(int a, int b) {
|
|
|
429
429
|
* @covers AC-QG-001-05
|
|
430
430
|
*/
|
|
431
431
|
it('should extract code block for methods', () => {
|
|
432
|
-
(readFileSync as
|
|
432
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
433
433
|
@implementation CodeBlockTest
|
|
434
434
|
- (int)calculate {
|
|
435
435
|
int result = 0;
|
|
@@ -446,7 +446,7 @@ static inline int fastAdd(int a, int b) {
|
|
|
446
446
|
});
|
|
447
447
|
|
|
448
448
|
it('should fall back to super.detectLanguage for non-m/non-mm extensions', () => {
|
|
449
|
-
(readFileSync as
|
|
449
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
450
450
|
const adapter = new ObjectiveCAdapter('test.ts');
|
|
451
451
|
expect(adapter.detectLanguage()).toBe('typescript');
|
|
452
452
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { PythonAdapter } from '../python';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -10,7 +10,7 @@ import { readFileSync } from 'fs';
|
|
|
10
10
|
|
|
11
11
|
describe('PythonAdapter', () => {
|
|
12
12
|
it('should implement the Adapter interface', () => {
|
|
13
|
-
(readFileSync as
|
|
13
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass\nclass TestClass:');
|
|
14
14
|
const adapter = new PythonAdapter('test.py');
|
|
15
15
|
|
|
16
16
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -21,24 +21,24 @@ describe('PythonAdapter', () => {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it('should detect language as python for .py files', () => {
|
|
24
|
-
(readFileSync as
|
|
24
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass');
|
|
25
25
|
const adapter = new PythonAdapter('test.py');
|
|
26
26
|
const detected = adapter.detectLanguage();
|
|
27
27
|
expect(detected).toBe('python');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should parse Python file AST correctly', () => {
|
|
31
|
-
(readFileSync as
|
|
31
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass\nclass TestClass:');
|
|
32
32
|
const adapter = new PythonAdapter('test.py');
|
|
33
33
|
const ast = adapter.parseAST();
|
|
34
34
|
expect(ast).toHaveProperty('content');
|
|
35
35
|
expect(ast).toHaveProperty('language');
|
|
36
36
|
expect(ast).toHaveProperty('filePath');
|
|
37
|
-
expect(ast.language).toBe('python');
|
|
37
|
+
expect((ast as { language: unknown }).language).toBe('python');
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('should extract functions from Python AST', () => {
|
|
41
|
-
(readFileSync as
|
|
41
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass\nclass TestClass:');
|
|
42
42
|
const adapter = new PythonAdapter('test.py');
|
|
43
43
|
const functions = adapter.extractFunctions();
|
|
44
44
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -46,7 +46,7 @@ describe('PythonAdapter', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should extract classes from Python AST', () => {
|
|
49
|
-
(readFileSync as
|
|
49
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass\nclass TestClass:');
|
|
50
50
|
const adapter = new PythonAdapter('test.py');
|
|
51
51
|
const classes = adapter.extractClasses();
|
|
52
52
|
expect(Array.isArray(classes)).toBe(true);
|
|
@@ -54,27 +54,27 @@ describe('PythonAdapter', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('should count Python file physical lines', () => {
|
|
57
|
-
(readFileSync as
|
|
57
|
+
(readFileSync as Mock).mockReturnValue('def test_fn(): pass\ndef test_fn2(): pass');
|
|
58
58
|
const adapter = new PythonAdapter('test.py');
|
|
59
59
|
const lineCount = adapter.countLines();
|
|
60
60
|
expect(lineCount).toBe(2);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it('should handle async functions in Python', () => {
|
|
64
|
-
(readFileSync as
|
|
64
|
+
(readFileSync as Mock).mockReturnValue('async def async_fn(): pass');
|
|
65
65
|
const adapter = new PythonAdapter('test.py');
|
|
66
66
|
const functions = adapter.extractFunctions();
|
|
67
67
|
expect(Array.isArray(functions)).toBe(true);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it('should fall back to super.detectLanguage for non-py extensions', () => {
|
|
71
|
-
(readFileSync as
|
|
71
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
72
72
|
const adapter = new PythonAdapter('test.ts');
|
|
73
73
|
expect(adapter.detectLanguage()).toBe('typescript');
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
it('should extract code block with indented body', () => {
|
|
77
|
-
(readFileSync as
|
|
77
|
+
(readFileSync as Mock).mockReturnValue('def outer():\n inner()\n return 0');
|
|
78
78
|
const adapter = new PythonAdapter('test.py');
|
|
79
79
|
const functions = adapter.extractFunctions();
|
|
80
80
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { SwiftAdapter } from '../swift';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -10,7 +10,7 @@ import { readFileSync } from 'fs';
|
|
|
10
10
|
|
|
11
11
|
describe('SwiftAdapter', () => {
|
|
12
12
|
it('should implement the Adapter interface', () => {
|
|
13
|
-
(readFileSync as
|
|
13
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}\nclass TestClass {}');
|
|
14
14
|
const adapter = new SwiftAdapter('test.swift');
|
|
15
15
|
|
|
16
16
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -21,24 +21,24 @@ describe('SwiftAdapter', () => {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it('should detect language as swift for .swift files', () => {
|
|
24
|
-
(readFileSync as
|
|
24
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}');
|
|
25
25
|
const adapter = new SwiftAdapter('test.swift');
|
|
26
26
|
const detected = adapter.detectLanguage();
|
|
27
27
|
expect(detected).toBe('swift');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should parse Swift file AST correctly', () => {
|
|
31
|
-
(readFileSync as
|
|
31
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}\nclass TestClass {}');
|
|
32
32
|
const adapter = new SwiftAdapter('test.swift');
|
|
33
33
|
const ast = adapter.parseAST();
|
|
34
34
|
expect(ast).toHaveProperty('content');
|
|
35
35
|
expect(ast).toHaveProperty('language');
|
|
36
36
|
expect(ast).toHaveProperty('filePath');
|
|
37
|
-
expect(ast.language).toBe('swift');
|
|
37
|
+
expect((ast as { language: unknown }).language).toBe('swift');
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('should extract functions from Swift AST', () => {
|
|
41
|
-
(readFileSync as
|
|
41
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}\nclass TestClass {}');
|
|
42
42
|
const adapter = new SwiftAdapter('test.swift');
|
|
43
43
|
const functions = adapter.extractFunctions();
|
|
44
44
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -46,7 +46,7 @@ describe('SwiftAdapter', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should extract classes from Swift AST', () => {
|
|
49
|
-
(readFileSync as
|
|
49
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}\nclass TestClass {}');
|
|
50
50
|
const adapter = new SwiftAdapter('test.swift');
|
|
51
51
|
const classes = adapter.extractClasses();
|
|
52
52
|
expect(Array.isArray(classes)).toBe(true);
|
|
@@ -54,14 +54,14 @@ describe('SwiftAdapter', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('should count Swift file physical lines', () => {
|
|
57
|
-
(readFileSync as
|
|
57
|
+
(readFileSync as Mock).mockReturnValue('func testFn() {}\nfunc testFn2() {}');
|
|
58
58
|
const adapter = new SwiftAdapter('test.swift');
|
|
59
59
|
const lineCount = adapter.countLines();
|
|
60
60
|
expect(lineCount).toBe(2);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it('should fall back to super.detectLanguage for non-swift extensions', () => {
|
|
64
|
-
(readFileSync as
|
|
64
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
65
65
|
const adapter = new SwiftAdapter('test.py');
|
|
66
66
|
expect(adapter.detectLanguage()).toBe('python');
|
|
67
67
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, type Mock } from 'vitest';;
|
|
2
2
|
import { TypeScriptAdapter } from '../typescript';
|
|
3
3
|
|
|
4
4
|
vi.mock('fs', () => ({
|
|
@@ -11,7 +11,7 @@ import { readFileSync } from 'fs';
|
|
|
11
11
|
describe('TypeScriptAdapter', () => {
|
|
12
12
|
|
|
13
13
|
it('should implement the Adapter interface', () => {
|
|
14
|
-
(readFileSync as
|
|
14
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
15
15
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
16
16
|
|
|
17
17
|
expect(adapter).toHaveProperty('detectLanguage');
|
|
@@ -22,31 +22,31 @@ describe('TypeScriptAdapter', () => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('should detect language as typescript for .ts files', () => {
|
|
25
|
-
(readFileSync as
|
|
25
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
26
26
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
27
27
|
const detected = adapter.detectLanguage();
|
|
28
28
|
expect(detected).toBe('typescript');
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('should detect language as typescript for .tsx files', () => {
|
|
32
|
-
(readFileSync as
|
|
32
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
33
33
|
const adapter = new TypeScriptAdapter('test.tsx');
|
|
34
34
|
const detected = adapter.detectLanguage();
|
|
35
35
|
expect(detected).toBe('typescript');
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it('should parse TypeScript file AST correctly', () => {
|
|
39
|
-
(readFileSync as
|
|
39
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
40
40
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
41
41
|
const ast = adapter.parseAST();
|
|
42
42
|
expect(ast).toHaveProperty('content');
|
|
43
43
|
expect(ast).toHaveProperty('language');
|
|
44
44
|
expect(ast).toHaveProperty('filePath');
|
|
45
|
-
expect(ast.language).toBe('typescript');
|
|
45
|
+
expect((ast as { language: unknown }).language).toBe('typescript');
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should extract functions from TypeScript AST', () => {
|
|
49
|
-
(readFileSync as
|
|
49
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
50
50
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
51
51
|
const functions = adapter.extractFunctions();
|
|
52
52
|
expect(Array.isArray(functions)).toBe(true);
|
|
@@ -54,7 +54,7 @@ describe('TypeScriptAdapter', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('should extract classes from TypeScript AST', () => {
|
|
57
|
-
(readFileSync as
|
|
57
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nclass TestClass {}');
|
|
58
58
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
59
59
|
const classes = adapter.extractClasses();
|
|
60
60
|
expect(Array.isArray(classes)).toBe(true);
|
|
@@ -62,14 +62,14 @@ describe('TypeScriptAdapter', () => {
|
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
it('should count TypeScript file physical lines', () => {
|
|
65
|
-
(readFileSync as
|
|
65
|
+
(readFileSync as Mock).mockReturnValue('export function testFn() {}\nexport function testFn2() {}');
|
|
66
66
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
67
67
|
const lineCount = adapter.countLines();
|
|
68
68
|
expect(lineCount).toBe(2);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it('should handle TypeScript-specific syntax correctly', () => {
|
|
72
|
-
(readFileSync as
|
|
72
|
+
(readFileSync as Mock).mockReturnValue(`
|
|
73
73
|
export async function asyncFn() {}
|
|
74
74
|
export function* generatorFn() {}
|
|
75
75
|
class MyClass {
|
|
@@ -91,7 +91,7 @@ describe('TypeScriptAdapter', () => {
|
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('should throw error when file cannot be read', () => {
|
|
94
|
-
(readFileSync as
|
|
94
|
+
(readFileSync as Mock).mockImplementation(() => {
|
|
95
95
|
throw new Error('Could not read file');
|
|
96
96
|
});
|
|
97
97
|
|
|
@@ -101,13 +101,13 @@ describe('TypeScriptAdapter', () => {
|
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
it('should fall back to super.detectLanguage for non-ts/non-tsx extensions', () => {
|
|
104
|
-
(readFileSync as
|
|
104
|
+
(readFileSync as Mock).mockReturnValue('content');
|
|
105
105
|
const adapter = new TypeScriptAdapter('test.py');
|
|
106
106
|
expect(adapter.detectLanguage()).toBe('python');
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
it('should extract re-export declarations', () => {
|
|
110
|
-
(readFileSync as
|
|
110
|
+
(readFileSync as Mock).mockReturnValue('export { Foo };\nexport { Bar };\nexport function baz() {}');
|
|
111
111
|
const adapter = new TypeScriptAdapter('test.ts');
|
|
112
112
|
const exports = adapter.extractExports();
|
|
113
113
|
const reExports = exports.filter(ex => (ex as {type: string}).type === 're-export');
|
|
@@ -7,6 +7,7 @@ const mockAdapter = {
|
|
|
7
7
|
parseAST: () => undefined,
|
|
8
8
|
extractFunctions: () => [],
|
|
9
9
|
extractClasses: () => [],
|
|
10
|
+
extractExports: () => [],
|
|
10
11
|
countLines: (_fileName: string) => 10 // Default to small file
|
|
11
12
|
};
|
|
12
13
|
|
|
@@ -22,7 +23,7 @@ describe('largeFileRule', () => {
|
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
it('should detect files exceeding 1000 lines', () => {
|
|
25
|
-
const largeFileAdapter
|
|
26
|
+
const largeFileAdapter = {
|
|
26
27
|
...mockAdapter,
|
|
27
28
|
countLines: () => 1001
|
|
28
29
|
};
|
|
@@ -39,7 +40,7 @@ describe('largeFileRule', () => {
|
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it('should handle exactly threshold lines as not violating', () => {
|
|
42
|
-
const thresholdFileAdapter
|
|
43
|
+
const thresholdFileAdapter = {
|
|
43
44
|
...mockAdapter,
|
|
44
45
|
countLines: () => 1000
|
|
45
46
|
};
|
|
@@ -61,7 +62,7 @@ describe('largeFileRule', () => {
|
|
|
61
62
|
});
|
|
62
63
|
|
|
63
64
|
it('should return empty violations when adapter throws error', () => {
|
|
64
|
-
const mockAdapterThatThrows
|
|
65
|
+
const mockAdapterThatThrows = {
|
|
65
66
|
...mockAdapter,
|
|
66
67
|
countLines: () => { throw new Error('Adapter failed'); }
|
|
67
68
|
};
|