@nahisaho/musubix-core 1.0.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/bin/musubix.js +18 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +27 -0
- package/dist/__tests__/index.test.js.map +1 -0
- package/dist/auth/auth-manager.d.ts +320 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.js +580 -0
- package/dist/auth/auth-manager.js.map +1 -0
- package/dist/cli/base.d.ts +58 -0
- package/dist/cli/base.d.ts.map +1 -0
- package/dist/cli/base.js +93 -0
- package/dist/cli/base.js.map +1 -0
- package/dist/cli/commands/help.d.ts +17 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +228 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/index.d.ts +14 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +25 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +38 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +258 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/codegen/coding-standards.d.ts +250 -0
- package/dist/codegen/coding-standards.d.ts.map +1 -0
- package/dist/codegen/coding-standards.js +976 -0
- package/dist/codegen/coding-standards.js.map +1 -0
- package/dist/codegen/coverage-reporter.d.ts +264 -0
- package/dist/codegen/coverage-reporter.d.ts.map +1 -0
- package/dist/codegen/coverage-reporter.js +697 -0
- package/dist/codegen/coverage-reporter.js.map +1 -0
- package/dist/codegen/dependency-analyzer.d.ts +271 -0
- package/dist/codegen/dependency-analyzer.d.ts.map +1 -0
- package/dist/codegen/dependency-analyzer.js +661 -0
- package/dist/codegen/dependency-analyzer.js.map +1 -0
- package/dist/codegen/generator.d.ts +275 -0
- package/dist/codegen/generator.d.ts.map +1 -0
- package/dist/codegen/generator.js +781 -0
- package/dist/codegen/generator.js.map +1 -0
- package/dist/codegen/index.d.ts +18 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +27 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/integration-test-generator.d.ts +312 -0
- package/dist/codegen/integration-test-generator.d.ts.map +1 -0
- package/dist/codegen/integration-test-generator.js +765 -0
- package/dist/codegen/integration-test-generator.js.map +1 -0
- package/dist/codegen/pattern-conformance.d.ts +309 -0
- package/dist/codegen/pattern-conformance.d.ts.map +1 -0
- package/dist/codegen/pattern-conformance.js +590 -0
- package/dist/codegen/pattern-conformance.js.map +1 -0
- package/dist/codegen/quality-metrics.d.ts +235 -0
- package/dist/codegen/quality-metrics.d.ts.map +1 -0
- package/dist/codegen/quality-metrics.js +439 -0
- package/dist/codegen/quality-metrics.js.map +1 -0
- package/dist/codegen/security-scanner.d.ts +179 -0
- package/dist/codegen/security-scanner.d.ts.map +1 -0
- package/dist/codegen/security-scanner.js +495 -0
- package/dist/codegen/security-scanner.js.map +1 -0
- package/dist/codegen/static-analyzer.d.ts +188 -0
- package/dist/codegen/static-analyzer.d.ts.map +1 -0
- package/dist/codegen/static-analyzer.js +490 -0
- package/dist/codegen/static-analyzer.js.map +1 -0
- package/dist/codegen/unit-test-generator.d.ts +289 -0
- package/dist/codegen/unit-test-generator.d.ts.map +1 -0
- package/dist/codegen/unit-test-generator.js +634 -0
- package/dist/codegen/unit-test-generator.js.map +1 -0
- package/dist/design/adr-generator.d.ts +227 -0
- package/dist/design/adr-generator.d.ts.map +1 -0
- package/dist/design/adr-generator.js +423 -0
- package/dist/design/adr-generator.js.map +1 -0
- package/dist/design/c4-generator.d.ts +267 -0
- package/dist/design/c4-generator.d.ts.map +1 -0
- package/dist/design/c4-generator.js +453 -0
- package/dist/design/c4-generator.js.map +1 -0
- package/dist/design/framework-optimizer.d.ts +190 -0
- package/dist/design/framework-optimizer.d.ts.map +1 -0
- package/dist/design/framework-optimizer.js +589 -0
- package/dist/design/framework-optimizer.js.map +1 -0
- package/dist/design/index.d.ts +12 -0
- package/dist/design/index.d.ts.map +1 -0
- package/dist/design/index.js +13 -0
- package/dist/design/index.js.map +1 -0
- package/dist/design/pattern-detector.d.ts +270 -0
- package/dist/design/pattern-detector.d.ts.map +1 -0
- package/dist/design/pattern-detector.js +621 -0
- package/dist/design/pattern-detector.js.map +1 -0
- package/dist/design/solid-validator.d.ts +188 -0
- package/dist/design/solid-validator.d.ts.map +1 -0
- package/dist/design/solid-validator.js +579 -0
- package/dist/design/solid-validator.js.map +1 -0
- package/dist/error/data-persistence.d.ts +311 -0
- package/dist/error/data-persistence.d.ts.map +1 -0
- package/dist/error/data-persistence.js +586 -0
- package/dist/error/data-persistence.js.map +1 -0
- package/dist/error/graceful-degradation.d.ts +309 -0
- package/dist/error/graceful-degradation.d.ts.map +1 -0
- package/dist/error/graceful-degradation.js +510 -0
- package/dist/error/graceful-degradation.js.map +1 -0
- package/dist/error/index.d.ts +11 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +19 -0
- package/dist/error/index.js.map +1 -0
- package/dist/explanation/explanation-generator.d.ts +228 -0
- package/dist/explanation/explanation-generator.d.ts.map +1 -0
- package/dist/explanation/explanation-generator.js +662 -0
- package/dist/explanation/explanation-generator.js.map +1 -0
- package/dist/explanation/index.d.ts +11 -0
- package/dist/explanation/index.d.ts.map +1 -0
- package/dist/explanation/index.js +19 -0
- package/dist/explanation/index.js.map +1 -0
- package/dist/explanation/reasoning-chain.d.ts +314 -0
- package/dist/explanation/reasoning-chain.d.ts.map +1 -0
- package/dist/explanation/reasoning-chain.js +414 -0
- package/dist/explanation/reasoning-chain.js.map +1 -0
- package/dist/explanation/visual-explanation.d.ts +315 -0
- package/dist/explanation/visual-explanation.d.ts.map +1 -0
- package/dist/explanation/visual-explanation.js +667 -0
- package/dist/explanation/visual-explanation.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/requirements/decomposer.d.ts +235 -0
- package/dist/requirements/decomposer.d.ts.map +1 -0
- package/dist/requirements/decomposer.js +587 -0
- package/dist/requirements/decomposer.js.map +1 -0
- package/dist/requirements/related-finder.d.ts +261 -0
- package/dist/requirements/related-finder.d.ts.map +1 -0
- package/dist/requirements/related-finder.js +629 -0
- package/dist/requirements/related-finder.js.map +1 -0
- package/dist/traceability/impact.d.ts +196 -0
- package/dist/traceability/impact.d.ts.map +1 -0
- package/dist/traceability/impact.js +438 -0
- package/dist/traceability/impact.js.map +1 -0
- package/dist/traceability/index.d.ts +9 -0
- package/dist/traceability/index.d.ts.map +1 -0
- package/dist/traceability/index.js +10 -0
- package/dist/traceability/index.js.map +1 -0
- package/dist/traceability/manager.d.ts +266 -0
- package/dist/traceability/manager.d.ts.map +1 -0
- package/dist/traceability/manager.js +412 -0
- package/dist/traceability/manager.js.map +1 -0
- package/dist/types/common.d.ts +294 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +15 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/ears.d.ts +158 -0
- package/dist/types/ears.d.ts.map +1 -0
- package/dist/types/ears.js +33 -0
- package/dist/types/ears.js.map +1 -0
- package/dist/types/errors.d.ts +176 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +55 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/data-protector.d.ts +122 -0
- package/dist/utils/data-protector.d.ts.map +1 -0
- package/dist/utils/data-protector.js +275 -0
- package/dist/utils/data-protector.js.map +1 -0
- package/dist/utils/error-handler.d.ts +101 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +324 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/i18n-manager.d.ts +259 -0
- package/dist/utils/i18n-manager.d.ts.map +1 -0
- package/dist/utils/i18n-manager.js +554 -0
- package/dist/utils/i18n-manager.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +120 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +237 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/performance-profiler.d.ts +251 -0
- package/dist/utils/performance-profiler.d.ts.map +1 -0
- package/dist/utils/performance-profiler.js +458 -0
- package/dist/utils/performance-profiler.js.map +1 -0
- package/dist/utils/scalability-optimizer.d.ts +294 -0
- package/dist/utils/scalability-optimizer.d.ts.map +1 -0
- package/dist/utils/scalability-optimizer.js +606 -0
- package/dist/utils/scalability-optimizer.js.map +1 -0
- package/dist/utils/structured-logger.d.ts +294 -0
- package/dist/utils/structured-logger.d.ts.map +1 -0
- package/dist/utils/structured-logger.js +630 -0
- package/dist/utils/structured-logger.js.map +1 -0
- package/dist/utils/version-compatibility.d.ts +217 -0
- package/dist/utils/version-compatibility.d.ts.map +1 -0
- package/dist/utils/version-compatibility.js +443 -0
- package/dist/utils/version-compatibility.js.map +1 -0
- package/dist/validators/ears-validator.d.ts +182 -0
- package/dist/validators/ears-validator.d.ts.map +1 -0
- package/dist/validators/ears-validator.js +357 -0
- package/dist/validators/ears-validator.js.map +1 -0
- package/dist/validators/index.d.ts +8 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/index.js +9 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,765 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates integration tests for component interactions
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
* @module codegen/integration-test-generator
|
|
8
|
+
*
|
|
9
|
+
* @see REQ-TST-002 - Integration Test Generation
|
|
10
|
+
* @see Article VII - Quality Assurance Standards
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Default configuration
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_INTEGRATION_CONFIG = {
|
|
16
|
+
framework: 'jest',
|
|
17
|
+
assertionStyle: 'expect',
|
|
18
|
+
includeFixtures: true,
|
|
19
|
+
generateCleanup: true,
|
|
20
|
+
defaultTimeout: 30000,
|
|
21
|
+
testFileSuffix: '.integration.test',
|
|
22
|
+
useContainers: false,
|
|
23
|
+
apiBaseUrl: 'http://localhost:3000',
|
|
24
|
+
dbConnectionPattern: 'postgresql://localhost:5432/test',
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Integration Test Generator
|
|
28
|
+
*/
|
|
29
|
+
export class IntegrationTestGenerator {
|
|
30
|
+
config;
|
|
31
|
+
constructor(config) {
|
|
32
|
+
this.config = { ...DEFAULT_INTEGRATION_CONFIG, ...config };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate API integration tests
|
|
36
|
+
*/
|
|
37
|
+
generateApiTests(endpoints, targetFile) {
|
|
38
|
+
const scenarios = endpoints.map((endpoint) => this.createApiScenario(endpoint));
|
|
39
|
+
const suite = {
|
|
40
|
+
name: 'API Integration Tests',
|
|
41
|
+
description: 'Integration tests for API endpoints',
|
|
42
|
+
type: 'api',
|
|
43
|
+
scenarios,
|
|
44
|
+
fixtures: [],
|
|
45
|
+
};
|
|
46
|
+
return this.generateTestFile(suite, targetFile);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generate service integration tests
|
|
50
|
+
*/
|
|
51
|
+
generateServiceTests(interactions, targetFile) {
|
|
52
|
+
const scenarios = interactions.map((interaction) => this.createServiceScenario(interaction));
|
|
53
|
+
const suite = {
|
|
54
|
+
name: 'Service Integration Tests',
|
|
55
|
+
description: 'Integration tests for service interactions',
|
|
56
|
+
type: 'service',
|
|
57
|
+
scenarios,
|
|
58
|
+
fixtures: [],
|
|
59
|
+
};
|
|
60
|
+
return this.generateTestFile(suite, targetFile);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Generate database integration tests
|
|
64
|
+
*/
|
|
65
|
+
generateDatabaseTests(operations, targetFile) {
|
|
66
|
+
const scenarios = operations.map((op) => this.createDatabaseScenario(op));
|
|
67
|
+
const fixtures = [
|
|
68
|
+
{
|
|
69
|
+
name: 'database-connection',
|
|
70
|
+
type: 'database',
|
|
71
|
+
data: { connectionString: this.config.dbConnectionPattern },
|
|
72
|
+
cleanupRequired: true,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
const suite = {
|
|
76
|
+
name: 'Database Integration Tests',
|
|
77
|
+
description: 'Integration tests for database operations',
|
|
78
|
+
type: 'database',
|
|
79
|
+
scenarios,
|
|
80
|
+
fixtures,
|
|
81
|
+
globalSetup: this.generateDatabaseSetup(),
|
|
82
|
+
globalTeardown: this.generateDatabaseTeardown(),
|
|
83
|
+
};
|
|
84
|
+
return this.generateTestFile(suite, targetFile);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Generate workflow integration tests
|
|
88
|
+
*/
|
|
89
|
+
generateWorkflowTests(workflows, targetFile) {
|
|
90
|
+
const scenarios = workflows.map((workflow) => this.createWorkflowScenario(workflow));
|
|
91
|
+
const suite = {
|
|
92
|
+
name: 'Workflow Integration Tests',
|
|
93
|
+
description: 'Integration tests for business workflows',
|
|
94
|
+
type: 'workflow',
|
|
95
|
+
scenarios,
|
|
96
|
+
fixtures: [],
|
|
97
|
+
};
|
|
98
|
+
return this.generateTestFile(suite, targetFile);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Generate from scenarios
|
|
102
|
+
*/
|
|
103
|
+
generateFromScenarios(scenarios, suiteName, targetFile) {
|
|
104
|
+
const suite = {
|
|
105
|
+
name: suiteName,
|
|
106
|
+
description: `Integration tests: ${suiteName}`,
|
|
107
|
+
type: scenarios[0]?.type ?? 'component',
|
|
108
|
+
scenarios,
|
|
109
|
+
fixtures: this.collectFixtures(scenarios),
|
|
110
|
+
};
|
|
111
|
+
return this.generateTestFile(suite, targetFile);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create API scenario
|
|
115
|
+
*/
|
|
116
|
+
createApiScenario(endpoint) {
|
|
117
|
+
const steps = [
|
|
118
|
+
{
|
|
119
|
+
order: 1,
|
|
120
|
+
action: `Send ${endpoint.method} request to ${endpoint.path}`,
|
|
121
|
+
target: 'api',
|
|
122
|
+
method: endpoint.method,
|
|
123
|
+
input: endpoint.requestBody,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
const expectedOutcomes = [
|
|
127
|
+
{
|
|
128
|
+
component: 'api',
|
|
129
|
+
type: 'response',
|
|
130
|
+
expected: { status: endpoint.method === 'POST' ? 201 : 200 },
|
|
131
|
+
matcher: 'contains',
|
|
132
|
+
},
|
|
133
|
+
];
|
|
134
|
+
if (endpoint.responseSchema) {
|
|
135
|
+
expectedOutcomes.push({
|
|
136
|
+
component: 'api',
|
|
137
|
+
type: 'response',
|
|
138
|
+
expected: endpoint.responseSchema,
|
|
139
|
+
matcher: 'matches',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
name: `${endpoint.method} ${endpoint.path}`,
|
|
144
|
+
description: `Test ${endpoint.method} ${endpoint.path} endpoint`,
|
|
145
|
+
type: 'api',
|
|
146
|
+
components: ['api'],
|
|
147
|
+
preconditions: endpoint.auth !== 'none' ? ['User is authenticated'] : [],
|
|
148
|
+
steps,
|
|
149
|
+
expectedOutcomes,
|
|
150
|
+
timeout: this.config.defaultTimeout,
|
|
151
|
+
tags: ['api', endpoint.method.toLowerCase()],
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Create service scenario
|
|
156
|
+
*/
|
|
157
|
+
createServiceScenario(interaction) {
|
|
158
|
+
const steps = [
|
|
159
|
+
{
|
|
160
|
+
order: 1,
|
|
161
|
+
action: `Call ${interaction.method} on ${interaction.target}`,
|
|
162
|
+
target: interaction.target,
|
|
163
|
+
method: interaction.method,
|
|
164
|
+
input: interaction.input,
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
if (interaction.type === 'async' || interaction.type === 'event') {
|
|
168
|
+
steps.push({
|
|
169
|
+
order: 2,
|
|
170
|
+
action: 'Wait for response/event',
|
|
171
|
+
target: interaction.source,
|
|
172
|
+
waitFor: 'response',
|
|
173
|
+
delay: 1000,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
name: `${interaction.source} → ${interaction.target}`,
|
|
178
|
+
description: `Test ${interaction.source} calling ${interaction.target}.${interaction.method}`,
|
|
179
|
+
type: 'service',
|
|
180
|
+
components: [interaction.source, interaction.target],
|
|
181
|
+
preconditions: ['Services are running'],
|
|
182
|
+
steps,
|
|
183
|
+
expectedOutcomes: [
|
|
184
|
+
{
|
|
185
|
+
component: interaction.source,
|
|
186
|
+
type: 'response',
|
|
187
|
+
expected: interaction.output ?? {},
|
|
188
|
+
matcher: interaction.output ? 'equals' : 'exists',
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
tags: ['service', interaction.type],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Create database scenario
|
|
196
|
+
*/
|
|
197
|
+
createDatabaseScenario(operation) {
|
|
198
|
+
const steps = [];
|
|
199
|
+
const expectedOutcomes = [];
|
|
200
|
+
switch (operation.type) {
|
|
201
|
+
case 'insert':
|
|
202
|
+
steps.push({
|
|
203
|
+
order: 1,
|
|
204
|
+
action: `Insert into ${operation.table}`,
|
|
205
|
+
target: 'database',
|
|
206
|
+
method: 'insert',
|
|
207
|
+
input: operation.data,
|
|
208
|
+
});
|
|
209
|
+
expectedOutcomes.push({
|
|
210
|
+
component: 'database',
|
|
211
|
+
type: 'data',
|
|
212
|
+
expected: { rowCount: 1 },
|
|
213
|
+
matcher: 'contains',
|
|
214
|
+
});
|
|
215
|
+
break;
|
|
216
|
+
case 'select':
|
|
217
|
+
steps.push({
|
|
218
|
+
order: 1,
|
|
219
|
+
action: `Select from ${operation.table}`,
|
|
220
|
+
target: 'database',
|
|
221
|
+
method: 'select',
|
|
222
|
+
input: operation.data,
|
|
223
|
+
});
|
|
224
|
+
expectedOutcomes.push({
|
|
225
|
+
component: 'database',
|
|
226
|
+
type: 'data',
|
|
227
|
+
expected: { rows: [] },
|
|
228
|
+
matcher: 'exists',
|
|
229
|
+
});
|
|
230
|
+
break;
|
|
231
|
+
case 'update':
|
|
232
|
+
steps.push({
|
|
233
|
+
order: 1,
|
|
234
|
+
action: `Setup: Insert test data into ${operation.table}`,
|
|
235
|
+
target: 'database',
|
|
236
|
+
method: 'insert',
|
|
237
|
+
input: operation.data,
|
|
238
|
+
}, {
|
|
239
|
+
order: 2,
|
|
240
|
+
action: `Update ${operation.table}`,
|
|
241
|
+
target: 'database',
|
|
242
|
+
method: 'update',
|
|
243
|
+
input: operation.data,
|
|
244
|
+
});
|
|
245
|
+
expectedOutcomes.push({
|
|
246
|
+
component: 'database',
|
|
247
|
+
type: 'data',
|
|
248
|
+
expected: { rowCount: 1 },
|
|
249
|
+
matcher: 'contains',
|
|
250
|
+
});
|
|
251
|
+
break;
|
|
252
|
+
case 'delete':
|
|
253
|
+
steps.push({
|
|
254
|
+
order: 1,
|
|
255
|
+
action: `Setup: Insert test data into ${operation.table}`,
|
|
256
|
+
target: 'database',
|
|
257
|
+
method: 'insert',
|
|
258
|
+
input: operation.data,
|
|
259
|
+
}, {
|
|
260
|
+
order: 2,
|
|
261
|
+
action: `Delete from ${operation.table}`,
|
|
262
|
+
target: 'database',
|
|
263
|
+
method: 'delete',
|
|
264
|
+
});
|
|
265
|
+
expectedOutcomes.push({
|
|
266
|
+
component: 'database',
|
|
267
|
+
type: 'data',
|
|
268
|
+
expected: { rowCount: 1 },
|
|
269
|
+
matcher: 'contains',
|
|
270
|
+
});
|
|
271
|
+
break;
|
|
272
|
+
case 'transaction':
|
|
273
|
+
steps.push({
|
|
274
|
+
order: 1,
|
|
275
|
+
action: 'Begin transaction',
|
|
276
|
+
target: 'database',
|
|
277
|
+
method: 'beginTransaction',
|
|
278
|
+
}, {
|
|
279
|
+
order: 2,
|
|
280
|
+
action: `Perform operations on ${operation.table}`,
|
|
281
|
+
target: 'database',
|
|
282
|
+
method: 'execute',
|
|
283
|
+
input: operation.data,
|
|
284
|
+
}, {
|
|
285
|
+
order: 3,
|
|
286
|
+
action: 'Commit transaction',
|
|
287
|
+
target: 'database',
|
|
288
|
+
method: 'commit',
|
|
289
|
+
});
|
|
290
|
+
expectedOutcomes.push({
|
|
291
|
+
component: 'database',
|
|
292
|
+
type: 'state',
|
|
293
|
+
expected: { committed: true },
|
|
294
|
+
matcher: 'equals',
|
|
295
|
+
});
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
name: operation.name,
|
|
300
|
+
description: `Database ${operation.type} test for ${operation.table}`,
|
|
301
|
+
type: 'database',
|
|
302
|
+
components: ['database', operation.table],
|
|
303
|
+
preconditions: ['Database connection established', 'Test database clean'],
|
|
304
|
+
steps,
|
|
305
|
+
expectedOutcomes,
|
|
306
|
+
tags: ['database', operation.type],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Create workflow scenario
|
|
311
|
+
*/
|
|
312
|
+
createWorkflowScenario(workflow) {
|
|
313
|
+
const steps = workflow.steps.map((step, index) => ({
|
|
314
|
+
order: index + 1,
|
|
315
|
+
action: step,
|
|
316
|
+
target: 'workflow',
|
|
317
|
+
}));
|
|
318
|
+
const expectedOutcomes = Object.entries(workflow.expectedState).map(([key, value]) => ({
|
|
319
|
+
component: 'workflow',
|
|
320
|
+
type: 'state',
|
|
321
|
+
expected: { [key]: value },
|
|
322
|
+
matcher: 'equals',
|
|
323
|
+
}));
|
|
324
|
+
return {
|
|
325
|
+
name: workflow.name,
|
|
326
|
+
description: `Workflow test: ${workflow.name}`,
|
|
327
|
+
type: 'workflow',
|
|
328
|
+
components: ['workflow'],
|
|
329
|
+
preconditions: ['System in initial state'],
|
|
330
|
+
steps,
|
|
331
|
+
expectedOutcomes,
|
|
332
|
+
tags: ['workflow', 'e2e'],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Generate test file
|
|
337
|
+
*/
|
|
338
|
+
generateTestFile(suite, targetFile) {
|
|
339
|
+
const lines = [];
|
|
340
|
+
// Imports
|
|
341
|
+
lines.push(this.generateImports(suite));
|
|
342
|
+
lines.push('');
|
|
343
|
+
// Global setup
|
|
344
|
+
if (suite.globalSetup) {
|
|
345
|
+
lines.push(suite.globalSetup);
|
|
346
|
+
lines.push('');
|
|
347
|
+
}
|
|
348
|
+
// Describe block
|
|
349
|
+
lines.push(`describe('${suite.name}', () => {`);
|
|
350
|
+
// Setup/teardown
|
|
351
|
+
if (this.config.includeFixtures && suite.fixtures.length > 0) {
|
|
352
|
+
lines.push(this.generateFixtureSetup(suite.fixtures));
|
|
353
|
+
}
|
|
354
|
+
if (suite.globalTeardown) {
|
|
355
|
+
lines.push(` afterAll(async () => {`);
|
|
356
|
+
lines.push(` ${suite.globalTeardown}`);
|
|
357
|
+
lines.push(` });`);
|
|
358
|
+
lines.push('');
|
|
359
|
+
}
|
|
360
|
+
// Scenarios
|
|
361
|
+
for (const scenario of suite.scenarios) {
|
|
362
|
+
lines.push(this.generateScenarioTest(scenario));
|
|
363
|
+
lines.push('');
|
|
364
|
+
}
|
|
365
|
+
lines.push('});');
|
|
366
|
+
// Calculate metadata
|
|
367
|
+
const content = lines.join('\n');
|
|
368
|
+
const filePath = this.getTestFilePath(targetFile);
|
|
369
|
+
const fixtures = suite.fixtures.map((f) => f.name);
|
|
370
|
+
const externalDeps = this.collectExternalDependencies(suite);
|
|
371
|
+
const estimatedDuration = this.estimateDuration(suite);
|
|
372
|
+
return {
|
|
373
|
+
content,
|
|
374
|
+
filePath,
|
|
375
|
+
scenarioCount: suite.scenarios.length,
|
|
376
|
+
fixtures,
|
|
377
|
+
externalDependencies: externalDeps,
|
|
378
|
+
estimatedDuration,
|
|
379
|
+
warnings: this.generateWarnings(suite),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Generate imports
|
|
384
|
+
*/
|
|
385
|
+
generateImports(suite) {
|
|
386
|
+
const lines = [];
|
|
387
|
+
// Framework imports
|
|
388
|
+
switch (this.config.framework) {
|
|
389
|
+
case 'jest':
|
|
390
|
+
// Jest globals are available
|
|
391
|
+
break;
|
|
392
|
+
case 'vitest':
|
|
393
|
+
lines.push("import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';");
|
|
394
|
+
break;
|
|
395
|
+
case 'mocha':
|
|
396
|
+
lines.push("import { expect } from 'chai';");
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
// Type-specific imports
|
|
400
|
+
if (suite.type === 'api') {
|
|
401
|
+
lines.push("import request from 'supertest';");
|
|
402
|
+
}
|
|
403
|
+
if (suite.type === 'database') {
|
|
404
|
+
lines.push("import { Pool } from 'pg';");
|
|
405
|
+
}
|
|
406
|
+
if (this.config.useContainers) {
|
|
407
|
+
lines.push("import { GenericContainer, StartedTestContainer } from 'testcontainers';");
|
|
408
|
+
}
|
|
409
|
+
return lines.join('\n');
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Generate fixture setup
|
|
413
|
+
*/
|
|
414
|
+
generateFixtureSetup(fixtures) {
|
|
415
|
+
const lines = [];
|
|
416
|
+
// Declare fixture variables
|
|
417
|
+
for (const fixture of fixtures) {
|
|
418
|
+
lines.push(` let ${fixture.name.replace(/-/g, '_')}: any;`);
|
|
419
|
+
}
|
|
420
|
+
lines.push('');
|
|
421
|
+
// Setup
|
|
422
|
+
lines.push(' beforeAll(async () => {');
|
|
423
|
+
for (const fixture of fixtures) {
|
|
424
|
+
const varName = fixture.name.replace(/-/g, '_');
|
|
425
|
+
switch (fixture.type) {
|
|
426
|
+
case 'database':
|
|
427
|
+
lines.push(` ${varName} = await setupDatabase(${JSON.stringify(fixture.data)});`);
|
|
428
|
+
break;
|
|
429
|
+
case 'mock-server':
|
|
430
|
+
lines.push(` ${varName} = await startMockServer(${JSON.stringify(fixture.data)});`);
|
|
431
|
+
break;
|
|
432
|
+
case 'file':
|
|
433
|
+
lines.push(` ${varName} = await setupTestFiles(${JSON.stringify(fixture.data)});`);
|
|
434
|
+
break;
|
|
435
|
+
default:
|
|
436
|
+
lines.push(` ${varName} = ${JSON.stringify(fixture.data)};`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
lines.push(' });');
|
|
440
|
+
lines.push('');
|
|
441
|
+
// Teardown
|
|
442
|
+
if (fixtures.some((f) => f.cleanupRequired)) {
|
|
443
|
+
lines.push(' afterAll(async () => {');
|
|
444
|
+
for (const fixture of fixtures.filter((f) => f.cleanupRequired)) {
|
|
445
|
+
const varName = fixture.name.replace(/-/g, '_');
|
|
446
|
+
switch (fixture.type) {
|
|
447
|
+
case 'database':
|
|
448
|
+
lines.push(` await ${varName}?.end();`);
|
|
449
|
+
break;
|
|
450
|
+
case 'mock-server':
|
|
451
|
+
lines.push(` await ${varName}?.close();`);
|
|
452
|
+
break;
|
|
453
|
+
case 'file':
|
|
454
|
+
lines.push(` await cleanupTestFiles(${varName});`);
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
lines.push(' });');
|
|
459
|
+
lines.push('');
|
|
460
|
+
}
|
|
461
|
+
return lines.join('\n');
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Generate scenario test
|
|
465
|
+
*/
|
|
466
|
+
generateScenarioTest(scenario) {
|
|
467
|
+
const lines = [];
|
|
468
|
+
const timeout = scenario.timeout ?? this.config.defaultTimeout;
|
|
469
|
+
lines.push(` describe('${scenario.name}', () => {`);
|
|
470
|
+
// Add tags as comments
|
|
471
|
+
if (scenario.tags?.length) {
|
|
472
|
+
lines.push(` // Tags: ${scenario.tags.join(', ')}`);
|
|
473
|
+
}
|
|
474
|
+
// Preconditions setup
|
|
475
|
+
if (scenario.preconditions.length > 0) {
|
|
476
|
+
lines.push(' // Preconditions:');
|
|
477
|
+
for (const precondition of scenario.preconditions) {
|
|
478
|
+
lines.push(` // - ${precondition}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// Generate test based on type
|
|
482
|
+
switch (scenario.type) {
|
|
483
|
+
case 'api':
|
|
484
|
+
lines.push(this.generateApiTest(scenario, timeout));
|
|
485
|
+
break;
|
|
486
|
+
case 'database':
|
|
487
|
+
lines.push(this.generateDatabaseTest(scenario, timeout));
|
|
488
|
+
break;
|
|
489
|
+
case 'service':
|
|
490
|
+
lines.push(this.generateServiceTest(scenario, timeout));
|
|
491
|
+
break;
|
|
492
|
+
case 'workflow':
|
|
493
|
+
lines.push(this.generateWorkflowTest(scenario, timeout));
|
|
494
|
+
break;
|
|
495
|
+
default:
|
|
496
|
+
lines.push(this.generateGenericTest(scenario, timeout));
|
|
497
|
+
}
|
|
498
|
+
lines.push(' });');
|
|
499
|
+
return lines.join('\n');
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Generate API test
|
|
503
|
+
*/
|
|
504
|
+
generateApiTest(scenario, timeout) {
|
|
505
|
+
const lines = [];
|
|
506
|
+
const step = scenario.steps[0];
|
|
507
|
+
lines.push(` it('${scenario.description}', async () => {`);
|
|
508
|
+
lines.push(` const response = await request(app)`);
|
|
509
|
+
lines.push(` .${(step?.method ?? 'get').toLowerCase()}('${step?.target ?? '/'}')`);
|
|
510
|
+
if (step?.input) {
|
|
511
|
+
lines.push(` .send(${JSON.stringify(step.input)})`);
|
|
512
|
+
}
|
|
513
|
+
lines.push(` .expect('Content-Type', /json/);`);
|
|
514
|
+
lines.push('');
|
|
515
|
+
for (const outcome of scenario.expectedOutcomes) {
|
|
516
|
+
if (outcome.type === 'response') {
|
|
517
|
+
const expected = outcome.expected;
|
|
518
|
+
if (expected.status) {
|
|
519
|
+
lines.push(` expect(response.status).toBe(${expected.status});`);
|
|
520
|
+
}
|
|
521
|
+
if (expected.body) {
|
|
522
|
+
lines.push(` expect(response.body).toMatchObject(${JSON.stringify(expected.body)});`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
lines.push(` }, ${timeout});`);
|
|
527
|
+
return lines.join('\n');
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Generate database test
|
|
531
|
+
*/
|
|
532
|
+
generateDatabaseTest(scenario, timeout) {
|
|
533
|
+
const lines = [];
|
|
534
|
+
lines.push(` it('${scenario.description}', async () => {`);
|
|
535
|
+
lines.push(' const client = await pool.connect();');
|
|
536
|
+
lines.push(' try {');
|
|
537
|
+
for (const step of scenario.steps) {
|
|
538
|
+
lines.push(` // Step ${step.order}: ${step.action}`);
|
|
539
|
+
switch (step.method) {
|
|
540
|
+
case 'insert':
|
|
541
|
+
lines.push(` const insertResult = await client.query(`);
|
|
542
|
+
lines.push(` 'INSERT INTO ${step.target} VALUES ($1) RETURNING *',`);
|
|
543
|
+
lines.push(` [${JSON.stringify(step.input)}]`);
|
|
544
|
+
lines.push(' );');
|
|
545
|
+
break;
|
|
546
|
+
case 'select':
|
|
547
|
+
lines.push(` const selectResult = await client.query('SELECT * FROM ${step.target}');`);
|
|
548
|
+
break;
|
|
549
|
+
case 'update':
|
|
550
|
+
lines.push(` const updateResult = await client.query(`);
|
|
551
|
+
lines.push(` 'UPDATE ${step.target} SET data = $1',`);
|
|
552
|
+
lines.push(` [${JSON.stringify(step.input)}]`);
|
|
553
|
+
lines.push(' );');
|
|
554
|
+
break;
|
|
555
|
+
case 'delete':
|
|
556
|
+
lines.push(` const deleteResult = await client.query('DELETE FROM ${step.target}');`);
|
|
557
|
+
break;
|
|
558
|
+
case 'beginTransaction':
|
|
559
|
+
lines.push(' await client.query(\'BEGIN\');');
|
|
560
|
+
break;
|
|
561
|
+
case 'commit':
|
|
562
|
+
lines.push(' await client.query(\'COMMIT\');');
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
lines.push('');
|
|
567
|
+
for (const outcome of scenario.expectedOutcomes) {
|
|
568
|
+
const expected = outcome.expected;
|
|
569
|
+
if (expected.rowCount !== undefined) {
|
|
570
|
+
lines.push(` expect(result.rowCount).toBe(${expected.rowCount});`);
|
|
571
|
+
}
|
|
572
|
+
if (expected.committed !== undefined) {
|
|
573
|
+
lines.push(' // Transaction committed successfully');
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
lines.push(' } finally {');
|
|
577
|
+
lines.push(' client.release();');
|
|
578
|
+
lines.push(' }');
|
|
579
|
+
lines.push(` }, ${timeout});`);
|
|
580
|
+
return lines.join('\n');
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Generate service test
|
|
584
|
+
*/
|
|
585
|
+
generateServiceTest(scenario, timeout) {
|
|
586
|
+
const lines = [];
|
|
587
|
+
lines.push(` it('${scenario.description}', async () => {`);
|
|
588
|
+
for (const step of scenario.steps) {
|
|
589
|
+
lines.push(` // Step ${step.order}: ${step.action}`);
|
|
590
|
+
if (step.delay) {
|
|
591
|
+
lines.push(` await new Promise(resolve => setTimeout(resolve, ${step.delay}));`);
|
|
592
|
+
}
|
|
593
|
+
lines.push(` const result${step.order} = await ${step.target}.${step.method}(${JSON.stringify(step.input)});`);
|
|
594
|
+
}
|
|
595
|
+
lines.push('');
|
|
596
|
+
for (const outcome of scenario.expectedOutcomes) {
|
|
597
|
+
switch (outcome.matcher) {
|
|
598
|
+
case 'equals':
|
|
599
|
+
lines.push(` expect(result).toEqual(${JSON.stringify(outcome.expected)});`);
|
|
600
|
+
break;
|
|
601
|
+
case 'contains':
|
|
602
|
+
lines.push(` expect(result).toMatchObject(${JSON.stringify(outcome.expected)});`);
|
|
603
|
+
break;
|
|
604
|
+
case 'exists':
|
|
605
|
+
lines.push(' expect(result).toBeDefined();');
|
|
606
|
+
break;
|
|
607
|
+
case 'called':
|
|
608
|
+
lines.push(` expect(${outcome.component}).toHaveBeenCalled();`);
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
lines.push(` }, ${timeout});`);
|
|
613
|
+
return lines.join('\n');
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Generate workflow test
|
|
617
|
+
*/
|
|
618
|
+
generateWorkflowTest(scenario, timeout) {
|
|
619
|
+
const lines = [];
|
|
620
|
+
lines.push(` it('${scenario.description}', async () => {`);
|
|
621
|
+
lines.push(' let state = initialState;');
|
|
622
|
+
lines.push('');
|
|
623
|
+
for (const step of scenario.steps) {
|
|
624
|
+
lines.push(` // Step ${step.order}: ${step.action}`);
|
|
625
|
+
lines.push(` state = await executeStep(state, '${step.action}');`);
|
|
626
|
+
}
|
|
627
|
+
lines.push('');
|
|
628
|
+
for (const outcome of scenario.expectedOutcomes) {
|
|
629
|
+
const expected = outcome.expected;
|
|
630
|
+
for (const [key, value] of Object.entries(expected)) {
|
|
631
|
+
lines.push(` expect(state.${key}).toEqual(${JSON.stringify(value)});`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
lines.push(` }, ${timeout});`);
|
|
635
|
+
return lines.join('\n');
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Generate generic test
|
|
639
|
+
*/
|
|
640
|
+
generateGenericTest(scenario, timeout) {
|
|
641
|
+
const lines = [];
|
|
642
|
+
lines.push(` it('${scenario.description}', async () => {`);
|
|
643
|
+
for (const step of scenario.steps) {
|
|
644
|
+
lines.push(` // ${step.action}`);
|
|
645
|
+
}
|
|
646
|
+
lines.push('');
|
|
647
|
+
lines.push(' // Add assertions');
|
|
648
|
+
lines.push(' expect(true).toBe(true);');
|
|
649
|
+
lines.push(` }, ${timeout});`);
|
|
650
|
+
return lines.join('\n');
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Generate database setup
|
|
654
|
+
*/
|
|
655
|
+
generateDatabaseSetup() {
|
|
656
|
+
return `
|
|
657
|
+
const pool = new Pool({
|
|
658
|
+
connectionString: process.env.DATABASE_URL || '${this.config.dbConnectionPattern}'
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
async function setupDatabase() {
|
|
662
|
+
const client = await pool.connect();
|
|
663
|
+
try {
|
|
664
|
+
// Create test tables
|
|
665
|
+
await client.query(\`
|
|
666
|
+
CREATE TABLE IF NOT EXISTS test_table (
|
|
667
|
+
id SERIAL PRIMARY KEY,
|
|
668
|
+
data JSONB
|
|
669
|
+
)
|
|
670
|
+
\`);
|
|
671
|
+
} finally {
|
|
672
|
+
client.release();
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
`.trim();
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Generate database teardown
|
|
679
|
+
*/
|
|
680
|
+
generateDatabaseTeardown() {
|
|
681
|
+
return `await pool.end();`;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Collect fixtures from scenarios
|
|
685
|
+
*/
|
|
686
|
+
collectFixtures(scenarios) {
|
|
687
|
+
const fixtures = new Map();
|
|
688
|
+
for (const scenario of scenarios) {
|
|
689
|
+
if (scenario.fixtures) {
|
|
690
|
+
for (const fixture of scenario.fixtures) {
|
|
691
|
+
if (!fixtures.has(fixture.name)) {
|
|
692
|
+
fixtures.set(fixture.name, fixture);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return Array.from(fixtures.values());
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Collect external dependencies
|
|
701
|
+
*/
|
|
702
|
+
collectExternalDependencies(suite) {
|
|
703
|
+
const deps = new Set();
|
|
704
|
+
if (suite.type === 'api') {
|
|
705
|
+
deps.add('supertest');
|
|
706
|
+
}
|
|
707
|
+
if (suite.type === 'database') {
|
|
708
|
+
deps.add('pg');
|
|
709
|
+
}
|
|
710
|
+
if (this.config.useContainers) {
|
|
711
|
+
deps.add('testcontainers');
|
|
712
|
+
}
|
|
713
|
+
return Array.from(deps);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Estimate duration
|
|
717
|
+
*/
|
|
718
|
+
estimateDuration(suite) {
|
|
719
|
+
let duration = 0;
|
|
720
|
+
for (const scenario of suite.scenarios) {
|
|
721
|
+
duration += scenario.timeout ?? this.config.defaultTimeout;
|
|
722
|
+
// Add time for each step
|
|
723
|
+
for (const step of scenario.steps) {
|
|
724
|
+
duration += step.delay ?? 100;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
// Add fixture setup time
|
|
728
|
+
duration += suite.fixtures.length * 2000;
|
|
729
|
+
return duration;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Get test file path
|
|
733
|
+
*/
|
|
734
|
+
getTestFilePath(targetFile) {
|
|
735
|
+
const parts = targetFile.split('/');
|
|
736
|
+
const filename = parts.pop();
|
|
737
|
+
const ext = filename.split('.').pop();
|
|
738
|
+
const baseName = filename.replace(`.${ext}`, '');
|
|
739
|
+
return [...parts, '__tests__', `${baseName}${this.config.testFileSuffix}.${ext}`].join('/');
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Generate warnings
|
|
743
|
+
*/
|
|
744
|
+
generateWarnings(suite) {
|
|
745
|
+
const warnings = [];
|
|
746
|
+
if (suite.scenarios.length > 20) {
|
|
747
|
+
warnings.push('Large number of scenarios - consider splitting into multiple files');
|
|
748
|
+
}
|
|
749
|
+
if (suite.type === 'database' && !suite.fixtures.some((f) => f.type === 'database')) {
|
|
750
|
+
warnings.push('Database tests without database fixture - tests may fail');
|
|
751
|
+
}
|
|
752
|
+
const totalDuration = this.estimateDuration(suite);
|
|
753
|
+
if (totalDuration > 300000) {
|
|
754
|
+
warnings.push('Estimated test duration exceeds 5 minutes - consider parallelization');
|
|
755
|
+
}
|
|
756
|
+
return warnings;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Create integration test generator instance
|
|
761
|
+
*/
|
|
762
|
+
export function createIntegrationTestGenerator(config) {
|
|
763
|
+
return new IntegrationTestGenerator(config);
|
|
764
|
+
}
|
|
765
|
+
//# sourceMappingURL=integration-test-generator.js.map
|