claudecode-omc 4.7.4 → 4.8.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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +50 -0
- package/agents/test-engineer.md +74 -0
- package/bridge/cli.cjs +9335 -117
- package/dist/cli/index.js +201 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/testing/analyzers/complexity.d.ts +18 -0
- package/dist/testing/analyzers/complexity.d.ts.map +1 -0
- package/dist/testing/analyzers/complexity.js +121 -0
- package/dist/testing/analyzers/complexity.js.map +1 -0
- package/dist/testing/analyzers/coverage.d.ts +13 -0
- package/dist/testing/analyzers/coverage.d.ts.map +1 -0
- package/dist/testing/analyzers/coverage.js +99 -0
- package/dist/testing/analyzers/coverage.js.map +1 -0
- package/dist/testing/analyzers/quality-scorer.d.ts +8 -0
- package/dist/testing/analyzers/quality-scorer.d.ts.map +1 -0
- package/dist/testing/analyzers/quality-scorer.js +128 -0
- package/dist/testing/analyzers/quality-scorer.js.map +1 -0
- package/dist/testing/analyzers/types.d.ts +56 -0
- package/dist/testing/analyzers/types.d.ts.map +1 -0
- package/dist/testing/analyzers/types.js +2 -0
- package/dist/testing/analyzers/types.js.map +1 -0
- package/dist/testing/cli/agent-integration.d.ts +20 -0
- package/dist/testing/cli/agent-integration.d.ts.map +1 -0
- package/dist/testing/cli/agent-integration.js +60 -0
- package/dist/testing/cli/agent-integration.js.map +1 -0
- package/dist/testing/cli/commands.d.ts +100 -0
- package/dist/testing/cli/commands.d.ts.map +1 -0
- package/dist/testing/cli/commands.js +250 -0
- package/dist/testing/cli/commands.js.map +1 -0
- package/dist/testing/cli/ultraqa-integration.d.ts +13 -0
- package/dist/testing/cli/ultraqa-integration.d.ts.map +1 -0
- package/dist/testing/cli/ultraqa-integration.js +68 -0
- package/dist/testing/cli/ultraqa-integration.js.map +1 -0
- package/dist/testing/detectors/go.d.ts +3 -0
- package/dist/testing/detectors/go.d.ts.map +1 -0
- package/dist/testing/detectors/go.js +38 -0
- package/dist/testing/detectors/go.js.map +1 -0
- package/dist/testing/detectors/index.d.ts +8 -0
- package/dist/testing/detectors/index.d.ts.map +1 -0
- package/dist/testing/detectors/index.js +46 -0
- package/dist/testing/detectors/index.js.map +1 -0
- package/dist/testing/detectors/package-json.d.ts +3 -0
- package/dist/testing/detectors/package-json.d.ts.map +1 -0
- package/dist/testing/detectors/package-json.js +52 -0
- package/dist/testing/detectors/package-json.js.map +1 -0
- package/dist/testing/detectors/python.d.ts +3 -0
- package/dist/testing/detectors/python.d.ts.map +1 -0
- package/dist/testing/detectors/python.js +37 -0
- package/dist/testing/detectors/python.js.map +1 -0
- package/dist/testing/detectors/rust.d.ts +3 -0
- package/dist/testing/detectors/rust.d.ts.map +1 -0
- package/dist/testing/detectors/rust.js +39 -0
- package/dist/testing/detectors/rust.js.map +1 -0
- package/dist/testing/generators/contract.d.ts +14 -0
- package/dist/testing/generators/contract.d.ts.map +1 -0
- package/dist/testing/generators/contract.js +163 -0
- package/dist/testing/generators/contract.js.map +1 -0
- package/dist/testing/generators/e2e.d.ts +34 -0
- package/dist/testing/generators/e2e.d.ts.map +1 -0
- package/dist/testing/generators/e2e.js +74 -0
- package/dist/testing/generators/e2e.js.map +1 -0
- package/dist/testing/generators/go.d.ts +12 -0
- package/dist/testing/generators/go.d.ts.map +1 -0
- package/dist/testing/generators/go.js +144 -0
- package/dist/testing/generators/go.js.map +1 -0
- package/dist/testing/generators/nodejs.d.ts +12 -0
- package/dist/testing/generators/nodejs.d.ts.map +1 -0
- package/dist/testing/generators/nodejs.js +37 -0
- package/dist/testing/generators/nodejs.js.map +1 -0
- package/dist/testing/generators/python.d.ts +12 -0
- package/dist/testing/generators/python.d.ts.map +1 -0
- package/dist/testing/generators/python.js +163 -0
- package/dist/testing/generators/python.js.map +1 -0
- package/dist/testing/generators/react.d.ts +12 -0
- package/dist/testing/generators/react.d.ts.map +1 -0
- package/dist/testing/generators/react.js +31 -0
- package/dist/testing/generators/react.js.map +1 -0
- package/dist/testing/generators/rust.d.ts +11 -0
- package/dist/testing/generators/rust.d.ts.map +1 -0
- package/dist/testing/generators/rust.js +138 -0
- package/dist/testing/generators/rust.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/integrations/autopilot.d.ts +42 -0
- package/dist/testing/integrations/autopilot.d.ts.map +1 -0
- package/dist/testing/integrations/autopilot.js +55 -0
- package/dist/testing/integrations/autopilot.js.map +1 -0
- package/dist/testing/integrations/cicd.d.ts +26 -0
- package/dist/testing/integrations/cicd.d.ts.map +1 -0
- package/dist/testing/integrations/cicd.js +162 -0
- package/dist/testing/integrations/cicd.js.map +1 -0
- package/dist/testing/integrations/giskard/behavioral-tests.d.ts +4 -0
- package/dist/testing/integrations/giskard/behavioral-tests.d.ts.map +1 -0
- package/dist/testing/integrations/giskard/behavioral-tests.js +66 -0
- package/dist/testing/integrations/giskard/behavioral-tests.js.map +1 -0
- package/dist/testing/integrations/giskard/types.d.ts +35 -0
- package/dist/testing/integrations/giskard/types.d.ts.map +1 -0
- package/dist/testing/integrations/giskard/types.js +2 -0
- package/dist/testing/integrations/giskard/types.js.map +1 -0
- package/dist/testing/integrations/promptfoo/config-generator.d.ts +5 -0
- package/dist/testing/integrations/promptfoo/config-generator.d.ts.map +1 -0
- package/dist/testing/integrations/promptfoo/config-generator.js +44 -0
- package/dist/testing/integrations/promptfoo/config-generator.js.map +1 -0
- package/dist/testing/integrations/promptfoo/types.d.ts +36 -0
- package/dist/testing/integrations/promptfoo/types.d.ts.map +1 -0
- package/dist/testing/integrations/promptfoo/types.js +2 -0
- package/dist/testing/integrations/promptfoo/types.js.map +1 -0
- package/dist/testing/integrations/ralph.d.ts +65 -0
- package/dist/testing/integrations/ralph.d.ts.map +1 -0
- package/dist/testing/integrations/ralph.js +69 -0
- package/dist/testing/integrations/ralph.js.map +1 -0
- package/dist/testing/performance/cache-manager.d.ts +16 -0
- package/dist/testing/performance/cache-manager.d.ts.map +1 -0
- package/dist/testing/performance/cache-manager.js +39 -0
- package/dist/testing/performance/cache-manager.js.map +1 -0
- package/dist/testing/performance/parallel-generator.d.ts +23 -0
- package/dist/testing/performance/parallel-generator.d.ts.map +1 -0
- package/dist/testing/performance/parallel-generator.js +31 -0
- package/dist/testing/performance/parallel-generator.js.map +1 -0
- package/dist/testing/types.d.ts +23 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/docs/2026-03-06-llm-testing-system-phase1.md +0 -0
- package/docs/plans/2026-03-06-llm-testing-system-design.md +311 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase1.md +1268 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase2.md +3053 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase3.md +1830 -0
- package/docs/testing/PHASE2.md +266 -0
- package/docs/testing/PHASE3.md +601 -0
- package/docs/testing/README.md +634 -0
- package/package.json +1 -1
- package/skills/test-gen/skill.md +531 -0
- package/skills/ultraqa.md +58 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface ContractTestOptions {
|
|
2
|
+
spec?: any;
|
|
3
|
+
apiDefinition?: any;
|
|
4
|
+
framework: 'pact' | 'supertest' | 'msw';
|
|
5
|
+
consumer?: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
}
|
|
8
|
+
interface ContractTestResult {
|
|
9
|
+
testCode: string;
|
|
10
|
+
testFilePath: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function generateContractTest(options: ContractTestOptions): Promise<ContractTestResult>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/testing/generators/contract.ts"],"names":[],"mappings":"AAAA,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkBpG"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
export async function generateContractTest(options) {
|
|
2
|
+
const { spec, apiDefinition, framework, consumer, provider } = options;
|
|
3
|
+
let testCode = '';
|
|
4
|
+
let testFilePath = '';
|
|
5
|
+
if (framework === 'pact' && spec) {
|
|
6
|
+
testCode = generatePactTest(spec, consumer || 'consumer', provider || 'provider');
|
|
7
|
+
testFilePath = `tests/contract/${consumer}-${provider}.pact.test.ts`;
|
|
8
|
+
}
|
|
9
|
+
else if (framework === 'supertest' && apiDefinition) {
|
|
10
|
+
testCode = generateSupertestContract(apiDefinition);
|
|
11
|
+
testFilePath = `tests/contract/api.contract.test.ts`;
|
|
12
|
+
}
|
|
13
|
+
else if (framework === 'msw' && spec) {
|
|
14
|
+
testCode = generateMSWHandlers(spec);
|
|
15
|
+
testFilePath = `tests/mocks/handlers.ts`;
|
|
16
|
+
}
|
|
17
|
+
return { testCode, testFilePath };
|
|
18
|
+
}
|
|
19
|
+
function generatePactTest(spec, consumer, provider) {
|
|
20
|
+
const paths = spec.paths || {};
|
|
21
|
+
const interactions = [];
|
|
22
|
+
for (const [path, methods] of Object.entries(paths)) {
|
|
23
|
+
for (const [method, details] of Object.entries(methods)) {
|
|
24
|
+
const interaction = generatePactInteraction(path, method.toUpperCase(), details);
|
|
25
|
+
interactions.push(interaction);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return `import { Pact } from '@pact-foundation/pact';
|
|
29
|
+
import { like, eachLike } from '@pact-foundation/pact/dsl/matchers';
|
|
30
|
+
|
|
31
|
+
describe('${consumer} <-> ${provider} Contract', () => {
|
|
32
|
+
const provider = new Pact({
|
|
33
|
+
consumer: '${consumer}',
|
|
34
|
+
provider: '${provider}',
|
|
35
|
+
port: 1234,
|
|
36
|
+
log: './logs/pact.log',
|
|
37
|
+
dir: './pacts',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
beforeAll(() => provider.setup());
|
|
41
|
+
afterEach(() => provider.verify());
|
|
42
|
+
afterAll(() => provider.finalize());
|
|
43
|
+
|
|
44
|
+
${interactions.join('\n\n')}
|
|
45
|
+
});
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
function generatePactInteraction(path, method, details) {
|
|
49
|
+
const response = details.responses?.['200'] || details.responses?.['201'];
|
|
50
|
+
const responseSchema = response?.content?.['application/json']?.schema;
|
|
51
|
+
const responseBody = responseSchema ? generateMatcherFromSchema(responseSchema) : '{}';
|
|
52
|
+
return ` it('${method} ${path}', async () => {
|
|
53
|
+
await provider.addInteraction({
|
|
54
|
+
state: 'resource exists',
|
|
55
|
+
uponReceiving: '${method} request to ${path}',
|
|
56
|
+
withRequest: {
|
|
57
|
+
method: '${method}',
|
|
58
|
+
path: '${path}',
|
|
59
|
+
},
|
|
60
|
+
willRespondWith: {
|
|
61
|
+
status: 200,
|
|
62
|
+
headers: { 'Content-Type': 'application/json' },
|
|
63
|
+
body: ${responseBody},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Make actual request and verify
|
|
68
|
+
const response = await fetch(\`http://localhost:1234${path}\`);
|
|
69
|
+
expect(response.status).toBe(200);
|
|
70
|
+
});`;
|
|
71
|
+
}
|
|
72
|
+
function generateMatcherFromSchema(schema) {
|
|
73
|
+
if (schema.type === 'object') {
|
|
74
|
+
const properties = schema.properties || {};
|
|
75
|
+
const matchers = [];
|
|
76
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
77
|
+
if (prop.type === 'string') {
|
|
78
|
+
matchers.push(`${key}: like('example')`);
|
|
79
|
+
}
|
|
80
|
+
else if (prop.type === 'number') {
|
|
81
|
+
matchers.push(`${key}: like(123)`);
|
|
82
|
+
}
|
|
83
|
+
else if (prop.type === 'boolean') {
|
|
84
|
+
matchers.push(`${key}: like(true)`);
|
|
85
|
+
}
|
|
86
|
+
else if (prop.type === 'array') {
|
|
87
|
+
matchers.push(`${key}: eachLike({ id: like('1') })`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return `{ ${matchers.join(', ')} }`;
|
|
91
|
+
}
|
|
92
|
+
return '{}';
|
|
93
|
+
}
|
|
94
|
+
function generateSupertestContract(apiDefinition) {
|
|
95
|
+
const { endpoint, method, requestBody, responseBody } = apiDefinition;
|
|
96
|
+
const requestExample = generateExampleFromSchema(requestBody);
|
|
97
|
+
const responseExample = generateExampleFromSchema(responseBody);
|
|
98
|
+
return `import request from 'supertest';
|
|
99
|
+
import app from '../src/app';
|
|
100
|
+
|
|
101
|
+
describe('API Contract Tests', () => {
|
|
102
|
+
it('${method} ${endpoint} should match contract', async () => {
|
|
103
|
+
const response = await request(app)
|
|
104
|
+
.${method.toLowerCase()}('${endpoint}')
|
|
105
|
+
.send(${JSON.stringify(requestExample, null, 2)})
|
|
106
|
+
.expect(200)
|
|
107
|
+
.expect('Content-Type', /json/);
|
|
108
|
+
|
|
109
|
+
// Verify response structure
|
|
110
|
+
expect(response.body).toMatchObject(${JSON.stringify(responseExample, null, 2)});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
function generateMSWHandlers(spec) {
|
|
116
|
+
const paths = spec.paths || {};
|
|
117
|
+
const handlers = [];
|
|
118
|
+
for (const [path, methods] of Object.entries(paths)) {
|
|
119
|
+
for (const [method, details] of Object.entries(methods)) {
|
|
120
|
+
const handler = generateMSWHandler(path, method, details);
|
|
121
|
+
handlers.push(handler);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return `import { rest } from 'msw';
|
|
125
|
+
|
|
126
|
+
export const handlers = [
|
|
127
|
+
${handlers.join(',\n\n')}
|
|
128
|
+
];
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
function generateMSWHandler(path, method, details) {
|
|
132
|
+
const response = details.responses?.['200'] || details.responses?.['201'];
|
|
133
|
+
const responseSchema = response?.content?.['application/json']?.schema;
|
|
134
|
+
const responseExample = responseSchema ? generateExampleFromSchema(responseSchema.properties || {}) : {};
|
|
135
|
+
return ` rest.${method.toLowerCase()}('${path}', (req, res, ctx) => {
|
|
136
|
+
return res(
|
|
137
|
+
ctx.status(200),
|
|
138
|
+
ctx.json(${JSON.stringify(responseExample, null, 2)})
|
|
139
|
+
);
|
|
140
|
+
})`;
|
|
141
|
+
}
|
|
142
|
+
function generateExampleFromSchema(schema) {
|
|
143
|
+
if (typeof schema === 'string') {
|
|
144
|
+
return schema === 'string' ? 'example' : schema === 'number' ? 123 : schema === 'boolean' ? true : [];
|
|
145
|
+
}
|
|
146
|
+
const example = {};
|
|
147
|
+
for (const [key, type] of Object.entries(schema)) {
|
|
148
|
+
if (type === 'string') {
|
|
149
|
+
example[key] = 'example';
|
|
150
|
+
}
|
|
151
|
+
else if (type === 'number') {
|
|
152
|
+
example[key] = 123;
|
|
153
|
+
}
|
|
154
|
+
else if (type === 'boolean') {
|
|
155
|
+
example[key] = true;
|
|
156
|
+
}
|
|
157
|
+
else if (type === 'array') {
|
|
158
|
+
example[key] = [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return example;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/testing/generators/contract.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAA4B;IACrE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEvE,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,YAAY,GAAG,EAAE,CAAC;IAEtB,IAAI,SAAS,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC;QACjC,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,QAAQ,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,CAAC,CAAC;QAClF,YAAY,GAAG,kBAAkB,QAAQ,IAAI,QAAQ,eAAe,CAAC;IACvE,CAAC;SAAM,IAAI,SAAS,KAAK,WAAW,IAAI,aAAa,EAAE,CAAC;QACtD,QAAQ,GAAG,yBAAyB,CAAC,aAAa,CAAC,CAAC;QACpD,YAAY,GAAG,qCAAqC,CAAC;IACvD,CAAC;SAAM,IAAI,SAAS,KAAK,KAAK,IAAI,IAAI,EAAE,CAAC;QACvC,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACrC,YAAY,GAAG,yBAAyB,CAAC;IAC3C,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAS,EAAE,QAAgB,EAAE,QAAgB;IACrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAc,CAAC,EAAE,CAAC;YAC/D,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;YACjF,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO;;;YAGG,QAAQ,QAAQ,QAAQ;;iBAEnB,QAAQ;iBACR,QAAQ;;;;;;;;;;EAUvB,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;;CAE1B,CAAC;AACF,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY,EAAE,MAAc,EAAE,OAAY;IACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,MAAM,cAAc,GAAG,QAAQ,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAEvE,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvF,OAAO,SAAS,MAAM,IAAI,IAAI;;;wBAGR,MAAM,eAAe,IAAI;;mBAE9B,MAAM;iBACR,IAAI;;;;;gBAKL,YAAY;;;;;0DAK8B,IAAI;;MAExD,CAAC;AACP,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAW;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAiC,CAAC,EAAE,CAAC;YAC5E,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAC;YAC3C,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC;YACtC,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,+BAA+B,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,OAAO,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,aAAkB;IACnD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC;IAEtE,MAAM,cAAc,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAC;IAEhE,OAAO;;;;QAID,MAAM,IAAI,QAAQ;;SAEjB,MAAM,CAAC,WAAW,EAAE,KAAK,QAAQ;cAC5B,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;0CAKX,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;;;CAGjF,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAS;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAc,CAAC,EAAE,CAAC;YAC/D,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAC1D,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO;;;EAGP,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;;CAEvB,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,MAAc,EAAE,OAAY;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,MAAM,cAAc,GAAG,QAAQ,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACvE,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,cAAc,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEzG,OAAO,UAAU,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI;;;iBAG/B,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;;KAEpD,CAAC;AACN,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAW;IAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACxG,CAAC;IAED,MAAM,OAAO,GAAQ,EAAE,CAAC;IAExB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;QAC3B,CAAC;aAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QACrB,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Test Generator for Playwright
|
|
3
|
+
* Generates Playwright test files from user flow descriptions
|
|
4
|
+
*/
|
|
5
|
+
export interface E2EStep {
|
|
6
|
+
action: 'goto' | 'click' | 'fill' | 'expect' | 'waitFor' | 'screenshot';
|
|
7
|
+
target: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
assertion?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface GeneratePlaywrightTestOptions {
|
|
12
|
+
steps: E2EStep[];
|
|
13
|
+
testName: string;
|
|
14
|
+
testSuite?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GenerateFromUserFlowOptions {
|
|
17
|
+
flowDescription: string;
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
testName: string;
|
|
20
|
+
}
|
|
21
|
+
export interface UserFlowResult {
|
|
22
|
+
testCode: string;
|
|
23
|
+
steps: E2EStep[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate Playwright test code from structured steps
|
|
27
|
+
*/
|
|
28
|
+
export declare function generatePlaywrightTest(options: GeneratePlaywrightTestOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Parse user flow description and generate Playwright test
|
|
31
|
+
* This is a simplified implementation - in production, use LLM for better parsing
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateFromUserFlow(options: GenerateFromUserFlowOptions): Promise<UserFlowResult>;
|
|
34
|
+
//# sourceMappingURL=e2e.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.d.ts","sourceRoot":"","sources":["../../../src/testing/generators/e2e.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAwBD;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,cAAc,CAAC,CA2BzB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Test Generator for Playwright
|
|
3
|
+
* Generates Playwright test files from user flow descriptions
|
|
4
|
+
*/
|
|
5
|
+
const PLAYWRIGHT_TEST_TEMPLATE = `import { test, expect } from '@playwright/test';
|
|
6
|
+
|
|
7
|
+
test.describe('{{testSuite}}', () => {
|
|
8
|
+
test('{{testName}}', async ({ page }) => {
|
|
9
|
+
{{testSteps}}
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
`;
|
|
13
|
+
const STEP_TEMPLATES = {
|
|
14
|
+
goto: "await page.goto('{{target}}');",
|
|
15
|
+
click: "await page.click('{{target}}');",
|
|
16
|
+
fill: "await page.fill('{{target}}', '{{value}}');",
|
|
17
|
+
expect: "await expect(page.locator('{{target}}')).{{assertion}}();",
|
|
18
|
+
waitFor: "await page.waitForSelector('{{target}}');",
|
|
19
|
+
screenshot: "await page.screenshot({ path: '{{target}}' });",
|
|
20
|
+
};
|
|
21
|
+
function renderTemplate(template, vars) {
|
|
22
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] || '');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate Playwright test code from structured steps
|
|
26
|
+
*/
|
|
27
|
+
export async function generatePlaywrightTest(options) {
|
|
28
|
+
const { steps, testName, testSuite = 'E2E Tests' } = options;
|
|
29
|
+
const testSteps = steps
|
|
30
|
+
.map((step) => {
|
|
31
|
+
const template = STEP_TEMPLATES[step.action];
|
|
32
|
+
return renderTemplate(template, {
|
|
33
|
+
target: step.target,
|
|
34
|
+
value: step.value || '',
|
|
35
|
+
assertion: step.assertion || '',
|
|
36
|
+
});
|
|
37
|
+
})
|
|
38
|
+
.join('\n ');
|
|
39
|
+
return renderTemplate(PLAYWRIGHT_TEST_TEMPLATE, {
|
|
40
|
+
testSuite,
|
|
41
|
+
testName,
|
|
42
|
+
testSteps,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse user flow description and generate Playwright test
|
|
47
|
+
* This is a simplified implementation - in production, use LLM for better parsing
|
|
48
|
+
*/
|
|
49
|
+
export async function generateFromUserFlow(options) {
|
|
50
|
+
const { flowDescription, baseUrl, testName } = options;
|
|
51
|
+
// Parse flow description into high-level steps
|
|
52
|
+
const steps = [];
|
|
53
|
+
const lowerFlow = flowDescription.toLowerCase();
|
|
54
|
+
// Split by common delimiters to identify distinct actions
|
|
55
|
+
const actions = flowDescription.split(/,\s*/).map(s => s.trim().toLowerCase());
|
|
56
|
+
for (const action of actions) {
|
|
57
|
+
if (action.includes('logs in') || action.includes('login')) {
|
|
58
|
+
// Simplified: represent login as a single goto action
|
|
59
|
+
steps.push({ action: 'goto', target: `${baseUrl}/login` });
|
|
60
|
+
}
|
|
61
|
+
else if (action.includes('navigates to') || action.includes('dashboard')) {
|
|
62
|
+
steps.push({ action: 'goto', target: `${baseUrl}/dashboard` });
|
|
63
|
+
}
|
|
64
|
+
else if (action.includes('clicks on') || action.includes('settings')) {
|
|
65
|
+
steps.push({ action: 'click', target: 'a[href="/settings"]' });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const testCode = await generatePlaywrightTest({ steps, testName });
|
|
69
|
+
return {
|
|
70
|
+
testCode,
|
|
71
|
+
steps,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=e2e.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["../../../src/testing/generators/e2e.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface GoTestOptions {
|
|
2
|
+
filePath: string;
|
|
3
|
+
code: string;
|
|
4
|
+
packageName: string;
|
|
5
|
+
}
|
|
6
|
+
interface GoTestResult {
|
|
7
|
+
testFilePath: string;
|
|
8
|
+
testCode: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateGoTest(options: GoTestOptions): Promise<GoTestResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=go.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/testing/generators/go.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAalF"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export async function generateGoTest(options) {
|
|
2
|
+
const { filePath, code, packageName } = options;
|
|
3
|
+
// Generate test file path: .go → _test.go
|
|
4
|
+
const testFilePath = filePath.replace(/\.go$/, '_test.go');
|
|
5
|
+
// Extract exported functions (capitalized names)
|
|
6
|
+
const functions = extractGoFunctions(code);
|
|
7
|
+
// Generate test code
|
|
8
|
+
const testCode = generateTestCode(packageName, functions);
|
|
9
|
+
return { testFilePath, testCode };
|
|
10
|
+
}
|
|
11
|
+
function extractGoFunctions(code) {
|
|
12
|
+
const functions = [];
|
|
13
|
+
// Match exported functions (capitalized first letter)
|
|
14
|
+
const funcRegex = /func\s+([A-Z]\w*)\s*\((.*?)\)\s*([\w.*[\]]*)?/g;
|
|
15
|
+
let match;
|
|
16
|
+
while ((match = funcRegex.exec(code)) !== null) {
|
|
17
|
+
const name = match[1];
|
|
18
|
+
const paramsStr = match[2];
|
|
19
|
+
const returnType = (match[3] || '').trim();
|
|
20
|
+
const params = parseGoParams(paramsStr);
|
|
21
|
+
functions.push({ name, params, returnType });
|
|
22
|
+
}
|
|
23
|
+
return functions;
|
|
24
|
+
}
|
|
25
|
+
function parseGoParams(paramsStr) {
|
|
26
|
+
if (!paramsStr.trim())
|
|
27
|
+
return [];
|
|
28
|
+
const params = [];
|
|
29
|
+
const parts = paramsStr.split(',').map(p => p.trim());
|
|
30
|
+
// Go allows grouped params: (a, b int) means both are int
|
|
31
|
+
// Process right-to-left to resolve types
|
|
32
|
+
let lastType = '';
|
|
33
|
+
const parsed = [];
|
|
34
|
+
for (const part of parts) {
|
|
35
|
+
const tokens = part.split(/\s+/);
|
|
36
|
+
if (tokens.length >= 2) {
|
|
37
|
+
// Has explicit type: "a int" or "input string"
|
|
38
|
+
const type = tokens[tokens.length - 1];
|
|
39
|
+
const names = tokens.slice(0, -1);
|
|
40
|
+
parsed.push({ names, type });
|
|
41
|
+
lastType = type;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// No type, will inherit from next param with type
|
|
45
|
+
parsed.push({ names: [tokens[0]], type: '' });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Resolve types right-to-left for grouped params
|
|
49
|
+
for (let i = parsed.length - 1; i >= 0; i--) {
|
|
50
|
+
if (parsed[i].type) {
|
|
51
|
+
lastType = parsed[i].type;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
parsed[i].type = lastType;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const p of parsed) {
|
|
58
|
+
for (const name of p.names) {
|
|
59
|
+
params.push({ name, type: p.type });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return params;
|
|
63
|
+
}
|
|
64
|
+
function generateTestCode(packageName, functions) {
|
|
65
|
+
let code = `package ${packageName}\n\nimport "testing"\n\n`;
|
|
66
|
+
for (const func of functions) {
|
|
67
|
+
code += generateTableDrivenTest(func);
|
|
68
|
+
}
|
|
69
|
+
return code;
|
|
70
|
+
}
|
|
71
|
+
function generateTableDrivenTest(func) {
|
|
72
|
+
const testName = `Test${func.name}`;
|
|
73
|
+
// Build struct fields from params + expected result
|
|
74
|
+
const structFields = func.params
|
|
75
|
+
.map(p => `\t\t${p.name} ${p.type}`)
|
|
76
|
+
.join('\n');
|
|
77
|
+
const expectedField = func.returnType
|
|
78
|
+
? `\t\texpected ${func.returnType}`
|
|
79
|
+
: '';
|
|
80
|
+
const allFields = [structFields, expectedField].filter(Boolean).join('\n');
|
|
81
|
+
// Build test case args
|
|
82
|
+
const argsList = func.params.map(p => `tt.${p.name}`).join(', ');
|
|
83
|
+
// Generate sample test case
|
|
84
|
+
const sampleArgs = func.params.map(p => getZeroValue(p.type)).join(', ');
|
|
85
|
+
const sampleExpected = func.returnType ? getZeroValue(func.returnType) : '';
|
|
86
|
+
let testCase = func.params.map(p => `${getZeroValue(p.type)}`).join(', ');
|
|
87
|
+
if (func.returnType) {
|
|
88
|
+
testCase += `, ${sampleExpected}`;
|
|
89
|
+
}
|
|
90
|
+
let code = `func ${testName}(t *testing.T) {\n`;
|
|
91
|
+
code += `\ttests := []struct {\n`;
|
|
92
|
+
code += `\t\tname string\n`;
|
|
93
|
+
code += `${allFields}\n`;
|
|
94
|
+
code += `\t}{\n`;
|
|
95
|
+
code += `\t\t{\n`;
|
|
96
|
+
code += `\t\t\tname: "basic case",\n`;
|
|
97
|
+
for (const p of func.params) {
|
|
98
|
+
code += `\t\t\t${p.name}: ${getZeroValue(p.type)},\n`;
|
|
99
|
+
}
|
|
100
|
+
if (func.returnType) {
|
|
101
|
+
code += `\t\t\texpected: ${getZeroValue(func.returnType)},\n`;
|
|
102
|
+
}
|
|
103
|
+
code += `\t\t},\n`;
|
|
104
|
+
code += `\t}\n\n`;
|
|
105
|
+
code += `\tfor _, tt := range tests {\n`;
|
|
106
|
+
code += `\t\tt.Run(tt.name, func(t *testing.T) {\n`;
|
|
107
|
+
if (func.returnType) {
|
|
108
|
+
code += `\t\t\tgot := ${func.name}(${argsList})\n`;
|
|
109
|
+
code += `\t\t\tif got != tt.expected {\n`;
|
|
110
|
+
code += `\t\t\t\tt.Errorf("${func.name}() = %v, want %v", got, tt.expected)\n`;
|
|
111
|
+
code += `\t\t\t}\n`;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
code += `\t\t\t${func.name}(${argsList})\n`;
|
|
115
|
+
}
|
|
116
|
+
code += `\t\t})\n`;
|
|
117
|
+
code += `\t}\n`;
|
|
118
|
+
code += `}\n\n`;
|
|
119
|
+
return code;
|
|
120
|
+
}
|
|
121
|
+
function getZeroValue(goType) {
|
|
122
|
+
switch (goType) {
|
|
123
|
+
case 'int':
|
|
124
|
+
case 'int8':
|
|
125
|
+
case 'int16':
|
|
126
|
+
case 'int32':
|
|
127
|
+
case 'int64':
|
|
128
|
+
case 'uint':
|
|
129
|
+
case 'uint8':
|
|
130
|
+
case 'uint16':
|
|
131
|
+
case 'uint32':
|
|
132
|
+
case 'uint64':
|
|
133
|
+
case 'float32':
|
|
134
|
+
case 'float64':
|
|
135
|
+
return '0';
|
|
136
|
+
case 'string':
|
|
137
|
+
return '""';
|
|
138
|
+
case 'bool':
|
|
139
|
+
return 'false';
|
|
140
|
+
default:
|
|
141
|
+
return 'nil';
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=go.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../../src/testing/generators/go.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface NodeJsTestOptions {
|
|
2
|
+
filePath: string;
|
|
3
|
+
code: string;
|
|
4
|
+
testFramework: 'vitest' | 'jest';
|
|
5
|
+
}
|
|
6
|
+
interface NodeJsTestResult {
|
|
7
|
+
testFilePath: string;
|
|
8
|
+
testCode: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateNodeJsTest(options: NodeJsTestOptions): Promise<NodeJsTestResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=nodejs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs.d.ts","sourceRoot":"","sources":["../../../src/testing/generators/nodejs.ts"],"names":[],"mappings":"AAAA,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,QAAQ,GAAG,MAAM,CAAC;CAClC;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2C9F"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export async function generateNodeJsTest(options) {
|
|
2
|
+
const { filePath, code, testFramework } = options;
|
|
3
|
+
// Extract function names from code
|
|
4
|
+
const functionMatches = code.matchAll(/export\s+(?:async\s+)?function\s+(\w+)/g);
|
|
5
|
+
const functions = Array.from(functionMatches).map(match => match[1]);
|
|
6
|
+
// Generate test file path
|
|
7
|
+
const testFilePath = filePath.replace(/\.ts$/, '.test.ts');
|
|
8
|
+
// Extract file name for import
|
|
9
|
+
const fileName = filePath.split('/').pop()?.replace(/\.ts$/, '') || 'module';
|
|
10
|
+
// Generate test code for each function
|
|
11
|
+
const testCases = functions.map(funcName => {
|
|
12
|
+
// Simple heuristic: if function name suggests math operation, generate math test
|
|
13
|
+
if (funcName === 'add') {
|
|
14
|
+
return ` it('adds two numbers', () => {
|
|
15
|
+
expect(add(2, 3)).toBe(5);
|
|
16
|
+
expect(add(-1, 1)).toBe(0);
|
|
17
|
+
expect(add(0, 0)).toBe(0);
|
|
18
|
+
});`;
|
|
19
|
+
}
|
|
20
|
+
// Generic test template
|
|
21
|
+
return ` it('${funcName} works correctly', () => {
|
|
22
|
+
// TODO: Add specific test cases for ${funcName}
|
|
23
|
+
expect(${funcName}).toBeDefined();
|
|
24
|
+
});`;
|
|
25
|
+
}).join('\n\n');
|
|
26
|
+
// Use function name for describe block if single function, otherwise use file name
|
|
27
|
+
const describeName = functions.length === 1 ? functions[0] : fileName;
|
|
28
|
+
const testCode = `import { describe, it, expect } from '${testFramework}';
|
|
29
|
+
import { ${functions.join(', ')} } from './${fileName}';
|
|
30
|
+
|
|
31
|
+
describe('${describeName}', () => {
|
|
32
|
+
${testCases}
|
|
33
|
+
});
|
|
34
|
+
`;
|
|
35
|
+
return { testFilePath, testCode };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=nodejs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs.js","sourceRoot":"","sources":["../../../src/testing/generators/nodejs.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA0B;IACjE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAElD,mCAAmC;IACnC,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAAC;IACjF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,0BAA0B;IAC1B,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3D,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;IAE7E,uCAAuC;IACvC,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACzC,iFAAiF;QACjF,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,OAAO;;;;MAIP,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,OAAO,SAAS,QAAQ;2CACe,QAAQ;aACtC,QAAQ;MACf,CAAC;IACL,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,mFAAmF;IACnF,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtE,MAAM,QAAQ,GAAG,yCAAyC,aAAa;WAC9D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,QAAQ;;YAEzC,YAAY;EACtB,SAAS;;CAEV,CAAC;IAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface PythonTestOptions {
|
|
2
|
+
filePath: string;
|
|
3
|
+
code: string;
|
|
4
|
+
testFramework: 'pytest' | 'unittest';
|
|
5
|
+
}
|
|
6
|
+
interface PythonTestResult {
|
|
7
|
+
testFilePath: string;
|
|
8
|
+
testCode: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function generatePythonTest(options: PythonTestOptions): Promise<PythonTestResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=python.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/testing/generators/python.ts"],"names":[],"mappings":"AAAA,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,QAAQ,GAAG,UAAU,CAAC;CACtC;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsB9F"}
|