qa360 1.2.2 → 1.3.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/README.md CHANGED
@@ -32,33 +32,101 @@ npx qa360@latest doctor
32
32
 
33
33
  **Note**: On first run, Playwright browsers will be automatically downloaded (~100MB). This happens only once.
34
34
 
35
+ ## Quick Start
36
+
37
+ ### 1. Generate a test pack
38
+
39
+ ```bash
40
+ # Interactive mode (recommended for first-time users)
41
+ qa360 init
42
+
43
+ # Or use a template directly
44
+ qa360 init --template api-basic --yes
45
+ qa360 init --template fullstack --yes
46
+ ```
47
+
48
+ ### 2. Run tests
49
+
50
+ ```bash
51
+ qa360 run
52
+ ```
53
+
54
+ ### 3. Verify proof
55
+
56
+ ```bash
57
+ qa360 verify .qa360/runs/
58
+ ```
59
+
35
60
  ## Usage
36
61
 
37
62
  ```bash
63
+ # Generate test pack (interactive)
64
+ qa360 init
65
+
66
+ # Generate with template
67
+ qa360 init --template api-basic
68
+ qa360 init --template fullstack
69
+ qa360 init --template security
70
+ qa360 init --template complete
71
+
38
72
  # System health check
39
73
  qa360 doctor
40
74
 
41
75
  # Run test pack
42
- qa360 run test.yml
76
+ qa360 run # Auto-detects qa360.yml
77
+ qa360 run custom-pack.yml # Use specific file
43
78
 
44
79
  # Verify proof bundle
80
+ qa360 verify .qa360/runs/
45
81
  qa360 verify proof.json
46
82
 
83
+ # View run history
84
+ qa360 history list
85
+ qa360 history show <run-id>
86
+
47
87
  # With JSON output (CI-friendly)
48
88
  qa360 doctor --json
49
89
  qa360 verify proof.json --json
50
90
  ```
51
91
 
92
+ ## Available Templates
93
+
94
+ | Template | Description | Gates |
95
+ |----------|-------------|-------|
96
+ | **api-basic** | Simple API smoke tests | api_smoke |
97
+ | **ui-basic** | Basic UI/E2E tests | ui |
98
+ | **fullstack** | API + UI + Performance | api_smoke, ui, perf |
99
+ | **security** | Security testing suite | sast, dast, secrets, deps |
100
+ | **accessibility** | Accessibility testing | ui, a11y |
101
+ | **complete** | All quality gates | All (8 gates) |
102
+
103
+ ## Example Files
104
+
105
+ Pre-made examples are included in the package:
106
+
107
+ ```bash
108
+ # List examples
109
+ ls examples/
110
+
111
+ # Copy an example
112
+ cp examples/api-basic.yml qa360.yml
113
+
114
+ # Run example directly
115
+ qa360 run examples/api-basic.yml
116
+ ```
117
+
52
118
  ## Commands
53
119
 
54
120
  | Command | Description |
55
121
  |---------|-------------|
56
- | `doctor` | Check system health, auto-fix issues |
57
- | `verify` | Verify cryptographic proof bundles |
122
+ | `init` | Generate test pack interactively |
58
123
  | `run` | Execute test pack |
59
- | `serve` | Start observability server |
124
+ | `verify` | Verify cryptographic proof bundles |
125
+ | `doctor` | Check system health, auto-fix issues |
126
+ | `history` | View run history and results |
60
127
  | `report` | Generate reports |
61
128
  | `secrets` | Manage encrypted secrets |
129
+ | `pack` | Pack validation and linting |
62
130
 
63
131
  ## Exit Codes
64
132
 
