qa-flowkit 0.4.0-alpha.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/.qa-ai/adapters/aider/.aider/README.md +25 -0
- package/.qa-ai/adapters/aider/.aider.conf.yml +6 -0
- package/.qa-ai/adapters/claude/agents/qa-workflow-orchestrator.md +18 -0
- package/.qa-ai/adapters/claude/commands/qa-add-tests.md +42 -0
- package/.qa-ai/adapters/claude/commands/qa-automation-plan.md +43 -0
- package/.qa-ai/adapters/claude/commands/qa-clean.md +42 -0
- package/.qa-ai/adapters/claude/commands/qa-config.md +51 -0
- package/.qa-ai/adapters/claude/commands/qa-coverage.md +46 -0
- package/.qa-ai/adapters/claude/commands/qa-doctor.md +11 -0
- package/.qa-ai/adapters/claude/commands/qa-full-flow.md +59 -0
- package/.qa-ai/adapters/claude/commands/qa-gate.md +36 -0
- package/.qa-ai/adapters/claude/commands/qa-help.md +30 -0
- package/.qa-ai/adapters/claude/commands/qa-init.md +70 -0
- package/.qa-ai/adapters/claude/commands/qa-status.md +56 -0
- package/.qa-ai/adapters/claude/commands/qa-update-tests.md +47 -0
- package/.qa-ai/adapters/claude/commands/qa-validate-features.md +36 -0
- package/.qa-ai/adapters/cline/.cline/README.md +25 -0
- package/.qa-ai/adapters/cline/.clinerules +9 -0
- package/.qa-ai/adapters/codex/README.md +44 -0
- package/.qa-ai/adapters/codex/prompts/implement-project.md +15 -0
- package/.qa-ai/adapters/continue/README.md +26 -0
- package/.qa-ai/adapters/continue/checks/qa-feature-conventions.md +15 -0
- package/.qa-ai/adapters/gemini/GEMINI.md +40 -0
- package/.qa-ai/adapters/generic/AGENTS.md +100 -0
- package/.qa-ai/adapters/goose/recipes/qa-flowkit.yaml +20 -0
- package/.qa-ai/adapters/opencode/README.md +57 -0
- package/.qa-ai/adapters/opencode/agents/qa-workflow.md +18 -0
- package/.qa-ai/adapters/opencode/commands/qa-add-tests.md +42 -0
- package/.qa-ai/adapters/opencode/commands/qa-automation-plan.md +43 -0
- package/.qa-ai/adapters/opencode/commands/qa-clean.md +42 -0
- package/.qa-ai/adapters/opencode/commands/qa-config.md +51 -0
- package/.qa-ai/adapters/opencode/commands/qa-coverage.md +46 -0
- package/.qa-ai/adapters/opencode/commands/qa-doctor.md +13 -0
- package/.qa-ai/adapters/opencode/commands/qa-full-flow.md +59 -0
- package/.qa-ai/adapters/opencode/commands/qa-gate.md +36 -0
- package/.qa-ai/adapters/opencode/commands/qa-help.md +30 -0
- package/.qa-ai/adapters/opencode/commands/qa-init.md +70 -0
- package/.qa-ai/adapters/opencode/commands/qa-status.md +56 -0
- package/.qa-ai/adapters/opencode/commands/qa-update-tests.md +47 -0
- package/.qa-ai/adapters/opencode/commands/qa-validate-features.md +36 -0
- package/.qa-ai/agents/README.md +39 -0
- package/.qa-ai/agents/api-testing-agent.md +73 -0
- package/.qa-ai/agents/automation-feasibility-agent.md +128 -0
- package/.qa-ai/agents/gherkin-test-design-agent.md +110 -0
- package/.qa-ai/agents/jira-task-agent.md +92 -0
- package/.qa-ai/agents/pr-agent.md +101 -0
- package/.qa-ai/agents/qa-context-intake-agent.md +75 -0
- package/.qa-ai/agents/qa-workflow-orchestrator.md +113 -0
- package/.qa-ai/agents/release-gate-agent.md +50 -0
- package/.qa-ai/agents/requirements-intake-agent.md +79 -0
- package/.qa-ai/agents/requirements-normalization-agent.md +80 -0
- package/.qa-ai/agents/specialists/available/appium.md +59 -0
- package/.qa-ai/agents/specialists/available/cypress.md +68 -0
- package/.qa-ai/agents/specialists/available/generic-test-design.md +117 -0
- package/.qa-ai/agents/specialists/available/jira.md +108 -0
- package/.qa-ai/agents/specialists/available/karate.md +97 -0
- package/.qa-ai/agents/specialists/available/playwright-api.md +87 -0
- package/.qa-ai/agents/specialists/available/playwright-ui.md +87 -0
- package/.qa-ai/agents/specialists/available/postman.md +108 -0
- package/.qa-ai/agents/specialists/available/rest-assured.md +103 -0
- package/.qa-ai/agents/specialists/available/selenium.md +91 -0
- package/.qa-ai/agents/specialists/available/testrail.md +85 -0
- package/.qa-ai/agents/specialists/available/webdriverio.md +81 -0
- package/.qa-ai/agents/test-design-system-agent.md +33 -0
- package/.qa-ai/agents/testrail-coverage-agent.md +84 -0
- package/.qa-ai/agents/testrail-sync-agent.md +96 -0
- package/.qa-ai/agents/webdriverio-implementation-agent.md +84 -0
- package/.qa-ai/presets/manual-only.yaml +65 -0
- package/.qa-ai/presets/selenium-jest-browserstack.yaml +72 -0
- package/.qa-ai/presets/webdriverio-playwright-api.yaml +85 -0
- package/.qa-ai/rules/api-testing.rules.md +7 -0
- package/.qa-ai/rules/approval.rules.md +8 -0
- package/.qa-ai/rules/automation.rules.md +7 -0
- package/.qa-ai/rules/gherkin.rules.md +12 -0
- package/.qa-ai/rules/testrail.rules.md +10 -0
- package/.qa-ai/rules/webdriverio.rules.md +9 -0
- package/.qa-ai/scripts/bootstrap-agent-adapters.mjs +127 -0
- package/.qa-ai/scripts/clean.mjs +243 -0
- package/.qa-ai/scripts/config.mjs +202 -0
- package/.qa-ai/scripts/doctor.mjs +383 -0
- package/.qa-ai/scripts/init.mjs +447 -0
- package/.qa-ai/scripts/lib/markdown-table.mjs +76 -0
- package/.qa-ai/scripts/lib/project-config.mjs +184 -0
- package/.qa-ai/scripts/lib/qa-next-steps.mjs +578 -0
- package/.qa-ai/scripts/lib/release-gate.mjs +66 -0
- package/.qa-ai/scripts/lib/test-design.mjs +92 -0
- package/.qa-ai/scripts/lib/test-management-mapping.mjs +73 -0
- package/.qa-ai/scripts/lib/utils.mjs +331 -0
- package/.qa-ai/scripts/qa-help.mjs +44 -0
- package/.qa-ai/scripts/smoke-npm-pack.mjs +187 -0
- package/.qa-ai/scripts/smoke-test.mjs +465 -0
- package/.qa-ai/scripts/sync-agent-adapters.mjs +121 -0
- package/.qa-ai/scripts/test-validators.mjs +334 -0
- package/.qa-ai/scripts/validate-active-specialists.mjs +106 -0
- package/.qa-ai/scripts/validate-features.mjs +277 -0
- package/.qa-ai/scripts/validate-release-gate.mjs +105 -0
- package/.qa-ai/scripts/validate-sync-plan.mjs +186 -0
- package/.qa-ai/scripts/validate-target.mjs +104 -0
- package/.qa-ai/scripts/validate-test-design.mjs +117 -0
- package/.qa-ai/scripts/validate-traceability.mjs +183 -0
- package/.qa-ai/templates/automation-feasibility-report.template.md +21 -0
- package/.qa-ai/templates/automation-implementation-plan.template.md +23 -0
- package/.qa-ai/templates/feature.template +13 -0
- package/.qa-ai/templates/jira-automation-task.template.md +25 -0
- package/.qa-ai/templates/pr-template.md +60 -0
- package/.qa-ai/templates/release-gate.template.yaml +16 -0
- package/.qa-ai/templates/requirement-analysis.template.md +17 -0
- package/.qa-ai/templates/test-design-proposal.template.md +26 -0
- package/.qa-ai/templates/test-design-system.template.md +15 -0
- package/.qa-ai/templates/test-management-mapping.template.json +18 -0
- package/.qa-ai/templates/testrail-coverage-analysis.template.md +17 -0
- package/.qa-ai/templates/testrail-sync-plan.template.md +22 -0
- package/.qa-ai/templates/traceability-matrix.template.md +4 -0
- package/.qa-ai/workflows/automation-analysis.md +23 -0
- package/.qa-ai/workflows/cleanup.md +52 -0
- package/.qa-ai/workflows/context-intake.md +66 -0
- package/.qa-ai/workflows/full-flow.md +55 -0
- package/.qa-ai/workflows/implementation.md +24 -0
- package/.qa-ai/workflows/intake.md +3 -0
- package/.qa-ai/workflows/pr.md +3 -0
- package/.qa-ai/workflows/release-gate.md +22 -0
- package/.qa-ai/workflows/test-design-system.md +33 -0
- package/.qa-ai/workflows/test-design.md +23 -0
- package/.qa-ai/workflows/testrail-sync.md +23 -0
- package/CHANGELOG.md +108 -0
- package/CODE_OF_CONDUCT.md +11 -0
- package/CONTRIBUTING.md +39 -0
- package/LICENSE +21 -0
- package/README.es.md +602 -0
- package/README.md +633 -0
- package/ROADMAP.md +107 -0
- package/SECURITY.md +18 -0
- package/bin/qa-flowkit.mjs +214 -0
- package/docs/qa-ai/agent-compatibility.md +100 -0
- package/docs/qa-ai/architecture.md +130 -0
- package/docs/qa-ai/backlog.md +393 -0
- package/docs/qa-ai/cleanup.md +104 -0
- package/docs/qa-ai/customizing-agents.md +148 -0
- package/docs/qa-ai/getting-started.md +385 -0
- package/docs/qa-ai/implementation-guide-for-codex.md +210 -0
- package/docs/qa-ai/npm-migration-plan.md +50 -0
- package/docs/qa-ai/open-source-release-checklist.md +17 -0
- package/docs/qa-ai/qa-help.md +76 -0
- package/docs/qa-ai/release-gate.md +60 -0
- package/docs/qa-ai/terminal-transcripts.md +316 -0
- package/docs/qa-ai/test-design-dual-mode.md +75 -0
- package/docs/qa-ai/troubleshooting.md +740 -0
- package/docs/qa-ai/workflow.md +147 -0
- package/package.json +72 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { validateTestDesignProposal, validateTestDesignSystem } from './lib/test-design.mjs';
|
|
3
|
+
import {
|
|
4
|
+
getConfigValue,
|
|
5
|
+
loadQaAiConfig,
|
|
6
|
+
logHeader,
|
|
7
|
+
parseArgs,
|
|
8
|
+
pathExists,
|
|
9
|
+
readText,
|
|
10
|
+
resolveRepoPath
|
|
11
|
+
} from './lib/utils.mjs';
|
|
12
|
+
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const args = parseArgs(process.argv);
|
|
15
|
+
|
|
16
|
+
function printHelp() {
|
|
17
|
+
console.log(`Usage: node .qa-ai/scripts/validate-test-design.mjs [options]
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--system-path <file> Override system test design path
|
|
21
|
+
--proposal-path <file> Override per-RF proposal path
|
|
22
|
+
--allow-missing Return success when files are missing
|
|
23
|
+
--require-rf-id Fail when RF IDs are not mentioned in the proposal
|
|
24
|
+
--help Show this help
|
|
25
|
+
|
|
26
|
+
Validates qa-ai-output/test-design-system.md and test-design-proposal.md structure.
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function validateFile(cwd, filePath, validator, options = {}) {
|
|
31
|
+
const absolute = resolveRepoPath(cwd, filePath, { label: 'test design file' });
|
|
32
|
+
if (!await pathExists(absolute)) {
|
|
33
|
+
if (options.allowMissing) {
|
|
34
|
+
return { ok: true, skipped: true, path: filePath, errors: [] };
|
|
35
|
+
}
|
|
36
|
+
return { ok: false, skipped: false, path: filePath, errors: [`Test design file not found: ${filePath}`] };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const content = await readText(absolute);
|
|
40
|
+
const result = validator(content, options.validatorOptions || {});
|
|
41
|
+
const errors = result.errors.map((error) => `${filePath}: ${error}`);
|
|
42
|
+
return { ok: result.ok, skipped: false, path: filePath, errors };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function validateTestDesignArtifacts(cwd, options = {}) {
|
|
46
|
+
const configInfo = await loadQaAiConfig(cwd);
|
|
47
|
+
const config = configInfo.data || {};
|
|
48
|
+
const systemPath =
|
|
49
|
+
options.systemPath ||
|
|
50
|
+
getConfigValue(config, 'testDesign.systemPath', 'qa-ai-output/test-design-system.md');
|
|
51
|
+
const proposalPath =
|
|
52
|
+
options.proposalPath ||
|
|
53
|
+
getConfigValue(config, 'testDesign.proposalPath', 'qa-ai-output/test-design-proposal.md');
|
|
54
|
+
|
|
55
|
+
const allowMissing = Boolean(options.allowMissing);
|
|
56
|
+
const validatorOptions = {
|
|
57
|
+
requireOfficialRfId: Boolean(options.requireRfId)
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const system = await validateFile(cwd, systemPath, validateTestDesignSystem, {
|
|
61
|
+
allowMissing,
|
|
62
|
+
validatorOptions
|
|
63
|
+
});
|
|
64
|
+
const proposal = await validateFile(cwd, proposalPath, validateTestDesignProposal, {
|
|
65
|
+
allowMissing,
|
|
66
|
+
validatorOptions
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const errors = [...system.errors, ...proposal.errors];
|
|
70
|
+
return {
|
|
71
|
+
ok: errors.length === 0,
|
|
72
|
+
system,
|
|
73
|
+
proposal,
|
|
74
|
+
errors
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function main() {
|
|
79
|
+
if (args.help) {
|
|
80
|
+
printHelp();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
logHeader('QA AI test design validator');
|
|
85
|
+
const result = await validateTestDesignArtifacts(cwd, {
|
|
86
|
+
systemPath: args['system-path'],
|
|
87
|
+
proposalPath: args['proposal-path'],
|
|
88
|
+
allowMissing: Boolean(args['allow-missing']),
|
|
89
|
+
requireRfId: Boolean(args['require-rf-id'])
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (result.system.skipped) {
|
|
93
|
+
console.log('SKIP - system test design file not found.');
|
|
94
|
+
} else if (result.system.ok) {
|
|
95
|
+
console.log(`PASS - ${result.system.path}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (result.proposal.skipped) {
|
|
99
|
+
console.log('SKIP - per-RF test design proposal not found.');
|
|
100
|
+
} else if (result.proposal.ok) {
|
|
101
|
+
console.log(`PASS - ${result.proposal.path}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (result.errors.length > 0) {
|
|
105
|
+
for (const error of result.errors) {
|
|
106
|
+
console.error(`FAIL - ${error}`);
|
|
107
|
+
}
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log('\nVALID - test design artifacts passed validation.');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main().catch((error) => {
|
|
115
|
+
console.error(error);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { normalizeColumn, parseMarkdownTable } from './lib/markdown-table.mjs';
|
|
5
|
+
import {
|
|
6
|
+
getConfigValue,
|
|
7
|
+
listFilesRecursive,
|
|
8
|
+
loadQaAiConfig,
|
|
9
|
+
logHeader,
|
|
10
|
+
parseArgs,
|
|
11
|
+
pathExists,
|
|
12
|
+
readText,
|
|
13
|
+
relativeTo,
|
|
14
|
+
resolveRepoPath
|
|
15
|
+
} from './lib/utils.mjs';
|
|
16
|
+
|
|
17
|
+
const cwd = process.cwd();
|
|
18
|
+
const args = parseArgs(process.argv);
|
|
19
|
+
const idPattern = /\b(?:RF|TC|TEST|QA)[-_ ]?[A-Z0-9]+\b/gi;
|
|
20
|
+
const caseIdPattern = /\b(?:TC|TEST|QA)[-_ ]?[A-Z0-9]+\b/gi;
|
|
21
|
+
const requiredColumns = [
|
|
22
|
+
'Requirement Source',
|
|
23
|
+
'RF',
|
|
24
|
+
'Feature File',
|
|
25
|
+
'Test Management Case ID',
|
|
26
|
+
'Type',
|
|
27
|
+
'Priority',
|
|
28
|
+
'Automation Status'
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function printHelp() {
|
|
32
|
+
console.log(`Usage: node .qa-ai/scripts/validate-traceability.mjs [options]
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
--path <file> Override configured traceability matrix path
|
|
36
|
+
--features <dir> Override configured feature root
|
|
37
|
+
--allow-empty Return success when no .feature files exist
|
|
38
|
+
--allow-missing Return success when the traceability matrix is missing
|
|
39
|
+
--help Show this help
|
|
40
|
+
|
|
41
|
+
Validates feature identifier coverage, traceability matrix table shape and duplicate test case or feature-file rows.
|
|
42
|
+
`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeId(value) {
|
|
46
|
+
return String(value || '').replace(/\s+/g, '-').toUpperCase();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function idsFromText(value) {
|
|
50
|
+
return [...String(value || '').matchAll(idPattern)].map((match) => normalizeId(match[0]));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function caseIdsFromText(value) {
|
|
54
|
+
return [...String(value || '').matchAll(caseIdPattern)].map((match) => normalizeId(match[0]));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function parseMatrix(content) {
|
|
58
|
+
const table = parseMarkdownTable(content, {
|
|
59
|
+
label: 'Traceability matrix',
|
|
60
|
+
requiredColumns
|
|
61
|
+
});
|
|
62
|
+
const errors = [...table.errors];
|
|
63
|
+
const rows = [];
|
|
64
|
+
for (const row of table.rows) {
|
|
65
|
+
const ids = [...new Set(idsFromText(row.cells.join(' ')))].sort();
|
|
66
|
+
const caseIds = [...new Set(caseIdsFromText(row.cells.join(' ')))].sort();
|
|
67
|
+
if (ids.length === 0) {
|
|
68
|
+
errors.push(`Line ${row.line}: row must include at least one RF/test identifier.`);
|
|
69
|
+
}
|
|
70
|
+
rows.push({ ...row, ids, caseIds });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { errors, rows, header: table.header };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function duplicateMatrixErrors(rows) {
|
|
77
|
+
const errors = [];
|
|
78
|
+
const byCaseId = new Map();
|
|
79
|
+
const byFeatureFile = new Map();
|
|
80
|
+
|
|
81
|
+
for (const row of rows) {
|
|
82
|
+
for (const id of row.caseIds) {
|
|
83
|
+
const current = byCaseId.get(id) || [];
|
|
84
|
+
current.push(row.line);
|
|
85
|
+
byCaseId.set(id, current);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const featureFile = String(row.values[normalizeColumn('Feature File')] || '').trim();
|
|
89
|
+
if (featureFile) {
|
|
90
|
+
const normalizedFeatureFile = featureFile.replaceAll('\\', '/').toLowerCase();
|
|
91
|
+
const current = byFeatureFile.get(normalizedFeatureFile) || [];
|
|
92
|
+
current.push(row.line);
|
|
93
|
+
byFeatureFile.set(normalizedFeatureFile, current);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const [id, lines] of byCaseId.entries()) {
|
|
98
|
+
if (lines.length > 1) errors.push(`Identifier ${id} appears in multiple traceability rows: ${lines.join(', ')}.`);
|
|
99
|
+
}
|
|
100
|
+
for (const [featureFile, lines] of byFeatureFile.entries()) {
|
|
101
|
+
if (lines.length > 1) errors.push(`Feature file ${featureFile} appears in multiple traceability rows: ${lines.join(', ')}.`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return errors;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function featureIds(featureRootPath) {
|
|
108
|
+
const files = await listFilesRecursive(featureRootPath, (filePath) => filePath.endsWith('.feature'));
|
|
109
|
+
const entries = [];
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
const content = await fs.readFile(file, 'utf8');
|
|
112
|
+
const ids = new Set([
|
|
113
|
+
...idsFromText(path.basename(file, '.feature')),
|
|
114
|
+
...idsFromText(content)
|
|
115
|
+
]);
|
|
116
|
+
entries.push({
|
|
117
|
+
file,
|
|
118
|
+
ids: [...ids].sort()
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return entries;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function main() {
|
|
125
|
+
if (args.help) {
|
|
126
|
+
printHelp();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
logHeader('QA AI traceability validator');
|
|
131
|
+
const configInfo = await loadQaAiConfig(cwd);
|
|
132
|
+
const featureRoot = args.features || getConfigValue(configInfo.data, 'gherkin.featurePath', 'features');
|
|
133
|
+
const matrixPath = args.path || getConfigValue(configInfo.data, 'traceability.matrixPath', 'qa-ai-output/traceability-matrix.md');
|
|
134
|
+
const featureRootPath = resolveRepoPath(cwd, featureRoot, { label: 'feature root' });
|
|
135
|
+
const matrixFilePath = resolveRepoPath(cwd, matrixPath, { label: 'traceability matrix' });
|
|
136
|
+
const features = await featureIds(featureRootPath);
|
|
137
|
+
|
|
138
|
+
if (features.length === 0) {
|
|
139
|
+
console.log(`No .feature files found under ${featureRoot}.`);
|
|
140
|
+
if (args['allow-empty']) return;
|
|
141
|
+
console.log('\nFAILED - no feature files found. Pass --allow-empty when this is expected.');
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!await pathExists(matrixFilePath)) {
|
|
146
|
+
console.log(`Traceability matrix not found at ${matrixPath}.`);
|
|
147
|
+
if (args['allow-missing']) return;
|
|
148
|
+
console.log('\nFAILED - create the traceability matrix or pass --allow-missing.');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const rawMatrixContent = await readText(matrixFilePath);
|
|
153
|
+
const matrix = parseMatrix(rawMatrixContent);
|
|
154
|
+
const matrixContent = normalizeId(rawMatrixContent);
|
|
155
|
+
const errors = [];
|
|
156
|
+
errors.push(...matrix.errors);
|
|
157
|
+
errors.push(...duplicateMatrixErrors(matrix.rows));
|
|
158
|
+
|
|
159
|
+
for (const feature of features) {
|
|
160
|
+
if (feature.ids.length === 0) {
|
|
161
|
+
errors.push(`${relativeTo(cwd, feature.file)} has no RF/test identifiers to trace.`);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
for (const id of feature.ids) {
|
|
165
|
+
if (!matrixContent.includes(id)) {
|
|
166
|
+
errors.push(`${relativeTo(cwd, feature.file)} identifier ${id} is missing from ${matrixPath}.`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (errors.length > 0) {
|
|
172
|
+
for (const error of errors) console.log(`[FAIL] ${error}`);
|
|
173
|
+
console.log(`\nFAILED - ${errors.length} traceability validation error(s).`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log(`[PASS] ${matrixPath} covers identifiers from ${features.length} feature file(s).`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
main().catch((error) => {
|
|
181
|
+
console.error(error);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Automation Feasibility Report
|
|
2
|
+
|
|
3
|
+
## Automatable tests
|
|
4
|
+
|
|
5
|
+
## Manual tests
|
|
6
|
+
|
|
7
|
+
## Partially automatable tests
|
|
8
|
+
|
|
9
|
+
## Blocked tests
|
|
10
|
+
|
|
11
|
+
## Required framework support
|
|
12
|
+
|
|
13
|
+
## Required test data
|
|
14
|
+
|
|
15
|
+
## Required selectors
|
|
16
|
+
|
|
17
|
+
## Required mocks/stubs
|
|
18
|
+
|
|
19
|
+
## Risks
|
|
20
|
+
|
|
21
|
+
## Proposed implementation
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Automation Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Tests to automate
|
|
4
|
+
|
|
5
|
+
## New files
|
|
6
|
+
|
|
7
|
+
## Existing files to modify
|
|
8
|
+
|
|
9
|
+
## Page objects
|
|
10
|
+
|
|
11
|
+
## Helpers
|
|
12
|
+
|
|
13
|
+
## Fixtures and data
|
|
14
|
+
|
|
15
|
+
## API clients
|
|
16
|
+
|
|
17
|
+
## Risks
|
|
18
|
+
|
|
19
|
+
## Execution plan
|
|
20
|
+
|
|
21
|
+
## Approval request
|
|
22
|
+
|
|
23
|
+
Do you approve implementing the proposed automation changes?
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@priority:<critical|high|medium|low> @type:<functional|integration|e2e|api|accessibility|compatibility|manual> @manual:<true|false>
|
|
2
|
+
Feature: <RF-ID> - <Feature title>
|
|
3
|
+
As a <role>
|
|
4
|
+
I want <capability>
|
|
5
|
+
So that <business value>
|
|
6
|
+
|
|
7
|
+
Acceptance Criteria:
|
|
8
|
+
- <acceptance criterion>
|
|
9
|
+
|
|
10
|
+
Scenario: <RF-ID> - <Scenario title>
|
|
11
|
+
Given <precondition>
|
|
12
|
+
When <action>
|
|
13
|
+
Then <expected result>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Automation Task Template
|
|
2
|
+
|
|
3
|
+
## Title
|
|
4
|
+
|
|
5
|
+
Automate QA test cases for <RF-ID> - <Feature name>
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
|
|
9
|
+
The following QA test cases have been identified as technically automatable but could not be implemented during the current flow.
|
|
10
|
+
|
|
11
|
+
## Test cases
|
|
12
|
+
|
|
13
|
+
- <Test ID> - <Title>
|
|
14
|
+
|
|
15
|
+
## Reason
|
|
16
|
+
|
|
17
|
+
- Missing stable test data / environment / credentials / framework support.
|
|
18
|
+
|
|
19
|
+
## Acceptance Criteria
|
|
20
|
+
|
|
21
|
+
- Automated tests are implemented using the configured framework.
|
|
22
|
+
- Tests follow repository conventions.
|
|
23
|
+
- Tests are linked to corresponding test management cases where available.
|
|
24
|
+
- Tests can be executed locally or in CI.
|
|
25
|
+
- Traceability matrix is updated.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Summary
|
|
2
|
+
|
|
3
|
+
This PR adds QA test design and automation coverage for <Requirement / RF>.
|
|
4
|
+
|
|
5
|
+
## Sources
|
|
6
|
+
|
|
7
|
+
- Requirement source:
|
|
8
|
+
- PRD:
|
|
9
|
+
- Supporting documentation:
|
|
10
|
+
- Attachments:
|
|
11
|
+
|
|
12
|
+
## Test Design
|
|
13
|
+
|
|
14
|
+
Added feature files:
|
|
15
|
+
|
|
16
|
+
-
|
|
17
|
+
|
|
18
|
+
## Test Management
|
|
19
|
+
|
|
20
|
+
Created cases:
|
|
21
|
+
|
|
22
|
+
-
|
|
23
|
+
|
|
24
|
+
Reused cases:
|
|
25
|
+
|
|
26
|
+
-
|
|
27
|
+
|
|
28
|
+
Cases requiring future review:
|
|
29
|
+
|
|
30
|
+
-
|
|
31
|
+
|
|
32
|
+
## Automation
|
|
33
|
+
|
|
34
|
+
Automated tests added:
|
|
35
|
+
|
|
36
|
+
-
|
|
37
|
+
|
|
38
|
+
Manual tests:
|
|
39
|
+
|
|
40
|
+
-
|
|
41
|
+
|
|
42
|
+
Pending automation:
|
|
43
|
+
|
|
44
|
+
-
|
|
45
|
+
|
|
46
|
+
## Traceability
|
|
47
|
+
|
|
48
|
+
Updated:
|
|
49
|
+
|
|
50
|
+
- `qa-ai-output/traceability-matrix.md`
|
|
51
|
+
|
|
52
|
+
## Execution status
|
|
53
|
+
|
|
54
|
+
- Executed locally: Yes/No
|
|
55
|
+
- Executed in CI: Yes/No
|
|
56
|
+
- First manual execution required: Yes/No
|
|
57
|
+
|
|
58
|
+
## Risks / Notes
|
|
59
|
+
|
|
60
|
+
-
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Release gate — proposal-first record for go/no-go decisions.
|
|
2
|
+
# QA FlowKit does not perform external writes. Update this file after validators and review.
|
|
3
|
+
|
|
4
|
+
decision: PENDING
|
|
5
|
+
approver: ""
|
|
6
|
+
recordedAt: ""
|
|
7
|
+
coverage_summary: |
|
|
8
|
+
Summarize traceability coverage, validator results and test-management sync status.
|
|
9
|
+
open_risks:
|
|
10
|
+
- Document any blocking or residual risks, or state "None documented" for PASS.
|
|
11
|
+
evidence_paths:
|
|
12
|
+
- qa-ai-output/traceability-matrix.md
|
|
13
|
+
- qa-ai-output/pr-summary.md
|
|
14
|
+
waived_reason: ""
|
|
15
|
+
notes: |
|
|
16
|
+
Required human approval before production release. Use WAIVED only with explicit approver and reason.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Test Design Proposal (per RF / epic)
|
|
2
|
+
|
|
3
|
+
> Per-RF or per-epic test cases. For system-wide strategy see `qa-ai-output/test-design-system.md` (standard and enterprise tracks).
|
|
4
|
+
|
|
5
|
+
## Official RF ID
|
|
6
|
+
|
|
7
|
+
<!-- Required before final .feature generation -->
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
## Proposed tests
|
|
12
|
+
|
|
13
|
+
| RF | CA | Test ID | Title | Type | Priority | Manual | Action |
|
|
14
|
+
|---|---|---|---|---|---|---|---|
|
|
15
|
+
|
|
16
|
+
## Existing tests to reuse
|
|
17
|
+
|
|
18
|
+
## Existing tests requiring modification
|
|
19
|
+
|
|
20
|
+
## New tests to create
|
|
21
|
+
|
|
22
|
+
## Ambiguities requiring user decision
|
|
23
|
+
|
|
24
|
+
## Approval request
|
|
25
|
+
|
|
26
|
+
Do you approve generating the proposed `.feature` files?
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"TC-001": {
|
|
3
|
+
"externalId": "C123",
|
|
4
|
+
"section": "Login",
|
|
5
|
+
"suite": "Regression",
|
|
6
|
+
"status": "planned",
|
|
7
|
+
"lastReviewedAt": "2026-05-25",
|
|
8
|
+
"notes": "Example only. Do not store secrets, tokens or credentials in this file."
|
|
9
|
+
},
|
|
10
|
+
"features/functional/RF-101-TC-001-login.feature": {
|
|
11
|
+
"externalId": "C124",
|
|
12
|
+
"section": "Login",
|
|
13
|
+
"suite": "Regression",
|
|
14
|
+
"status": "planned",
|
|
15
|
+
"lastReviewedAt": "2026-05-25",
|
|
16
|
+
"notes": "Alternative key style using the feature file path. Use either ID keys or feature-path keys consistently."
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Test Management Coverage Analysis
|
|
2
|
+
|
|
3
|
+
## Test management project
|
|
4
|
+
|
|
5
|
+
## Existing matching tests
|
|
6
|
+
|
|
7
|
+
## Valid existing tests
|
|
8
|
+
|
|
9
|
+
## Tests requiring update
|
|
10
|
+
|
|
11
|
+
## Missing tests
|
|
12
|
+
|
|
13
|
+
## Potential duplicates
|
|
14
|
+
|
|
15
|
+
## Proposed test management sections
|
|
16
|
+
|
|
17
|
+
## Recommendation
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Test Management Sync Plan
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
## Sections to create
|
|
6
|
+
|
|
7
|
+
## New cases to create
|
|
8
|
+
|
|
9
|
+
## Existing cases to keep
|
|
10
|
+
|
|
11
|
+
## Existing cases requiring changes
|
|
12
|
+
|
|
13
|
+
## Cases requiring user decision
|
|
14
|
+
|
|
15
|
+
| ID | Proposed action | Approval status | Target section | Notes |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
|
|
18
|
+
## Impact
|
|
19
|
+
|
|
20
|
+
## Approval request
|
|
21
|
+
|
|
22
|
+
Do you approve the proposed test management synchronization?
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Automation Analysis Workflow
|
|
2
|
+
|
|
3
|
+
Classify approved test cases by automation feasibility and propose implementation.
|
|
4
|
+
|
|
5
|
+
## Classification
|
|
6
|
+
|
|
7
|
+
- `automatable`: valuable and technically possible now.
|
|
8
|
+
- `manual`: should remain manual for business or operational reasons.
|
|
9
|
+
- `partial`: useful coverage can be automated, but manual checks remain.
|
|
10
|
+
- `blocked`: automatable in principle, but blocked by data, environment, selectors or framework support.
|
|
11
|
+
- `not-automatable`: unsuitable for UI/API automation.
|
|
12
|
+
|
|
13
|
+
## Output
|
|
14
|
+
|
|
15
|
+
Update `qa-ai-output/automation-feasibility-report.md` with:
|
|
16
|
+
|
|
17
|
+
- Feature/test IDs.
|
|
18
|
+
- Recommended framework from `qa-ai.config.yaml`.
|
|
19
|
+
- Required test data, selectors, mocks, clients or schemas.
|
|
20
|
+
- Risks and blockers.
|
|
21
|
+
- Pending configured issue tracker task drafts when automation cannot be implemented now.
|
|
22
|
+
|
|
23
|
+
Do not write automation code until `qa-ai-output/automation-implementation-plan.md` is approved.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Cleanup Workflow
|
|
2
|
+
|
|
3
|
+
Use this workflow when a user wants to inspect or remove files generated by `node .qa-ai/scripts/init.mjs` or `node .qa-ai/scripts/sync-agent-adapters.mjs`.
|
|
4
|
+
|
|
5
|
+
## Safety model
|
|
6
|
+
|
|
7
|
+
- Cleanup is manifest-based.
|
|
8
|
+
- The manifest lives at `.qa-ai/state/init-manifest.json`.
|
|
9
|
+
- Default cleanup is a dry-run and deletes nothing.
|
|
10
|
+
- `--force` is required before any file or directory is removed.
|
|
11
|
+
- Tracked files are protected by SHA-256 hashes.
|
|
12
|
+
- Modified tracked files are skipped unless `--include-modified` is explicitly passed.
|
|
13
|
+
- Directories are removed only when they are tracked and empty.
|
|
14
|
+
- The `.qa-ai/` framework folder is not removed by the clean command.
|
|
15
|
+
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
Preview all tracked cleanup actions:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
node .qa-ai/scripts/clean.mjs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Remove generated docs/config files that still match the manifest:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
node .qa-ai/scripts/clean.mjs --generated --force
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Remove generated adapter files and empty adapter directories:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
node .qa-ai/scripts/clean.mjs --adapters --empty-dirs --force
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Remove all tracked unchanged files and empty directories:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
node .qa-ai/scripts/clean.mjs --all --force
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Remove the manifest after all entries have been cleaned:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
node .qa-ai/scripts/clean.mjs --all --force --prune-state
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## What not to do
|
|
49
|
+
|
|
50
|
+
- Do not manually delete broad project folders when the manifest is available.
|
|
51
|
+
- Do not use `--include-modified` unless the user explicitly wants to discard local edits to generated files.
|
|
52
|
+
- Do not clean configured external tool data; the MVP has no external write cleanup.
|