@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.
Files changed (214) hide show
  1. package/bin/musubix.js +18 -0
  2. package/dist/__tests__/index.test.d.ts +2 -0
  3. package/dist/__tests__/index.test.d.ts.map +1 -0
  4. package/dist/__tests__/index.test.js +27 -0
  5. package/dist/__tests__/index.test.js.map +1 -0
  6. package/dist/auth/auth-manager.d.ts +320 -0
  7. package/dist/auth/auth-manager.d.ts.map +1 -0
  8. package/dist/auth/auth-manager.js +580 -0
  9. package/dist/auth/auth-manager.js.map +1 -0
  10. package/dist/cli/base.d.ts +58 -0
  11. package/dist/cli/base.d.ts.map +1 -0
  12. package/dist/cli/base.js +93 -0
  13. package/dist/cli/base.js.map +1 -0
  14. package/dist/cli/commands/help.d.ts +17 -0
  15. package/dist/cli/commands/help.d.ts.map +1 -0
  16. package/dist/cli/commands/help.js +228 -0
  17. package/dist/cli/commands/help.js.map +1 -0
  18. package/dist/cli/commands/index.d.ts +14 -0
  19. package/dist/cli/commands/index.d.ts.map +1 -0
  20. package/dist/cli/commands/index.js +25 -0
  21. package/dist/cli/commands/index.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts +38 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -0
  24. package/dist/cli/commands/init.js +258 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/cli/index.d.ts +9 -0
  27. package/dist/cli/index.d.ts.map +1 -0
  28. package/dist/cli/index.js +9 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/codegen/coding-standards.d.ts +250 -0
  31. package/dist/codegen/coding-standards.d.ts.map +1 -0
  32. package/dist/codegen/coding-standards.js +976 -0
  33. package/dist/codegen/coding-standards.js.map +1 -0
  34. package/dist/codegen/coverage-reporter.d.ts +264 -0
  35. package/dist/codegen/coverage-reporter.d.ts.map +1 -0
  36. package/dist/codegen/coverage-reporter.js +697 -0
  37. package/dist/codegen/coverage-reporter.js.map +1 -0
  38. package/dist/codegen/dependency-analyzer.d.ts +271 -0
  39. package/dist/codegen/dependency-analyzer.d.ts.map +1 -0
  40. package/dist/codegen/dependency-analyzer.js +661 -0
  41. package/dist/codegen/dependency-analyzer.js.map +1 -0
  42. package/dist/codegen/generator.d.ts +275 -0
  43. package/dist/codegen/generator.d.ts.map +1 -0
  44. package/dist/codegen/generator.js +781 -0
  45. package/dist/codegen/generator.js.map +1 -0
  46. package/dist/codegen/index.d.ts +18 -0
  47. package/dist/codegen/index.d.ts.map +1 -0
  48. package/dist/codegen/index.js +27 -0
  49. package/dist/codegen/index.js.map +1 -0
  50. package/dist/codegen/integration-test-generator.d.ts +312 -0
  51. package/dist/codegen/integration-test-generator.d.ts.map +1 -0
  52. package/dist/codegen/integration-test-generator.js +765 -0
  53. package/dist/codegen/integration-test-generator.js.map +1 -0
  54. package/dist/codegen/pattern-conformance.d.ts +309 -0
  55. package/dist/codegen/pattern-conformance.d.ts.map +1 -0
  56. package/dist/codegen/pattern-conformance.js +590 -0
  57. package/dist/codegen/pattern-conformance.js.map +1 -0
  58. package/dist/codegen/quality-metrics.d.ts +235 -0
  59. package/dist/codegen/quality-metrics.d.ts.map +1 -0
  60. package/dist/codegen/quality-metrics.js +439 -0
  61. package/dist/codegen/quality-metrics.js.map +1 -0
  62. package/dist/codegen/security-scanner.d.ts +179 -0
  63. package/dist/codegen/security-scanner.d.ts.map +1 -0
  64. package/dist/codegen/security-scanner.js +495 -0
  65. package/dist/codegen/security-scanner.js.map +1 -0
  66. package/dist/codegen/static-analyzer.d.ts +188 -0
  67. package/dist/codegen/static-analyzer.d.ts.map +1 -0
  68. package/dist/codegen/static-analyzer.js +490 -0
  69. package/dist/codegen/static-analyzer.js.map +1 -0
  70. package/dist/codegen/unit-test-generator.d.ts +289 -0
  71. package/dist/codegen/unit-test-generator.d.ts.map +1 -0
  72. package/dist/codegen/unit-test-generator.js +634 -0
  73. package/dist/codegen/unit-test-generator.js.map +1 -0
  74. package/dist/design/adr-generator.d.ts +227 -0
  75. package/dist/design/adr-generator.d.ts.map +1 -0
  76. package/dist/design/adr-generator.js +423 -0
  77. package/dist/design/adr-generator.js.map +1 -0
  78. package/dist/design/c4-generator.d.ts +267 -0
  79. package/dist/design/c4-generator.d.ts.map +1 -0
  80. package/dist/design/c4-generator.js +453 -0
  81. package/dist/design/c4-generator.js.map +1 -0
  82. package/dist/design/framework-optimizer.d.ts +190 -0
  83. package/dist/design/framework-optimizer.d.ts.map +1 -0
  84. package/dist/design/framework-optimizer.js +589 -0
  85. package/dist/design/framework-optimizer.js.map +1 -0
  86. package/dist/design/index.d.ts +12 -0
  87. package/dist/design/index.d.ts.map +1 -0
  88. package/dist/design/index.js +13 -0
  89. package/dist/design/index.js.map +1 -0
  90. package/dist/design/pattern-detector.d.ts +270 -0
  91. package/dist/design/pattern-detector.d.ts.map +1 -0
  92. package/dist/design/pattern-detector.js +621 -0
  93. package/dist/design/pattern-detector.js.map +1 -0
  94. package/dist/design/solid-validator.d.ts +188 -0
  95. package/dist/design/solid-validator.d.ts.map +1 -0
  96. package/dist/design/solid-validator.js +579 -0
  97. package/dist/design/solid-validator.js.map +1 -0
  98. package/dist/error/data-persistence.d.ts +311 -0
  99. package/dist/error/data-persistence.d.ts.map +1 -0
  100. package/dist/error/data-persistence.js +586 -0
  101. package/dist/error/data-persistence.js.map +1 -0
  102. package/dist/error/graceful-degradation.d.ts +309 -0
  103. package/dist/error/graceful-degradation.d.ts.map +1 -0
  104. package/dist/error/graceful-degradation.js +510 -0
  105. package/dist/error/graceful-degradation.js.map +1 -0
  106. package/dist/error/index.d.ts +11 -0
  107. package/dist/error/index.d.ts.map +1 -0
  108. package/dist/error/index.js +19 -0
  109. package/dist/error/index.js.map +1 -0
  110. package/dist/explanation/explanation-generator.d.ts +228 -0
  111. package/dist/explanation/explanation-generator.d.ts.map +1 -0
  112. package/dist/explanation/explanation-generator.js +662 -0
  113. package/dist/explanation/explanation-generator.js.map +1 -0
  114. package/dist/explanation/index.d.ts +11 -0
  115. package/dist/explanation/index.d.ts.map +1 -0
  116. package/dist/explanation/index.js +19 -0
  117. package/dist/explanation/index.js.map +1 -0
  118. package/dist/explanation/reasoning-chain.d.ts +314 -0
  119. package/dist/explanation/reasoning-chain.d.ts.map +1 -0
  120. package/dist/explanation/reasoning-chain.js +414 -0
  121. package/dist/explanation/reasoning-chain.js.map +1 -0
  122. package/dist/explanation/visual-explanation.d.ts +315 -0
  123. package/dist/explanation/visual-explanation.d.ts.map +1 -0
  124. package/dist/explanation/visual-explanation.js +667 -0
  125. package/dist/explanation/visual-explanation.js.map +1 -0
  126. package/dist/index.d.ts +33 -0
  127. package/dist/index.d.ts.map +1 -0
  128. package/dist/index.js +47 -0
  129. package/dist/index.js.map +1 -0
  130. package/dist/requirements/decomposer.d.ts +235 -0
  131. package/dist/requirements/decomposer.d.ts.map +1 -0
  132. package/dist/requirements/decomposer.js +587 -0
  133. package/dist/requirements/decomposer.js.map +1 -0
  134. package/dist/requirements/related-finder.d.ts +261 -0
  135. package/dist/requirements/related-finder.d.ts.map +1 -0
  136. package/dist/requirements/related-finder.js +629 -0
  137. package/dist/requirements/related-finder.js.map +1 -0
  138. package/dist/traceability/impact.d.ts +196 -0
  139. package/dist/traceability/impact.d.ts.map +1 -0
  140. package/dist/traceability/impact.js +438 -0
  141. package/dist/traceability/impact.js.map +1 -0
  142. package/dist/traceability/index.d.ts +9 -0
  143. package/dist/traceability/index.d.ts.map +1 -0
  144. package/dist/traceability/index.js +10 -0
  145. package/dist/traceability/index.js.map +1 -0
  146. package/dist/traceability/manager.d.ts +266 -0
  147. package/dist/traceability/manager.d.ts.map +1 -0
  148. package/dist/traceability/manager.js +412 -0
  149. package/dist/traceability/manager.js.map +1 -0
  150. package/dist/types/common.d.ts +294 -0
  151. package/dist/types/common.d.ts.map +1 -0
  152. package/dist/types/common.js +15 -0
  153. package/dist/types/common.js.map +1 -0
  154. package/dist/types/ears.d.ts +158 -0
  155. package/dist/types/ears.d.ts.map +1 -0
  156. package/dist/types/ears.js +33 -0
  157. package/dist/types/ears.js.map +1 -0
  158. package/dist/types/errors.d.ts +176 -0
  159. package/dist/types/errors.d.ts.map +1 -0
  160. package/dist/types/errors.js +55 -0
  161. package/dist/types/errors.js.map +1 -0
  162. package/dist/types/index.d.ts +10 -0
  163. package/dist/types/index.d.ts.map +1 -0
  164. package/dist/types/index.js +10 -0
  165. package/dist/types/index.js.map +1 -0
  166. package/dist/utils/data-protector.d.ts +122 -0
  167. package/dist/utils/data-protector.d.ts.map +1 -0
  168. package/dist/utils/data-protector.js +275 -0
  169. package/dist/utils/data-protector.js.map +1 -0
  170. package/dist/utils/error-handler.d.ts +101 -0
  171. package/dist/utils/error-handler.d.ts.map +1 -0
  172. package/dist/utils/error-handler.js +324 -0
  173. package/dist/utils/error-handler.js.map +1 -0
  174. package/dist/utils/i18n-manager.d.ts +259 -0
  175. package/dist/utils/i18n-manager.d.ts.map +1 -0
  176. package/dist/utils/i18n-manager.js +554 -0
  177. package/dist/utils/i18n-manager.js.map +1 -0
  178. package/dist/utils/index.d.ts +10 -0
  179. package/dist/utils/index.d.ts.map +1 -0
  180. package/dist/utils/index.js +10 -0
  181. package/dist/utils/index.js.map +1 -0
  182. package/dist/utils/logger.d.ts +120 -0
  183. package/dist/utils/logger.d.ts.map +1 -0
  184. package/dist/utils/logger.js +237 -0
  185. package/dist/utils/logger.js.map +1 -0
  186. package/dist/utils/performance-profiler.d.ts +251 -0
  187. package/dist/utils/performance-profiler.d.ts.map +1 -0
  188. package/dist/utils/performance-profiler.js +458 -0
  189. package/dist/utils/performance-profiler.js.map +1 -0
  190. package/dist/utils/scalability-optimizer.d.ts +294 -0
  191. package/dist/utils/scalability-optimizer.d.ts.map +1 -0
  192. package/dist/utils/scalability-optimizer.js +606 -0
  193. package/dist/utils/scalability-optimizer.js.map +1 -0
  194. package/dist/utils/structured-logger.d.ts +294 -0
  195. package/dist/utils/structured-logger.d.ts.map +1 -0
  196. package/dist/utils/structured-logger.js +630 -0
  197. package/dist/utils/structured-logger.js.map +1 -0
  198. package/dist/utils/version-compatibility.d.ts +217 -0
  199. package/dist/utils/version-compatibility.d.ts.map +1 -0
  200. package/dist/utils/version-compatibility.js +443 -0
  201. package/dist/utils/version-compatibility.js.map +1 -0
  202. package/dist/validators/ears-validator.d.ts +182 -0
  203. package/dist/validators/ears-validator.d.ts.map +1 -0
  204. package/dist/validators/ears-validator.js +357 -0
  205. package/dist/validators/ears-validator.js.map +1 -0
  206. package/dist/validators/index.d.ts +8 -0
  207. package/dist/validators/index.d.ts.map +1 -0
  208. package/dist/validators/index.js +9 -0
  209. package/dist/validators/index.js.map +1 -0
  210. package/dist/version.d.ts +8 -0
  211. package/dist/version.d.ts.map +1 -0
  212. package/dist/version.js +8 -0
  213. package/dist/version.js.map +1 -0
  214. 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