@@ -0,0 +1,66 @@
1
+ /**
2
+ * QA360 Init Command - Interactive pack generator
3
+ *
4
+ * Usage:
5
+ * qa360 init
6
+ * qa360 init --template api-basic
7
+ * qa360 init --output custom-pack.yml
8
+ */
9
+ /**
10
+ * CLI options for init command
11
+ */
12
+ export interface InitOptions {
13
+ template?: string;
14
+ output?: string;
15
+ force?: boolean;
16
+ yes?: boolean;
17
+ }
18
+ /**
19
+ * Available templates
20
+ */
21
+ export declare const TEMPLATES: {
22
+ 'api-basic': {
23
+ name: string;
24
+ description: string;
25
+ gates: string[];
26
+ };
27
+ 'ui-basic': {
28
+ name: string;
29
+ description: string;
30
+ gates: string[];
31
+ };
32
+ fullstack: {
33
+ name: string;
34
+ description: string;
35
+ gates: string[];
36
+ };
37
+ security: {
38
+ name: string;
39
+ description: string;
40
+ gates: string[];
41
+ };
42
+ complete: {
43
+ name: string;
44
+ description: string;
45
+ gates: string[];
46
+ };
47
+ };
48
+ /**
49
+ * Gate descriptions
50
+ */
51
+ export declare const GATE_DESCRIPTIONS: {
52
+ api_smoke: string;
53
+ ui: string;
54
+ a11y: string;
55
+ perf: string;
56
+ sast: string;
57
+ dast: string;
58
+ secrets: string;
59
+ deps: string;
60
+ };
61
+ /**
62
+ * Main init command
63
+ */
64
+ export declare function initCommand(options?: InitOptions): Promise<void>;
65
+ export default initCommand;
66
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;CAS7B,CAAC;AAkNF;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwE1E;AAED,eAAe,WAAW,CAAC"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * QA360 Init Command - Interactive pack generator
3
+ *
4
+ * Usage:
5
+ * qa360 init
6
+ * qa360 init --template api-basic
7
+ * qa360 init --output custom-pack.yml
8
+ */
9
+ import { existsSync, writeFileSync, mkdirSync } from 'fs';
10
+ import { join, resolve } from 'path';
11
+ import chalk from 'chalk';
12
+ import inquirer from 'inquirer';
13
+ import { dump } from 'js-yaml';
14
+ /**
15
+ * Available templates
16
+ */
17
+ export const TEMPLATES = {
18
+ 'api-basic': {
19
+ name: 'API Basic',
20
+ description: 'Simple API smoke tests (REST/GraphQL)',
21
+ gates: ['api_smoke'],
22
+ },
23
+ 'ui-basic': {
24
+ name: 'UI Basic',
25
+ description: 'Basic UI/E2E browser tests',
26
+ gates: ['ui'],
27
+ },
28
+ 'fullstack': {
29
+ name: 'Full Stack',
30
+ description: 'API + UI + Performance tests',
31
+ gates: ['api_smoke', 'ui', 'perf'],
32
+ },
33
+ 'security': {
34
+ name: 'Security',
35
+ description: 'SAST, DAST, secrets scanning, dependency checks',
36
+ gates: ['sast', 'dast', 'secrets', 'deps'],
37
+ },
38
+ 'complete': {
39
+ name: 'Complete',
40
+ description: 'All quality gates (API, UI, Performance, Security, Accessibility)',
41
+ gates: ['api_smoke', 'ui', 'a11y', 'perf', 'sast', 'dast', 'secrets', 'deps'],
42
+ },
43
+ };
44
+ /**
45
+ * Gate descriptions
46
+ */
47
+ export const GATE_DESCRIPTIONS = {
48
+ api_smoke: 'API smoke tests (REST/GraphQL health checks)',
49
+ ui: 'UI/E2E tests (browser automation)',
50
+ a11y: 'Accessibility tests (WCAG compliance)',
51
+ perf: 'Performance tests (load/stress testing)',
52
+ sast: 'Static security analysis (code scanning)',
53
+ dast: 'Dynamic security testing (runtime scanning)',
54
+ secrets: 'Secrets detection (credential scanning)',
55
+ deps: 'Dependency vulnerability checks',
56
+ };
57
+ /**
58
+ * Interactive prompts
59
+ */
60
+ async function promptForConfig() {
61
+ const answers = await inquirer.prompt([
62
+ {
63
+ type: 'input',
64
+ name: 'name',
65
+ message: 'Pack name:',
66
+ default: 'my-qa360-tests',
67
+ validate: (input) => input.length > 0 || 'Name is required',
68
+ },
69
+ {
70
+ type: 'list',
71
+ name: 'template',
72
+ message: 'Choose a template:',
73
+ choices: Object.entries(TEMPLATES).map(([key, value]) => ({
74
+ name: `${value.name} - ${value.description}`,
75
+ value: key,
76
+ })),
77
+ },
78
+ {
79
+ type: 'confirm',
80
+ name: 'customizeGates',
81
+ message: 'Customize quality gates?',
82
+ default: false,
83
+ },
84
+ ]);
85
+ let gates = TEMPLATES[answers.template].gates;
86
+ if (answers.customizeGates) {
87
+ const gateAnswers = await inquirer.prompt([
88
+ {
89
+ type: 'checkbox',
90
+ name: 'gates',
91
+ message: 'Select quality gates to enable:',
92
+ choices: Object.entries(GATE_DESCRIPTIONS).map(([key, desc]) => ({
93
+ name: `${key} - ${desc}`,
94
+ value: key,
95
+ checked: gates.includes(key),
96
+ })),
97
+ validate: (input) => input.length > 0 || 'Select at least one gate',
98
+ },
99
+ ]);
100
+ gates = gateAnswers.gates;
101
+ }
102
+ // Prompt for target URLs based on selected gates
103
+ const targets = {};
104
+ if (gates.includes('api_smoke')) {
105
+ const apiAnswers = await inquirer.prompt([
106
+ {
107
+ type: 'input',
108
+ name: 'apiUrl',
109
+ message: 'API base URL:',
110
+ default: 'https://api.example.com',
111
+ validate: (input) => input.startsWith('http') || 'Must be a valid URL',
112
+ },
113
+ {
114
+ type: 'input',
115
+ name: 'smokeTests',
116
+ message: 'Smoke test endpoints (comma-separated):',
117
+ default: 'GET /health -> 200, GET /status -> 200',
118
+ },
119
+ ]);
120
+ targets.api = {
121
+ baseUrl: apiAnswers.apiUrl,
122
+ smoke: apiAnswers.smokeTests.split(',').map((s) => s.trim()),
123
+ };
124
+ }
125
+ if (gates.includes('ui') || gates.includes('a11y')) {
126
+ const uiAnswers = await inquirer.prompt([
127
+ {
128
+ type: 'input',
129
+ name: 'webUrl',
130
+ message: 'Web application URL:',
131
+ default: 'https://example.com',
132
+ validate: (input) => input.startsWith('http') || 'Must be a valid URL',
133
+ },
134
+ {
135
+ type: 'input',
136
+ name: 'pages',
137
+ message: 'Pages to test (comma-separated):',
138
+ default: 'https://example.com, https://example.com/about',
139
+ },
140
+ ]);
141
+ targets.web = {
142
+ baseUrl: uiAnswers.webUrl,
143
+ pages: uiAnswers.pages.split(',').map((s) => s.trim()),
144
+ };
145
+ }
146
+ // Build pack config
147
+ const pack = {
148
+ version: 1,
149
+ name: answers.name,
150
+ gates: gates,
151
+ targets,
152
+ };
153
+ // Add budgets if perf/a11y gates enabled
154
+ if (gates.includes('perf') || gates.includes('a11y')) {
155
+ pack.budgets = {};
156
+ if (gates.includes('perf')) {
157
+ pack.budgets.perf_p95_ms = 2000;
158
+ }
159
+ if (gates.includes('a11y')) {
160
+ pack.budgets.a11y_min = 90;
161
+ }
162
+ }
163
+ // Add security config if security gates enabled
164
+ if (gates.some((g) => ['sast', 'dast', 'secrets', 'deps'].includes(g))) {
165
+ pack.security = {};
166
+ if (gates.includes('sast')) {
167
+ pack.security.sast = {
168
+ max_critical: 0,
169
+ max_high: 3,
170
+ };
171
+ }
172
+ if (gates.includes('dast')) {
173
+ pack.security.dast = {
174
+ max_high: 5,
175
+ };
176
+ }
177
+ }
178
+ return pack;
179
+ }
180
+ /**
181
+ * Generate pack from template
182
+ */
183
+ function generateFromTemplate(templateKey, name) {
184
+ const template = TEMPLATES[templateKey];
185
+ if (!template) {
186
+ throw new Error(`Unknown template: ${templateKey}`);
187
+ }
188
+ const pack = {
189
+ version: 1,
190
+ name: name || `${templateKey}-tests`,
191
+ gates: template.gates,
192
+ targets: {},
193
+ };
194
+ // Add default targets based on gates
195
+ if (template.gates.includes('api_smoke')) {
196
+ pack.targets.api = {
197
+ baseUrl: 'https://api.example.com',
198
+ smoke: [
199
+ 'GET /health -> 200',
200
+ 'GET /status -> 200',
201
+ ],
202
+ };
203
+ }
204
+ if (template.gates.includes('ui') || template.gates.includes('a11y')) {
205
+ pack.targets.web = {
206
+ baseUrl: 'https://example.com',
207
+ pages: [
208
+ 'https://example.com',
209
+ ],
210
+ };
211
+ }
212
+ // Add budgets
213
+ if (template.gates.includes('perf') || template.gates.includes('a11y')) {
214
+ pack.budgets = {};
215
+ if (template.gates.includes('perf')) {
216
+ pack.budgets.perf_p95_ms = 2000;
217
+ }
218
+ if (template.gates.includes('a11y')) {
219
+ pack.budgets.a11y_min = 90;
220
+ }
221
+ }
222
+ // Add security config
223
+ if (template.gates.some((g) => ['sast', 'dast', 'secrets', 'deps'].includes(g))) {
224
+ pack.security = {};
225
+ if (template.gates.includes('sast')) {
226
+ pack.security.sast = {
227
+ max_critical: 0,
228
+ max_high: 3,
229
+ };
230
+ }
231
+ if (template.gates.includes('dast')) {
232
+ pack.security.dast = {
233
+ max_high: 5,
234
+ };
235
+ }
236
+ }
237
+ return pack;
238
+ }
239
+ /**
240
+ * Main init command
241
+ */
242
+ export async function initCommand(options = {}) {
243
+ try {
244
+ console.log(chalk.bold.cyan('\n🚀 QA360 Pack Generator\n'));
245
+ // Determine output file
246
+ const outputFile = options.output
247
+ ? resolve(options.output)
248
+ : join(process.cwd(), 'qa360.yml');
249
+ // Check if file exists
250
+ if (existsSync(outputFile) && !options.force) {
251
+ const overwrite = await inquirer.prompt([
252
+ {
253
+ type: 'confirm',
254
+ name: 'overwrite',
255
+ message: `File ${outputFile} already exists. Overwrite?`,
256
+ default: false,
257
+ },
258
+ ]);
259
+ if (!overwrite.overwrite) {
260
+ console.log(chalk.yellow('\n⚠️ Aborted. Use --force to overwrite.'));
261
+ return;
262
+ }
263
+ }
264
+ // Generate pack config
265
+ let pack;
266
+ if (options.template) {
267
+ // Use template directly
268
+ pack = generateFromTemplate(options.template);
269
+ console.log(chalk.green(`✅ Using template: ${TEMPLATES[options.template]?.name || options.template}`));
270
+ }
271
+ else if (options.yes) {
272
+ // Use default template (api-basic)
273
+ pack = generateFromTemplate('api-basic');
274
+ console.log(chalk.green('✅ Using default template: API Basic'));
275
+ }
276
+ else {
277
+ // Interactive mode
278
+ pack = await promptForConfig();
279
+ }
280
+ // Convert to YAML
281
+ const yaml = dump(pack, {
282
+ indent: 2,
283
+ lineWidth: 120,
284
+ noRefs: true,
285
+ });
286
+ // Ensure directory exists
287
+ const dir = resolve(outputFile, '..');
288
+ if (!existsSync(dir)) {
289
+ mkdirSync(dir, { recursive: true });
290
+ }
291
+ // Write file
292
+ writeFileSync(outputFile, yaml, 'utf-8');
293
+ console.log(chalk.green.bold('\n✅ Pack created successfully!'));
294
+ console.log(chalk.gray(`\n📄 File: ${outputFile}`));
295
+ console.log(chalk.gray(`📋 Gates: ${pack.gates?.join(', ')}`));
296
+ console.log(chalk.cyan('\n📚 Next steps:'));
297
+ console.log(chalk.gray(' 1. Edit the pack file to customize your tests'));
298
+ console.log(chalk.gray(' 2. Run: qa360 run'));
299
+ console.log(chalk.gray(' 3. View results: qa360 verify .qa360/runs/\n'));
300
+ }
301
+ catch (error) {
302
+ console.error(chalk.red('\n❌ Init failed:'));
303
+ console.error(chalk.red(` ${error instanceof Error ? error.message : 'Unknown error'}`));
304
+ process.exit(1);
305
+ }
306
+ }
307
+ export default initCommand;
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'),
16
16
  const version = packageJson.version;
