qa360 1.4.5 → 2.0.1
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/README.md +1 -1
- package/dist/commands/ai.d.ts +41 -0
- package/dist/commands/ai.js +499 -0
- package/dist/commands/ask.js +12 -12
- package/dist/commands/coverage.d.ts +8 -0
- package/dist/commands/coverage.js +252 -0
- package/dist/commands/explain.d.ts +27 -0
- package/dist/commands/explain.js +630 -0
- package/dist/commands/flakiness.d.ts +73 -0
- package/dist/commands/flakiness.js +435 -0
- package/dist/commands/generate.d.ts +66 -0
- package/dist/commands/generate.js +438 -0
- package/dist/commands/init.d.ts +56 -9
- package/dist/commands/init.js +217 -10
- package/dist/commands/monitor.d.ts +27 -0
- package/dist/commands/monitor.js +225 -0
- package/dist/commands/ollama.d.ts +40 -0
- package/dist/commands/ollama.js +301 -0
- package/dist/commands/pack.d.ts +37 -9
- package/dist/commands/pack.js +240 -141
- package/dist/commands/regression.d.ts +8 -0
- package/dist/commands/regression.js +340 -0
- package/dist/commands/repair.d.ts +26 -0
- package/dist/commands/repair.js +307 -0
- package/dist/commands/retry.d.ts +43 -0
- package/dist/commands/retry.js +275 -0
- package/dist/commands/run.d.ts +8 -3
- package/dist/commands/run.js +45 -31
- package/dist/commands/slo.d.ts +8 -0
- package/dist/commands/slo.js +327 -0
- package/dist/core/adapters/playwright-native-api.d.ts +183 -0
- package/dist/core/adapters/playwright-native-api.js +461 -0
- package/dist/core/adapters/playwright-ui.d.ts +7 -0
- package/dist/core/adapters/playwright-ui.js +29 -1
- package/dist/core/ai/anthropic-provider.d.ts +50 -0
- package/dist/core/ai/anthropic-provider.js +211 -0
- package/dist/core/ai/deepseek-provider.d.ts +81 -0
- package/dist/core/ai/deepseek-provider.js +254 -0
- package/dist/core/ai/index.d.ts +60 -0
- package/dist/core/ai/index.js +18 -0
- package/dist/core/ai/llm-client.d.ts +45 -0
- package/dist/core/ai/llm-client.js +7 -0
- package/dist/core/ai/mock-provider.d.ts +49 -0
- package/dist/core/ai/mock-provider.js +121 -0
- package/dist/core/ai/ollama-provider.d.ts +78 -0
- package/dist/core/ai/ollama-provider.js +192 -0
- package/dist/core/ai/openai-provider.d.ts +48 -0
- package/dist/core/ai/openai-provider.js +188 -0
- package/dist/core/ai/provider-factory.d.ts +160 -0
- package/dist/core/ai/provider-factory.js +269 -0
- package/dist/core/auth/api-key-provider.d.ts +16 -0
- package/dist/core/auth/api-key-provider.js +63 -0
- package/dist/core/auth/aws-iam-provider.d.ts +35 -0
- package/dist/core/auth/aws-iam-provider.js +177 -0
- package/dist/core/auth/azure-ad-provider.d.ts +15 -0
- package/dist/core/auth/azure-ad-provider.js +99 -0
- package/dist/core/auth/basic-auth-provider.d.ts +26 -0
- package/dist/core/auth/basic-auth-provider.js +111 -0
- package/dist/core/auth/gcp-adc-provider.d.ts +27 -0
- package/dist/core/auth/gcp-adc-provider.js +126 -0
- package/dist/core/auth/index.d.ts +238 -0
- package/dist/core/auth/index.js +82 -0
- package/dist/core/auth/jwt-provider.d.ts +19 -0
- package/dist/core/auth/jwt-provider.js +160 -0
- package/dist/core/auth/manager.d.ts +84 -0
- package/dist/core/auth/manager.js +230 -0
- package/dist/core/auth/oauth2-provider.d.ts +17 -0
- package/dist/core/auth/oauth2-provider.js +114 -0
- package/dist/core/auth/totp-provider.d.ts +31 -0
- package/dist/core/auth/totp-provider.js +134 -0
- package/dist/core/auth/ui-login-provider.d.ts +26 -0
- package/dist/core/auth/ui-login-provider.js +198 -0
- package/dist/core/cache/index.d.ts +7 -0
- package/dist/core/cache/index.js +6 -0
- package/dist/core/cache/lru-cache.d.ts +203 -0
- package/dist/core/cache/lru-cache.js +397 -0
- package/dist/core/coverage/analyzer.d.ts +101 -0
- package/dist/core/coverage/analyzer.js +415 -0
- package/dist/core/coverage/collector.d.ts +74 -0
- package/dist/core/coverage/collector.js +459 -0
- package/dist/core/coverage/config.d.ts +37 -0
- package/dist/core/coverage/config.js +156 -0
- package/dist/core/coverage/index.d.ts +11 -0
- package/dist/core/coverage/index.js +15 -0
- package/dist/core/coverage/types.d.ts +267 -0
- package/dist/core/coverage/types.js +6 -0
- package/dist/core/coverage/vault.d.ts +95 -0
- package/dist/core/coverage/vault.js +405 -0
- package/dist/core/dashboard/assets.d.ts +6 -0
- package/dist/core/dashboard/assets.js +690 -0
- package/dist/core/dashboard/index.d.ts +6 -0
- package/dist/core/dashboard/index.js +5 -0
- package/dist/core/dashboard/server.d.ts +72 -0
- package/dist/core/dashboard/server.js +354 -0
- package/dist/core/dashboard/types.d.ts +70 -0
- package/dist/core/dashboard/types.js +5 -0
- package/dist/core/discoverer/index.d.ts +115 -0
- package/dist/core/discoverer/index.js +250 -0
- package/dist/core/flakiness/index.d.ts +228 -0
- package/dist/core/flakiness/index.js +384 -0
- package/dist/core/generation/code-formatter.d.ts +111 -0
- package/dist/core/generation/code-formatter.js +307 -0
- package/dist/core/generation/code-generator.d.ts +144 -0
- package/dist/core/generation/code-generator.js +293 -0
- package/dist/core/generation/generator.d.ts +40 -0
- package/dist/core/generation/generator.js +76 -0
- package/dist/core/generation/index.d.ts +30 -0
- package/dist/core/generation/index.js +28 -0
- package/dist/core/generation/pack-generator.d.ts +107 -0
- package/dist/core/generation/pack-generator.js +416 -0
- package/dist/core/generation/prompt-builder.d.ts +132 -0
- package/dist/core/generation/prompt-builder.js +672 -0
- package/dist/core/generation/source-analyzer.d.ts +213 -0
- package/dist/core/generation/source-analyzer.js +657 -0
- package/dist/core/generation/test-optimizer.d.ts +117 -0
- package/dist/core/generation/test-optimizer.js +328 -0
- package/dist/core/generation/types.d.ts +214 -0
- package/dist/core/generation/types.js +4 -0
- package/dist/core/index.d.ts +23 -1
- package/dist/core/index.js +39 -0
- package/dist/core/pack/validator.js +31 -1
- package/dist/core/pack-v2/index.d.ts +9 -0
- package/dist/core/pack-v2/index.js +8 -0
- package/dist/core/pack-v2/loader.d.ts +62 -0
- package/dist/core/pack-v2/loader.js +231 -0
- package/dist/core/pack-v2/migrator.d.ts +56 -0
- package/dist/core/pack-v2/migrator.js +455 -0
- package/dist/core/pack-v2/validator.d.ts +61 -0
- package/dist/core/pack-v2/validator.js +577 -0
- package/dist/core/regression/detector.d.ts +107 -0
- package/dist/core/regression/detector.js +497 -0
- package/dist/core/regression/index.d.ts +9 -0
- package/dist/core/regression/index.js +11 -0
- package/dist/core/regression/trend-analyzer.d.ts +102 -0
- package/dist/core/regression/trend-analyzer.js +345 -0
- package/dist/core/regression/types.d.ts +222 -0
- package/dist/core/regression/types.js +7 -0
- package/dist/core/regression/vault.d.ts +87 -0
- package/dist/core/regression/vault.js +289 -0
- package/dist/core/repair/engine/fixer.d.ts +24 -0
- package/dist/core/repair/engine/fixer.js +226 -0
- package/dist/core/repair/engine/suggestion-engine.d.ts +18 -0
- package/dist/core/repair/engine/suggestion-engine.js +187 -0
- package/dist/core/repair/index.d.ts +10 -0
- package/dist/core/repair/index.js +13 -0
- package/dist/core/repair/repairer.d.ts +90 -0
- package/dist/core/repair/repairer.js +284 -0
- package/dist/core/repair/types.d.ts +91 -0
- package/dist/core/repair/types.js +6 -0
- package/dist/core/repair/utils/error-analyzer.d.ts +28 -0
- package/dist/core/repair/utils/error-analyzer.js +264 -0
- package/dist/core/retry/flakiness-integration.d.ts +60 -0
- package/dist/core/retry/flakiness-integration.js +228 -0
- package/dist/core/retry/index.d.ts +14 -0
- package/dist/core/retry/index.js +16 -0
- package/dist/core/retry/retry-engine.d.ts +80 -0
- package/dist/core/retry/retry-engine.js +296 -0
- package/dist/core/retry/types.d.ts +178 -0
- package/dist/core/retry/types.js +52 -0
- package/dist/core/retry/vault.d.ts +77 -0
- package/dist/core/retry/vault.js +304 -0
- package/dist/core/runner/e2e-helpers.d.ts +102 -0
- package/dist/core/runner/e2e-helpers.js +153 -0
- package/dist/core/runner/phase3-runner.d.ts +101 -2
- package/dist/core/runner/phase3-runner.js +559 -24
- package/dist/core/self-healing/assertion-healer.d.ts +97 -0
- package/dist/core/self-healing/assertion-healer.js +371 -0
- package/dist/core/self-healing/engine.d.ts +122 -0
- package/dist/core/self-healing/engine.js +538 -0
- package/dist/core/self-healing/index.d.ts +10 -0
- package/dist/core/self-healing/index.js +11 -0
- package/dist/core/self-healing/selector-healer.d.ts +103 -0
- package/dist/core/self-healing/selector-healer.js +372 -0
- package/dist/core/self-healing/types.d.ts +152 -0
- package/dist/core/self-healing/types.js +6 -0
- package/dist/core/slo/config.d.ts +107 -0
- package/dist/core/slo/config.js +360 -0
- package/dist/core/slo/index.d.ts +11 -0
- package/dist/core/slo/index.js +15 -0
- package/dist/core/slo/sli-calculator.d.ts +92 -0
- package/dist/core/slo/sli-calculator.js +364 -0
- package/dist/core/slo/slo-tracker.d.ts +148 -0
- package/dist/core/slo/slo-tracker.js +379 -0
- package/dist/core/slo/types.d.ts +281 -0
- package/dist/core/slo/types.js +7 -0
- package/dist/core/slo/vault.d.ts +102 -0
- package/dist/core/slo/vault.js +427 -0
- package/dist/core/tui/index.d.ts +7 -0
- package/dist/core/tui/index.js +6 -0
- package/dist/core/tui/monitor.d.ts +92 -0
- package/dist/core/tui/monitor.js +271 -0
- package/dist/core/tui/renderer.d.ts +33 -0
- package/dist/core/tui/renderer.js +218 -0
- package/dist/core/tui/types.d.ts +63 -0
- package/dist/core/tui/types.js +5 -0
- package/dist/core/types/pack-v2.d.ts +425 -0
- package/dist/core/types/pack-v2.js +8 -0
- package/dist/core/vault/index.d.ts +116 -0
- package/dist/core/vault/index.js +400 -5
- package/dist/core/watch/index.d.ts +7 -0
- package/dist/core/watch/index.js +6 -0
- package/dist/core/watch/watch-mode.d.ts +213 -0
- package/dist/core/watch/watch-mode.js +389 -0
- package/dist/index.js +68 -68
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +136 -0
- package/package.json +5 -1
- package/dist/core/adapters/playwright-api.d.ts +0 -82
- package/dist/core/adapters/playwright-api.js +0 -264
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Pack Generator
|
|
3
|
+
*
|
|
4
|
+
* Converts generated test specifications into QA360 pack YAML format.
|
|
5
|
+
* This bridges the gap between AI-generated tests and runnable QA360 packs.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const generator = new PackGenerator();
|
|
10
|
+
* const packYaml = generator.generateFromApiSpec(apiSpec, {
|
|
11
|
+
* name: 'my-api-tests',
|
|
12
|
+
* version: 2
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Pack Generator
|
|
18
|
+
*
|
|
19
|
+
* Converts test specifications into QA360 pack YAML format.
|
|
20
|
+
*/
|
|
21
|
+
export class PackGenerator {
|
|
22
|
+
defaults;
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.defaults = {
|
|
25
|
+
name: options.name ?? 'generated-tests',
|
|
26
|
+
description: options.description ?? 'Auto-generated test pack',
|
|
27
|
+
timeout: options.timeout ?? 30000,
|
|
28
|
+
retries: options.retries ?? 2,
|
|
29
|
+
onFailure: options.onFailure ?? 'continue',
|
|
30
|
+
cacheTtl: options.cacheTtl ?? 300000
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate pack from API test specification
|
|
35
|
+
*/
|
|
36
|
+
generateFromApiSpec(spec, options) {
|
|
37
|
+
const opts = { ...this.defaults, ...options };
|
|
38
|
+
const warnings = [];
|
|
39
|
+
// Build gates from API endpoints
|
|
40
|
+
const gates = {};
|
|
41
|
+
// Group endpoints by type (smoke, full, etc.)
|
|
42
|
+
const smokeEndpoints = spec.endpoints.filter((e) => e.method === 'GET' && (e.path.includes('/health') || e.path.includes('/status') || e.path === '/'));
|
|
43
|
+
const apiEndpoints = spec.endpoints.filter((e) => !smokeEndpoints.includes(e));
|
|
44
|
+
// Add api_smoke gate if we have smoke endpoints
|
|
45
|
+
if (smokeEndpoints.length > 0) {
|
|
46
|
+
gates['api_smoke'] = {
|
|
47
|
+
adapter: 'playwright-native-api',
|
|
48
|
+
config: {
|
|
49
|
+
target: {
|
|
50
|
+
baseUrl: spec.baseUrl,
|
|
51
|
+
smoke: smokeEndpoints.map((e) => this.formatEndpointSpec(e))
|
|
52
|
+
},
|
|
53
|
+
timeout: opts.timeout,
|
|
54
|
+
retries: opts.retries
|
|
55
|
+
},
|
|
56
|
+
options: {
|
|
57
|
+
timeout: opts.timeout,
|
|
58
|
+
retries: opts.retries
|
|
59
|
+
},
|
|
60
|
+
budgets: {
|
|
61
|
+
p95_ms: 2000,
|
|
62
|
+
p99_ms: 5000
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Add api_full gate if we have other endpoints
|
|
67
|
+
if (apiEndpoints.length > 0) {
|
|
68
|
+
gates['api_full'] = {
|
|
69
|
+
adapter: 'playwright-native-api',
|
|
70
|
+
config: {
|
|
71
|
+
target: {
|
|
72
|
+
baseUrl: spec.baseUrl,
|
|
73
|
+
smoke: apiEndpoints.map((e) => this.formatEndpointSpec(e))
|
|
74
|
+
},
|
|
75
|
+
timeout: opts.timeout,
|
|
76
|
+
retries: opts.retries
|
|
77
|
+
},
|
|
78
|
+
options: {
|
|
79
|
+
timeout: opts.timeout,
|
|
80
|
+
retries: opts.retries
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Build pack config
|
|
85
|
+
const config = {
|
|
86
|
+
version: 2,
|
|
87
|
+
name: opts.name,
|
|
88
|
+
description: opts.description,
|
|
89
|
+
gates,
|
|
90
|
+
execution: {
|
|
91
|
+
parallel: false,
|
|
92
|
+
on_failure: opts.onFailure === 'stop' ? 'stop' : 'continue'
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
// Add auth if specified
|
|
96
|
+
if (spec.auth && spec.auth.type !== 'none') {
|
|
97
|
+
const authType = spec.auth.type === 'bearer' ? 'bearer' :
|
|
98
|
+
spec.auth.type === 'basic' ? 'basic' :
|
|
99
|
+
spec.auth.type === 'api_key' ? 'api_key' :
|
|
100
|
+
spec.auth.type === 'jwt' ? 'jwt' :
|
|
101
|
+
spec.auth.type === 'oauth2' ? 'oauth2' :
|
|
102
|
+
'bearer';
|
|
103
|
+
config.auth = {
|
|
104
|
+
profiles: {
|
|
105
|
+
default: {
|
|
106
|
+
type: authType,
|
|
107
|
+
config: spec.auth.config || {}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
yaml: this.toYaml(config),
|
|
115
|
+
config,
|
|
116
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Generate pack from UI test specification
|
|
121
|
+
*/
|
|
122
|
+
generateFromUiSpec(spec, options) {
|
|
123
|
+
const opts = { ...this.defaults, ...options };
|
|
124
|
+
const warnings = [];
|
|
125
|
+
const gates = {};
|
|
126
|
+
// Add ui_smoke gate for basic page checks
|
|
127
|
+
gates['ui_smoke'] = {
|
|
128
|
+
adapter: 'playwright-ui',
|
|
129
|
+
config: {
|
|
130
|
+
target: {
|
|
131
|
+
baseUrl: spec.baseUrl,
|
|
132
|
+
pages: spec.pages.slice(0, 3).map((p) => ({
|
|
133
|
+
url: p.url,
|
|
134
|
+
name: p.name,
|
|
135
|
+
actions: p.actions.slice(0, 5).map((a) => this.formatPageAction(a))
|
|
136
|
+
}))
|
|
137
|
+
},
|
|
138
|
+
viewport: spec.viewport || { width: 1280, height: 720 }
|
|
139
|
+
},
|
|
140
|
+
options: {
|
|
141
|
+
timeout: opts.timeout,
|
|
142
|
+
retries: opts.retries
|
|
143
|
+
},
|
|
144
|
+
budgets: {
|
|
145
|
+
a11y_min: 80
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
// Add ui_full gate if we have more pages
|
|
149
|
+
if (spec.pages.length > 3) {
|
|
150
|
+
gates['ui_full'] = {
|
|
151
|
+
adapter: 'playwright-ui',
|
|
152
|
+
config: {
|
|
153
|
+
target: {
|
|
154
|
+
baseUrl: spec.baseUrl,
|
|
155
|
+
pages: spec.pages.map((p) => ({
|
|
156
|
+
url: p.url,
|
|
157
|
+
name: p.name,
|
|
158
|
+
actions: p.actions.map((a) => this.formatPageAction(a))
|
|
159
|
+
}))
|
|
160
|
+
},
|
|
161
|
+
viewport: spec.viewport || { width: 1280, height: 720 }
|
|
162
|
+
},
|
|
163
|
+
options: {
|
|
164
|
+
timeout: opts.timeout * 2,
|
|
165
|
+
retries: opts.retries
|
|
166
|
+
},
|
|
167
|
+
budgets: {
|
|
168
|
+
a11y_min: 90
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const config = {
|
|
173
|
+
version: 2,
|
|
174
|
+
name: opts.name,
|
|
175
|
+
description: opts.description,
|
|
176
|
+
gates,
|
|
177
|
+
execution: {
|
|
178
|
+
parallel: false,
|
|
179
|
+
on_failure: opts.onFailure === 'stop' ? 'stop' : 'continue'
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
return {
|
|
183
|
+
success: true,
|
|
184
|
+
yaml: this.toYaml(config),
|
|
185
|
+
config,
|
|
186
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Generate pack from performance test specification
|
|
191
|
+
*/
|
|
192
|
+
generateFromPerfSpec(spec, options) {
|
|
193
|
+
const opts = { ...this.defaults, ...options };
|
|
194
|
+
const warnings = [];
|
|
195
|
+
const gates = {};
|
|
196
|
+
// Build budgets from thresholds
|
|
197
|
+
const budgets = {
|
|
198
|
+
p95_ms: this.extractThreshold(spec.options?.thresholds || [], 'p(95)'),
|
|
199
|
+
p99_ms: this.extractThreshold(spec.options?.thresholds || [], 'p(99)')
|
|
200
|
+
};
|
|
201
|
+
// Add perf gate
|
|
202
|
+
gates['perf'] = {
|
|
203
|
+
adapter: 'k6-perf',
|
|
204
|
+
config: {
|
|
205
|
+
target: {
|
|
206
|
+
baseUrl: spec.baseUrl,
|
|
207
|
+
scenarios: spec.scenarios.map((s) => ({
|
|
208
|
+
name: s.name,
|
|
209
|
+
weight: s.weight,
|
|
210
|
+
requests: s.requests.map((r) => ({
|
|
211
|
+
method: r.method,
|
|
212
|
+
path: r.path,
|
|
213
|
+
headers: r.headers,
|
|
214
|
+
body: r.body
|
|
215
|
+
}))
|
|
216
|
+
}))
|
|
217
|
+
},
|
|
218
|
+
options: spec.options || {
|
|
219
|
+
duration: '30s',
|
|
220
|
+
vus: 10,
|
|
221
|
+
maxVus: 50
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
budgets
|
|
225
|
+
};
|
|
226
|
+
const config = {
|
|
227
|
+
version: 2,
|
|
228
|
+
name: opts.name,
|
|
229
|
+
description: opts.description,
|
|
230
|
+
gates,
|
|
231
|
+
execution: {
|
|
232
|
+
parallel: false,
|
|
233
|
+
on_failure: opts.onFailure === 'stop' ? 'stop' : 'continue'
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
return {
|
|
237
|
+
success: true,
|
|
238
|
+
yaml: this.toYaml(config),
|
|
239
|
+
config,
|
|
240
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Generate pack from generic test specification
|
|
245
|
+
*/
|
|
246
|
+
generateFromSpec(spec, options) {
|
|
247
|
+
switch (spec.type) {
|
|
248
|
+
case 'api':
|
|
249
|
+
return this.generateFromApiSpec(spec, options);
|
|
250
|
+
case 'ui':
|
|
251
|
+
return this.generateFromUiSpec(spec, options);
|
|
252
|
+
case 'perf':
|
|
253
|
+
return this.generateFromPerfSpec(spec, options);
|
|
254
|
+
case 'unit':
|
|
255
|
+
return {
|
|
256
|
+
success: false,
|
|
257
|
+
yaml: '',
|
|
258
|
+
config: {},
|
|
259
|
+
errors: ['Unit tests are not supported in pack YAML format. Use direct test file generation instead.']
|
|
260
|
+
};
|
|
261
|
+
default:
|
|
262
|
+
return {
|
|
263
|
+
success: false,
|
|
264
|
+
yaml: '',
|
|
265
|
+
config: {},
|
|
266
|
+
errors: [`Unknown test type: ${spec.type}`]
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Format endpoint as smoke test spec
|
|
272
|
+
*/
|
|
273
|
+
formatEndpointSpec(endpoint) {
|
|
274
|
+
const firstExpectation = endpoint.expectations?.[0];
|
|
275
|
+
const status = firstExpectation?.status ?? 200;
|
|
276
|
+
const statusStr = Array.isArray(status) ? status[0] : status;
|
|
277
|
+
return `${endpoint.method} ${endpoint.path} -> ${statusStr}`;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Format page action
|
|
281
|
+
*/
|
|
282
|
+
formatPageAction(action) {
|
|
283
|
+
const formatted = {
|
|
284
|
+
action: action.type
|
|
285
|
+
};
|
|
286
|
+
if (action.selector) {
|
|
287
|
+
formatted.selector = action.selector;
|
|
288
|
+
}
|
|
289
|
+
if (action.value) {
|
|
290
|
+
formatted.value = action.value;
|
|
291
|
+
}
|
|
292
|
+
if (action.timeout) {
|
|
293
|
+
formatted.timeout = action.timeout;
|
|
294
|
+
}
|
|
295
|
+
return formatted;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Extract threshold value from thresholds array
|
|
299
|
+
*/
|
|
300
|
+
extractThreshold(thresholds, metric) {
|
|
301
|
+
const threshold = thresholds.find((t) => t.condition.includes(metric));
|
|
302
|
+
if (threshold) {
|
|
303
|
+
const match = threshold.condition.match(/<(\d+)/);
|
|
304
|
+
return match ? parseInt(match[1], 10) : 1000;
|
|
305
|
+
}
|
|
306
|
+
return 1000;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Convert config to YAML string
|
|
310
|
+
* Note: This is a simple YAML generator. For production, use a proper YAML library.
|
|
311
|
+
*/
|
|
312
|
+
toYaml(config) {
|
|
313
|
+
const lines = [];
|
|
314
|
+
lines.push(`version: ${config.version}`);
|
|
315
|
+
lines.push(`name: ${config.name}`);
|
|
316
|
+
if (config.description) {
|
|
317
|
+
lines.push(`description: ${config.description}`);
|
|
318
|
+
}
|
|
319
|
+
// Gates
|
|
320
|
+
if (config.gates && Object.keys(config.gates).length > 0) {
|
|
321
|
+
lines.push(`\ngates:`);
|
|
322
|
+
for (const [gateName, gateConfig] of Object.entries(config.gates)) {
|
|
323
|
+
lines.push(` ${gateName}:`);
|
|
324
|
+
if (gateConfig.adapter) {
|
|
325
|
+
lines.push(` adapter: ${gateConfig.adapter}`);
|
|
326
|
+
}
|
|
327
|
+
if (gateConfig.config) {
|
|
328
|
+
lines.push(` config:`);
|
|
329
|
+
this.indentObject(lines, gateConfig.config, 6);
|
|
330
|
+
}
|
|
331
|
+
if (gateConfig.options) {
|
|
332
|
+
lines.push(` options:`);
|
|
333
|
+
this.indentObject(lines, gateConfig.options, 6);
|
|
334
|
+
}
|
|
335
|
+
if (gateConfig.budgets) {
|
|
336
|
+
lines.push(` budgets:`);
|
|
337
|
+
this.indentObject(lines, gateConfig.budgets, 6);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Auth
|
|
342
|
+
if (config.auth && config.auth.profiles) {
|
|
343
|
+
lines.push(`\nauth:`);
|
|
344
|
+
lines.push(` profiles:`);
|
|
345
|
+
for (const [profileName, profile] of Object.entries(config.auth.profiles)) {
|
|
346
|
+
lines.push(` ${profileName}:`);
|
|
347
|
+
this.indentObject(lines, profile, 6);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Execution
|
|
351
|
+
if (config.execution) {
|
|
352
|
+
lines.push(`\nexecution:`);
|
|
353
|
+
this.indentObject(lines, config.execution, 2);
|
|
354
|
+
}
|
|
355
|
+
return lines.join('\n');
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Helper to indent object properties
|
|
359
|
+
*/
|
|
360
|
+
indentObject(lines, obj, indent) {
|
|
361
|
+
const spaces = ' '.repeat(indent);
|
|
362
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
363
|
+
if (value === undefined || value === null) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
367
|
+
lines.push(`${spaces}${key}:`);
|
|
368
|
+
this.indentObject(lines, value, indent + 2);
|
|
369
|
+
}
|
|
370
|
+
else if (Array.isArray(value)) {
|
|
371
|
+
if (value.length === 0) {
|
|
372
|
+
lines.push(`${spaces}${key}: []`);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
lines.push(`${spaces}${key}:`);
|
|
376
|
+
for (const item of value) {
|
|
377
|
+
if (typeof item === 'object' && !Array.isArray(item)) {
|
|
378
|
+
lines.push(`${spaces} -`);
|
|
379
|
+
this.indentObject(lines, item, indent + 4);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
lines.push(`${spaces} - ${JSON.stringify(item)}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else if (typeof value === 'string') {
|
|
388
|
+
lines.push(`${spaces}${key}: ${value}`);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
lines.push(`${spaces}${key}: ${JSON.stringify(value)}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Convenience function to generate pack from API spec
|
|
398
|
+
*/
|
|
399
|
+
export function generatePackFromApiSpec(spec, options) {
|
|
400
|
+
const generator = new PackGenerator(options);
|
|
401
|
+
return generator.generateFromApiSpec(spec, options);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Convenience function to generate pack from UI spec
|
|
405
|
+
*/
|
|
406
|
+
export function generatePackFromUiSpec(spec, options) {
|
|
407
|
+
const generator = new PackGenerator(options);
|
|
408
|
+
return generator.generateFromUiSpec(spec, options);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Convenience function to generate pack from performance spec
|
|
412
|
+
*/
|
|
413
|
+
export function generatePackFromPerfSpec(spec, options) {
|
|
414
|
+
const generator = new PackGenerator(options);
|
|
415
|
+
return generator.generateFromPerfSpec(spec, options);
|
|
416
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Prompt Builder
|
|
3
|
+
*
|
|
4
|
+
* Constructs effective prompts for LLM test generation.
|
|
5
|
+
* Uses system prompts, few-shot examples, and structured templates.
|
|
6
|
+
*/
|
|
7
|
+
import type { TestSpec, GenerationSource } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Prompt builder options
|
|
10
|
+
*/
|
|
11
|
+
export interface PromptBuilderOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Include code comments in generated tests
|
|
14
|
+
*/
|
|
15
|
+
includeComments?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Include detailed assertions
|
|
18
|
+
*/
|
|
19
|
+
includeDetailedAssertions?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Include retry logic for flaky tests
|
|
22
|
+
*/
|
|
23
|
+
includeRetryLogic?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Target code style
|
|
26
|
+
*/
|
|
27
|
+
codeStyle?: 'clean' | 'verbose' | 'concise';
|
|
28
|
+
/**
|
|
29
|
+
* Few-shot examples to include
|
|
30
|
+
*/
|
|
31
|
+
examples?: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Custom system prompt
|
|
34
|
+
*/
|
|
35
|
+
systemPrompt?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Built prompt result
|
|
39
|
+
*/
|
|
40
|
+
export interface BuiltPrompt {
|
|
41
|
+
system: string;
|
|
42
|
+
user: string;
|
|
43
|
+
estimatedTokens: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Prompt Builder class
|
|
47
|
+
*/
|
|
48
|
+
export declare class PromptBuilder {
|
|
49
|
+
private readonly options;
|
|
50
|
+
private readonly defaultOptions;
|
|
51
|
+
constructor(options?: PromptBuilderOptions);
|
|
52
|
+
/**
|
|
53
|
+
* Build prompt from generation source
|
|
54
|
+
*/
|
|
55
|
+
buildFromSource(source: GenerationSource): Promise<BuiltPrompt>;
|
|
56
|
+
/**
|
|
57
|
+
* Build prompt from OpenAPI/Swagger spec
|
|
58
|
+
*/
|
|
59
|
+
buildFromOpenAPI(specPath: string): BuiltPrompt;
|
|
60
|
+
/**
|
|
61
|
+
* Build prompt from HAR file
|
|
62
|
+
*/
|
|
63
|
+
buildFromHAR(filePath: string): BuiltPrompt;
|
|
64
|
+
/**
|
|
65
|
+
* Build prompt from URL
|
|
66
|
+
*/
|
|
67
|
+
buildFromUrl(url: string): BuiltPrompt;
|
|
68
|
+
/**
|
|
69
|
+
* Build prompt from test spec
|
|
70
|
+
*/
|
|
71
|
+
buildFromSpec(spec: TestSpec): BuiltPrompt;
|
|
72
|
+
/**
|
|
73
|
+
* Build prompt from description
|
|
74
|
+
*/
|
|
75
|
+
buildFromDescription(description: string): BuiltPrompt;
|
|
76
|
+
/**
|
|
77
|
+
* Build prompt from existing code
|
|
78
|
+
*/
|
|
79
|
+
buildFromCode(code: string, language: string): BuiltPrompt;
|
|
80
|
+
/**
|
|
81
|
+
* Build API spec prompt
|
|
82
|
+
*/
|
|
83
|
+
private buildApiSpecPrompt;
|
|
84
|
+
/**
|
|
85
|
+
* Build UI spec prompt
|
|
86
|
+
*/
|
|
87
|
+
private buildUiSpecPrompt;
|
|
88
|
+
/**
|
|
89
|
+
* Build performance spec prompt
|
|
90
|
+
*/
|
|
91
|
+
private buildPerfSpecPrompt;
|
|
92
|
+
/**
|
|
93
|
+
* Build unit test spec prompt
|
|
94
|
+
*/
|
|
95
|
+
private buildUnitSpecPrompt;
|
|
96
|
+
/**
|
|
97
|
+
* Get default system prompt
|
|
98
|
+
*/
|
|
99
|
+
private getDefaultSystemPrompt;
|
|
100
|
+
/**
|
|
101
|
+
* Get code style instructions
|
|
102
|
+
*/
|
|
103
|
+
private getCodeStyleInstructions;
|
|
104
|
+
/**
|
|
105
|
+
* Get few-shot example
|
|
106
|
+
*/
|
|
107
|
+
private getFewShotExample;
|
|
108
|
+
/**
|
|
109
|
+
* Get API test example
|
|
110
|
+
*/
|
|
111
|
+
private getApiExample;
|
|
112
|
+
/**
|
|
113
|
+
* Get UI test example
|
|
114
|
+
*/
|
|
115
|
+
private getUiExample;
|
|
116
|
+
/**
|
|
117
|
+
* Get performance test example
|
|
118
|
+
*/
|
|
119
|
+
private getPerfExample;
|
|
120
|
+
/**
|
|
121
|
+
* Get unit test example
|
|
122
|
+
*/
|
|
123
|
+
private getUnitExample;
|
|
124
|
+
/**
|
|
125
|
+
* Count approximate tokens
|
|
126
|
+
*/
|
|
127
|
+
private countTokens;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create a prompt builder with default options
|
|
131
|
+
*/
|
|
132
|
+
export declare function createPromptBuilder(options?: PromptBuilderOptions): PromptBuilder;
|