@keber/qa-framework 1.1.0 → 1.1.2
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/package.json +1 -1
- package/scripts/init.js +25 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keber/qa-framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
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
|
|
@@ -25,7 +25,9 @@ if (configFlag !== -1 && !args[configFlag + 1]) {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// When run as postinstall, process.cwd() points to node_modules/@keber/qa-framework.
|
|
29
|
+
// INIT_CWD is set by npm to the directory where `npm install` was invoked (the project root).
|
|
30
|
+
const cwd = process.env.INIT_CWD || process.cwd();
|
|
29
31
|
const explicitConfigPath = configFlag !== -1 ? path.resolve(cwd, args[configFlag + 1]) : null;
|
|
30
32
|
const rootConfigPath = path.resolve(cwd, 'qa-framework.config.json');
|
|
31
33
|
const qaConfigPath = path.resolve(cwd, 'qa', 'qa-framework.config.json');
|
|
@@ -50,7 +52,7 @@ if (explicitConfigPath) {
|
|
|
50
52
|
} else {
|
|
51
53
|
config = buildBootstrapConfig();
|
|
52
54
|
configSource = 'generated defaults';
|
|
53
|
-
|
|
55
|
+
process.stderr.write('[qa-framework/init] No config file found. Bootstrapping with default config.\n');
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
const qaRoot = path.resolve(cwd, config.conventions?.qaRoot ?? 'qa');
|
|
@@ -58,7 +60,7 @@ const localConfigPath = path.join(qaRoot, 'qa-framework.config.json');
|
|
|
58
60
|
|
|
59
61
|
// --skip-if-exists: bail out silently when qa/ is already initialised
|
|
60
62
|
if (skipIfExists && fs.existsSync(localConfigPath)) {
|
|
61
|
-
|
|
63
|
+
process.stderr.write('[qa-framework/init] qa/ already initialised - skipping (postinstall).\n');
|
|
62
64
|
process.exit(0);
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -67,11 +69,11 @@ if (!fs.existsSync(localConfigPath)) {
|
|
|
67
69
|
fs.writeFileSync(localConfigPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
68
70
|
console.log(` [created] ${path.relative(cwd, localConfigPath)}`);
|
|
69
71
|
} else {
|
|
70
|
-
console.log(` [exists] ${path.relative(cwd, localConfigPath)}
|
|
72
|
+
console.log(` [exists] ${path.relative(cwd, localConfigPath)} - skipped`);
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
process.stderr.write(`[qa-framework/init] Scaffolding qa/ at: ${qaRoot}\n`);
|
|
76
|
+
process.stderr.write(`[qa-framework/init] Using config source: ${configSource}\n`);
|
|
75
77
|
|
|
76
78
|
// --- Top-level folders ---
|
|
77
79
|
const topLevelFolders = [
|
|
@@ -87,7 +89,7 @@ const topLevelFolders = [
|
|
|
87
89
|
for (const folder of topLevelFolders) {
|
|
88
90
|
const fullPath = path.join(qaRoot, folder);
|
|
89
91
|
fs.mkdirSync(fullPath, { recursive: true });
|
|
90
|
-
console.log(` [created] ${path.relative(
|
|
92
|
+
console.log(` [created] ${path.relative(cwd, fullPath)}/`);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
// --- Standards placeholder ---
|
|
@@ -138,9 +140,9 @@ for (const mod of modules) {
|
|
|
138
140
|
} else {
|
|
139
141
|
fs.writeFileSync(dest, `# ${specFile}\n\n> Auto-generated placeholder\n`, 'utf8');
|
|
140
142
|
}
|
|
141
|
-
console.log(` [created] ${path.relative(
|
|
143
|
+
console.log(` [created] ${path.relative(cwd, dest)}`);
|
|
142
144
|
} else {
|
|
143
|
-
console.log(` [exists] ${path.relative(
|
|
145
|
+
console.log(` [exists] ${path.relative(cwd, dest)} - skipped`);
|
|
144
146
|
}
|
|
145
147
|
}
|
|
146
148
|
|
|
@@ -150,7 +152,7 @@ for (const mod of modules) {
|
|
|
150
152
|
const specTs = path.join(e2eDir, `${subKey}.spec.ts`);
|
|
151
153
|
if (!fs.existsSync(specTs)) {
|
|
152
154
|
fs.writeFileSync(specTs, specScaffold(mod.name, sub.name, moduleKey, subKey), 'utf8');
|
|
153
|
-
console.log(` [created] ${path.relative(
|
|
155
|
+
console.log(` [created] ${path.relative(cwd, specTs)}`);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
}
|
|
@@ -162,7 +164,7 @@ for (const file of ['playwright.config.ts', 'global-setup.ts', '.env.example', '
|
|
|
162
164
|
const dest = path.join(automationDir, file);
|
|
163
165
|
if (!fs.existsSync(dest)) {
|
|
164
166
|
fs.copyFileSync(path.join(scaffoldSrc, file), dest);
|
|
165
|
-
console.log(` [created] ${path.relative(
|
|
167
|
+
console.log(` [created] ${path.relative(cwd, dest)}`);
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
170
|
const fixturesDir = path.join(automationDir, 'fixtures');
|
|
@@ -171,7 +173,7 @@ for (const file of ['auth.ts', 'test-helpers.ts']) {
|
|
|
171
173
|
const dest = path.join(fixturesDir, file);
|
|
172
174
|
if (!fs.existsSync(dest)) {
|
|
173
175
|
fs.copyFileSync(path.join(scaffoldSrc, 'fixtures', file), dest);
|
|
174
|
-
console.log(` [created] ${path.relative(
|
|
176
|
+
console.log(` [created] ${path.relative(cwd , dest)}`);
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
@@ -246,8 +248,8 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
|
|
|
246
248
|
## Agent behavior rules
|
|
247
249
|
|
|
248
250
|
1. Before performing any QA task, read the relevant instruction file from \`qa/00-guides/\`
|
|
249
|
-
2. Always save artifacts in the correct \`qa/\` subfolder
|
|
250
|
-
3. Never hardcode credentials
|
|
251
|
+
2. Always save artifacts in the correct \`qa/\` subfolder - refer to \`qa/QA-STRUCTURE-GUIDE.md\`
|
|
252
|
+
3. Never hardcode credentials - always use env vars and \`<PLACEHOLDER>\` in documentation
|
|
251
253
|
4. Follow the naming conventions in \`qa/00-standards/naming-conventions.md\`
|
|
252
254
|
5. Project QA config is at \`qa/qa-framework.config.json\`
|
|
253
255
|
|
|
@@ -266,12 +268,13 @@ This project uses \`@keber/qa-framework\` v${config.frameworkVersion ?? '1.0.0'}
|
|
|
266
268
|
`;
|
|
267
269
|
writeIfMissing(copilotInstrPath, copilotInstrContent);
|
|
268
270
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
process.stderr.write('\n[qa-framework/init] ✅ QA framework scaffold complete!\n');
|
|
272
|
+
process.stderr.write('\nNext steps for the agent:\n');
|
|
273
|
+
process.stderr.write(' 1. If ADO integration is needed, run: npm install @keber/ado-qa\n');
|
|
274
|
+
process.stderr.write(' 2. If Playwright automation is needed, run: npm install @playwright/test\n');
|
|
275
|
+
process.stderr.write(' 3. Edit qa/qa-framework.config.json - add your project modules\n');
|
|
276
|
+
process.stderr.write(' 4. Copy qa/07-automation/.env.example -> qa/07-automation/.env and fill in credentials\n');
|
|
277
|
+
process.stderr.write(' 5. Add qa/07-automation/.env and qa/07-automation/.auth/ to .gitignore\n');
|
|
275
278
|
|
|
276
279
|
// -----------------------------------------------------------------------
|
|
277
280
|
// Helpers
|
|
@@ -280,7 +283,7 @@ function writeIfMissing(filePath, content) {
|
|
|
280
283
|
if (!fs.existsSync(filePath)) {
|
|
281
284
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
282
285
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
283
|
-
console.log(` [created] ${path.relative(
|
|
286
|
+
console.log(` [created] ${path.relative(cwd, filePath)}`);
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
289
|
|