@keber/qa-framework 1.1.1 → 1.1.3
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 +20 -9
- package/package.json +1 -1
- package/scripts/init.js +52 -21
package/README.md
CHANGED
|
@@ -28,27 +28,38 @@ This framework was designed to be:
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Install from npm
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npm install
|
|
35
|
-
npx qa-framework init
|
|
34
|
+
npm install @keber/qa-framework
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
The postinstall script scaffolds the `qa/` structure automatically. No need to run `init` manually.
|
|
38
|
+
|
|
39
|
+
### Using with an AI agent (GitHub Copilot, Claude, etc.)
|
|
40
|
+
|
|
41
|
+
Use this prompt in your IDE agent chat:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Install @keber/qa-framework and set up the project following qa/AGENT-NEXT-STEPS.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The install creates `qa/AGENT-NEXT-STEPS.md` with the exact steps the agent needs to complete the setup (optional integrations, module configuration, credentials, etc.).
|
|
48
|
+
|
|
49
|
+
### Using manually (without an agent)
|
|
39
50
|
|
|
40
51
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
node tools/qa-framework/scripts/cli.js init
|
|
52
|
+
npm install @keber/qa-framework
|
|
53
|
+
# then read qa/AGENT-NEXT-STEPS.md for next steps
|
|
44
54
|
```
|
|
45
55
|
|
|
46
56
|
The `init` command will:
|
|
47
57
|
|
|
48
58
|
1. Create the `qa/` directory tree in your project root
|
|
49
|
-
2. Copy all base templates into place
|
|
59
|
+
2. Copy all base templates and agent instructions into place
|
|
50
60
|
3. Create `qa/qa-framework.config.json` for project-specific settings
|
|
51
|
-
4.
|
|
61
|
+
4. Create `.github/copilot-instructions.md` with QA agent behavior rules
|
|
62
|
+
5. Create `qa/AGENT-NEXT-STEPS.md` with follow-up steps
|
|
52
63
|
|
|
53
64
|
---
|
|
54
65
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keber/qa-framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Reusable spec-driven QA framework for IDE-agent-assisted automated testing. Installable as an npm package. Provides structure, templates, agent instructions, and optional integrations for Playwright and Azure DevOps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"qa",
|
package/scripts/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* scripts/init.js
|
|
3
|
+
* scripts/init.js - Scaffold qa/ folder structure from config
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* qa-framework init
|
|
@@ -52,7 +52,7 @@ if (explicitConfigPath) {
|
|
|
52
52
|
} else {
|
|
53
53
|
config = buildBootstrapConfig();
|
|
54
54
|
configSource = 'generated defaults';
|
|
55
|
-
|
|
55
|
+
process.stderr.write('[qa-framework/init] No config file found. Bootstrapping with default config.\n');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const qaRoot = path.resolve(cwd, config.conventions?.qaRoot ?? 'qa');
|
|
@@ -60,7 +60,7 @@ const localConfigPath = path.join(qaRoot, 'qa-framework.config.json');
|
|
|
60
60
|
|
|
61
61
|
// --skip-if-exists: bail out silently when qa/ is already initialised
|
|
62
62
|
if (skipIfExists && fs.existsSync(localConfigPath)) {
|
|
63
|
-
|
|
63
|
+
process.stderr.write('[qa-framework/init] qa/ already initialised - skipping (postinstall).\n');
|
|
64
64
|
process.exit(0);
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -69,11 +69,11 @@ if (!fs.existsSync(localConfigPath)) {
|
|
|
69
69
|
fs.writeFileSync(localConfigPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
70
70
|
console.log(` [created] ${path.relative(cwd, localConfigPath)}`);
|
|
71
71
|
} else {
|
|
72
|
-
console.log(` [exists] ${path.relative(cwd, localConfigPath)}
|
|
72
|
+
console.log(` [exists] ${path.relative(cwd, localConfigPath)} - skipped`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
process.stderr.write(`[qa-framework/init] Scaffolding qa/ at: ${qaRoot}\n`);
|
|
76
|
+
process.stderr.write(`[qa-framework/init] Using config source: ${configSource}\n`);
|
|
77
77
|
|
|
78
78
|
// --- Top-level folders ---
|
|
79
79
|
const topLevelFolders = [
|
|
@@ -89,7 +89,7 @@ const topLevelFolders = [
|
|
|
89
89
|
for (const folder of topLevelFolders) {
|
|
90
90
|
const fullPath = path.join(qaRoot, folder);
|
|
91
91
|
fs.mkdirSync(fullPath, { recursive: true });
|
|
92
|
-
console.log(` [created] ${path.relative(
|
|
92
|
+
console.log(` [created] ${path.relative(cwd, fullPath)}/`);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// --- Standards placeholder ---
|
|
@@ -140,9 +140,9 @@ for (const mod of modules) {
|
|
|
140
140
|
} else {
|
|
141
141
|
fs.writeFileSync(dest, `# ${specFile}\n\n> Auto-generated placeholder\n`, 'utf8');
|
|
142
142
|
}
|
|
143
|
-
console.log(` [created] ${path.relative(
|
|
143
|
+
console.log(` [created] ${path.relative(cwd, dest)}`);
|
|
144
144
|
} else {
|
|
145
|
-
console.log(` [exists] ${path.relative(
|
|
145
|
+
console.log(` [exists] ${path.relative(cwd, dest)} - skipped`);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
@@ -152,7 +152,7 @@ for (const mod of modules) {
|
|
|
152
152
|
const specTs = path.join(e2eDir, `${subKey}.spec.ts`);
|
|
153
153
|
if (!fs.existsSync(specTs)) {
|
|
154
154
|
fs.writeFileSync(specTs, specScaffold(mod.name, sub.name, moduleKey, subKey), 'utf8');
|
|
155
|
-
console.log(` [created] ${path.relative(
|
|
155
|
+
console.log(` [created] ${path.relative(cwd, specTs)}`);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
}
|
|
@@ -164,7 +164,7 @@ for (const file of ['playwright.config.ts', 'global-setup.ts', '.env.example', '
|
|
|
164
164
|
const dest = path.join(automationDir, file);
|
|
165
165
|
if (!fs.existsSync(dest)) {
|
|
166
166
|
fs.copyFileSync(path.join(scaffoldSrc, file), dest);
|
|
167
|
-
console.log(` [created] ${path.relative(
|
|
167
|
+
console.log(` [created] ${path.relative(cwd, dest)}`);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
const fixturesDir = path.join(automationDir, 'fixtures');
|
|
@@ -173,7 +173,7 @@ for (const file of ['auth.ts', 'test-helpers.ts']) {
|
|
|
173
173
|
const dest = path.join(fixturesDir, file);
|
|
174
174
|
if (!fs.existsSync(dest)) {
|
|
175
175
|
fs.copyFileSync(path.join(scaffoldSrc, 'fixtures', file), dest);
|
|
176
|
-
console.log(` [created] ${path.relative(
|
|
176
|
+
console.log(` [created] ${path.relative(cwd , dest)}`);
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -247,9 +247,10 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
|
|
|
247
247
|
|
|
248
248
|
## Agent behavior rules
|
|
249
249
|
|
|
250
|
+
0. **On every conversation start:** check if \`qa/AGENT-NEXT-STEPS.md\` exists. If it does, read it and complete its steps before anything else.
|
|
250
251
|
1. Before performing any QA task, read the relevant instruction file from \`qa/00-guides/\`
|
|
251
|
-
2. Always save artifacts in the correct \`qa/\` subfolder
|
|
252
|
-
3. Never hardcode credentials
|
|
252
|
+
2. Always save artifacts in the correct \`qa/\` subfolder - refer to \`qa/QA-STRUCTURE-GUIDE.md\`
|
|
253
|
+
3. Never hardcode credentials - always use env vars and \`<PLACEHOLDER>\` in documentation
|
|
253
254
|
4. Follow the naming conventions in \`qa/00-standards/naming-conventions.md\`
|
|
254
255
|
5. Project QA config is at \`qa/qa-framework.config.json\`
|
|
255
256
|
|
|
@@ -268,12 +269,42 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
|
|
|
268
269
|
`;
|
|
269
270
|
writeIfMissing(copilotInstrPath, copilotInstrContent);
|
|
270
271
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
272
|
+
// --- AGENT-NEXT-STEPS.md — readable by the agent after install ---
|
|
273
|
+
const nextStepsContent = `# ✅ @keber/qa-framework installed successfully
|
|
274
|
+
|
|
275
|
+
> This file was generated automatically by the postinstall script.
|
|
276
|
+
> Read it and follow the steps below, then delete this file.
|
|
277
|
+
|
|
278
|
+
## What was scaffolded
|
|
279
|
+
|
|
280
|
+
- \`qa/\` folder structure with spec templates and agent instructions
|
|
281
|
+
- \`.github/copilot-instructions.md\` with QA agent behavior rules
|
|
282
|
+
|
|
283
|
+
## Required next steps
|
|
284
|
+
|
|
285
|
+
### 1. Configure your project modules
|
|
286
|
+
Edit \`qa/qa-framework.config.json\` and add your project modules under the \`"modules"\` array.
|
|
287
|
+
|
|
288
|
+
### 2. Optional integrations
|
|
289
|
+
|
|
290
|
+
**Azure DevOps integration:**
|
|
291
|
+
\`\`\`bash
|
|
292
|
+
npm install @keber/ado-qa
|
|
293
|
+
\`\`\`
|
|
294
|
+
|
|
295
|
+
**Playwright automation:**
|
|
296
|
+
\`\`\`bash
|
|
297
|
+
npm install @playwright/test
|
|
298
|
+
cd qa/07-automation && npm install && npx playwright install chromium
|
|
299
|
+
\`\`\`
|
|
300
|
+
|
|
301
|
+
### 3. Credentials
|
|
302
|
+
- Copy \`qa/07-automation/.env.example\` → \`qa/07-automation/.env\` and fill in credentials
|
|
303
|
+
- Add \`qa/07-automation/.env\` and \`qa/07-automation/.auth/\` to \`.gitignore\`
|
|
304
|
+
`;
|
|
305
|
+
const nextStepsPath = path.join(qaRoot, 'AGENT-NEXT-STEPS.md');
|
|
306
|
+
fs.writeFileSync(nextStepsPath, nextStepsContent, 'utf8');
|
|
307
|
+
console.log(` [created] ${path.relative(cwd, nextStepsPath)}`);
|
|
277
308
|
|
|
278
309
|
// -----------------------------------------------------------------------
|
|
279
310
|
// Helpers
|
|
@@ -282,7 +313,7 @@ function writeIfMissing(filePath, content) {
|
|
|
282
313
|
if (!fs.existsSync(filePath)) {
|
|
283
314
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
284
315
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
285
|
-
console.log(` [created] ${path.relative(
|
|
316
|
+
console.log(` [created] ${path.relative(cwd, filePath)}`);
|
|
286
317
|
}
|
|
287
318
|
}
|
|
288
319
|
|