17
17
  import { doctorCommand } from './commands/doctor.js';
18
18
  import { askCommand } from './commands/ask.js';
19
+ import { initCommand } from './commands/init.js';
19
20
  import { runCommand } from './commands/run.js';
20
21
  import { reportCommand } from './commands/report.js';
21
22
  import { verifyCommand } from './commands/verify.js';
@@ -37,6 +38,16 @@ program
37
38
  .action(async (options) => {
38
39
  await doctorCommand(options);
39
40
  });
41
+ program
42
+ .command('init')
43
+ .description('Generate pack.yml interactively')
44
+ .option('--template <name>', 'Use template: api-basic, ui-basic, fullstack, security, complete')
45
+ .option('--output <file>', 'Output file path', 'qa360.yml')
46
+ .option('--force', 'Overwrite existing file')
47
+ .option('-y, --yes', 'Skip prompts and use defaults')
48
+ .action(async (options) => {
49
+ await initCommand(options);
50
+ });
40
51
  program
41
52
  .command('ask [query]')
42
53
  .description('Natural language test requests - generates pack.yml')
@@ -0,0 +1,122 @@
1
+ # QA360 Examples
2
+
3
+ This directory contains example pack files for different testing scenarios.
4
+
5
+ ## Quick Start
6
+
7
+ Copy an example to your project:
8
+
9
+ ```bash
10
+ # Copy API basic example
11
+ cp examples/api-basic.yml qa360.yml
12
+
13
+ # Edit and customize
14
+ vim qa360.yml
15
+
16
+ # Run tests
17
+ qa360 run
18
+ ```
19
+
20
+ ## Available Examples
21
+
22
+ ### 1. **api-basic.yml** - API Smoke Tests
23
+ Simple REST/GraphQL health checks.
24
+
25
+ **Gates**: `api_smoke`
26
+
27
+ **Use case**: Verify API endpoints are responding correctly
28
+
29
+ ```bash
30
+ qa360 run examples/api-basic.yml
31
+ ```
32
+
33
+ ---
34
+
35
+ ### 2. **ui-basic.yml** - UI/E2E Tests
36
+ Basic browser automation tests.
37
+
38
+ **Gates**: `ui`
39
+
40
+ **Use case**: Test web pages load correctly
41
+
42
+ ```bash
43
+ qa360 run examples/ui-basic.yml
44
+ ```
45
+
46
+ ---
47
+
48
+ ### 3. **fullstack.yml** - Full Stack Tests
49
+ API + UI + Performance testing.
50
+
51
+ **Gates**: `api_smoke`, `ui`, `perf`
52
+
53
+ **Use case**: Complete application testing with Docker Compose integration
54
+
55
+ ```bash
56
+ qa360 run examples/fullstack.yml
57
+ ```
58
+
59
+ ---
60
+
61
+ ### 4. **security.yml** - Security Suite
62
+ Comprehensive security scanning.
63
+
64
+ **Gates**: `sast`, `dast`, `secrets`, `deps`
65
+
66
+ **Use case**: Security audit with vulnerability scanning
67
+
68
+ ```bash
69
+ qa360 run examples/security.yml
70
+ ```
71
+
72
+ ---
73
+
74
+ ### 5. **accessibility.yml** - Accessibility Tests
75
+ WCAG compliance testing.
76
+
77
+ **Gates**: `ui`, `a11y`
78
+
79
+ **Use case**: Ensure website meets accessibility standards
80
+
81
+ ```bash
82
+ qa360 run examples/accessibility.yml
83
+ ```
84
+
85
+ ---
86
+
87
+ ### 6. **complete.yml** - Complete Test Suite
88
+ All quality gates enabled.
89
+
90
+ **Gates**: All (8 gates)
91
+
92
+ **Use case**: Comprehensive quality assurance for production-ready applications
93
+
94
+ ```bash
95
+ qa360 run examples/complete.yml
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Interactive Generator
101
+
102
+ Generate a custom pack with:
103
+
104
+ ```bash
105
+ qa360 init
106
+ ```
107
+
108
+ This will walk you through creating a pack file tailored to your needs.
109
+
110
+ ## Customization
111
+
112
+ All examples use placeholder URLs. Replace with your actual endpoints:
113
+
114
+ - `https://api.example.com` → Your API URL
115
+ - `https://example.com` → Your web application URL
116
+ - `http://localhost:3000` → Your local dev server
117
+
118
+ ## Learn More
119
+
120
+ - [Pack Schema Documentation](https://github.com/xyqotech/qa360/blob/main/docs/pack-schema.md)
121
+ - [Quality Gates Reference](https://github.com/xyqotech/qa360/blob/main/docs/gates.md)
122
+ - [Full Documentation](https://github.com/xyqotech/qa360/blob/main/docs/README.md)
@@ -0,0 +1,25 @@
1
+ # QA360 Example: Accessibility Tests
2
+ # WCAG compliance and accessibility testing
3
+
4
+ version: 1
5
+ name: "Accessibility Tests"
6
+
7
+ gates:
8
+ - ui
9
+ - a11y
10
+
11
+ targets:
12
+ web:
13
+ baseUrl: "https://example.com"
14
+ pages:
15
+ - "https://example.com"
16
+ - "https://example.com/about"
17
+ - "https://example.com/contact"
18
+
19
+ # Accessibility budget
20
+ budgets:
21
+ a11y_min: 90 # Minimum accessibility score (0-100)
22
+
23
+ execution:
24
+ timeout: 60000
25
+ max_retries: 1
@@ -0,0 +1,23 @@
1
+ # QA360 Example: API Basic
2
+ # Simple API smoke tests for REST/GraphQL endpoints
3
+
4
+ version: 1
5
+ name: "API Health Check"
6
+
7
+ gates:
8
+ - api_smoke
9
+
10
+ targets:
11
+ api:
12
+ baseUrl: "https://httpbin.org"
13
+ smoke:
14
+ - "GET /status/200 -> 200"
15
+ - "GET /json -> 200"
16
+ - "GET /uuid -> 200"
17
+ - "POST /post -> 200"
18
+
19
+ # Optional: Execution settings
20
+ execution:
21
+ timeout: 30000 # 30 seconds
22
+ max_retries: 2
23
+ on_failure: continue # or 'stop'
@@ -0,0 +1,59 @@
1
+ # QA360 Example: Complete Test Suite
2
+ # All quality gates enabled - comprehensive quality assurance
3
+
4
+ version: 1
5
+ name: "Complete QA Suite"
6
+
7
+ gates:
8
+ - api_smoke # API health checks
9
+ - ui # Browser E2E tests
10
+ - a11y # Accessibility (WCAG)
11
+ - perf # Performance testing
12
+ - sast # Static security analysis
13
+ - dast # Dynamic security testing
14
+ - secrets # Credentials scanning
15
+ - deps # Dependency vulnerabilities
16
+
17
+ targets:
18
+ api:
19
+ baseUrl: "https://api.example.com"
20
+ smoke:
21
+ - "GET /health -> 200"
22
+ - "GET /status -> 200"
23
+ - "POST /login -> 200"
24
+
25
+ web:
26
+ baseUrl: "https://example.com"
27
+ pages:
28
+ - "https://example.com"
29
+ - "https://example.com/dashboard"
30
+
31
+ # Quality budgets
32
+ budgets:
33
+ perf_p95_ms: 2000 # P95 latency budget
34
+ a11y_min: 90 # Minimum accessibility score
35
+
36
+ # Security thresholds
37
+ security:
38
+ sast:
39
+ max_critical: 0
40
+ max_high: 3
41
+
42
+ dast:
43
+ max_high: 5
44
+
45
+ # Docker Compose integration
46
+ hooks:
47
+ beforeAll:
48
+ - compose: up
49
+ timeout: 30000
50
+ - wait_on: http://localhost:3000
51
+
52
+ afterAll:
53
+ - compose: down
54
+
55
+ # Execution settings
56
+ execution:
57
+ timeout: 120000 # 2 minutes
58
+ max_retries: 2
59
+ on_failure: continue
@@ -0,0 +1,42 @@
1
+ # QA360 Example: Full Stack
2
+ # Complete testing suite with API, UI, and Performance
3
+
4
+ version: 1
5
+ name: "Full Stack Tests"
6
+
7
+ gates:
8
+ - api_smoke
9
+ - ui
10
+ - perf
11
+
12
+ targets:
13
+ api:
14
+ baseUrl: "https://httpbin.org"
15
+ smoke:
16
+ - "GET /status/200 -> 200"
17
+ - "GET /json -> 200"
18
+ - "POST /post -> 200"
19
+
20
+ web:
21
+ baseUrl: "https://example.com"
22
+ pages:
23
+ - "https://example.com"
24
+
25
+ # Performance budgets
26
+ budgets:
27
+ perf_p95_ms: 2000 # P95 latency must be < 2000ms
28
+
29
+ # Hooks for local development
30
+ hooks:
31
+ beforeAll:
32
+ - compose: up
33
+ timeout: 30000
34
+ - wait_on: http://localhost:3000
35
+
36
+ afterAll:
37
+ - compose: down
38
+
39
+ execution:
40
+ timeout: 60000
41
+ max_retries: 2
42
+ on_failure: continue
@@ -0,0 +1,32 @@
1
+ # QA360 Example: Security Suite
2
+ # Comprehensive security testing (SAST, DAST, secrets, dependencies)
3
+
4
+ version: 1
5
+ name: "Security Test Suite"
6
+
7
+ gates:
8
+ - sast # Static Application Security Testing
9
+ - dast # Dynamic Application Security Testing
10
+ - secrets # Secrets detection
11
+ - deps # Dependency vulnerability scanning
12
+
13
+ targets:
14
+ api:
15
+ baseUrl: "https://api.example.com"
16
+
17
+ web:
18
+ baseUrl: "https://example.com"
19
+
20
+ # Security thresholds
21
+ security:
22
+ sast:
23
+ max_critical: 0 # Zero critical vulnerabilities allowed
24
+ max_high: 3 # Maximum 3 high-severity issues
25
+
26
+ dast:
27
+ max_high: 5 # Maximum 5 high-severity runtime issues
28
+
29
+ # Execution settings
30
+ execution:
31
+ timeout: 120000 # Security scans can take longer
32
+ on_failure: stop # Stop on first critical finding
@@ -0,0 +1,20 @@
1
+ # QA360 Example: UI Basic
2
+ # Basic UI/E2E browser tests
3
+
4
+ version: 1
5
+ name: "UI Browser Tests"
6
+
7
+ gates:
8
+ - ui
9
+
10
+ targets:
11
+ web:
12
+ baseUrl: "https://example.com"
13
+ pages:
14
+ - "https://example.com"
15
+ - "https://example.com/about"
16
+
17
+ # Optional: Browser configuration
18
+ execution:
19
+ timeout: 60000
20
+ max_retries: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qa360",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "QA360 Proof CLI - Quality as Cryptographic Proof",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,8 +27,7 @@
27
27
  "prepublishOnly": "npm run build:bundle && sed -i.bak 's/\"qa360-core\": \"workspace:\\*\",//g' package.json && rm -f package.json.bak",
28
28
  "postpublish": "git checkout package.json 2>/dev/null || true",
29
29
  "publish:dry": "npm run build:bundle && sed -i.bak 's/\"qa360-core\": \"workspace:\\*\",//g' package.json && npm publish --dry-run; git checkout package.json",
30
- "publish:real": "npm run build:bundle && npm publish --access public",
31
- "postinstall": "npx playwright install chromium --with-deps 2>/dev/null || echo 'Playwright browsers will be installed on first run'"
30
+ "publish:real": "npm run build:bundle && npm publish --access public"
32
31
  },
33
32
  "dependencies": {
34
33
  "@playwright/test": "^1.49.0",