@keber/qa-framework 1.13.1 → 1.13.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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/qa-framework.config.json +1 -1
- package/scripts/upgrade.js +47 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.13.2] - 2026-11-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`upgrade` no longer moves user-owned content during the legacy layout migrations.**
|
|
15
|
+
Section 5c used to move every unknown folder under `07-automation/e2e/` into `tests/`
|
|
16
|
+
(including `lib/`, `node_modules/`, `.auth/` and `test-results/`). It now moves a folder
|
|
17
|
+
only when it contains `*.spec.*` files and is not a tooling folder (`node_modules`, `lib`,
|
|
18
|
+
`test-results`, `playwright-report`, `blob-report`) or a dot-folder. Section 6 used to move
|
|
19
|
+
every flat `.md` in `02-test-plans/` to `sprints/legacy/`; it now moves only pre-v1.7.0
|
|
20
|
+
plans: files named `*-test-plan.md` or carrying the old `**Plan ID**: TP-` header.
|
|
21
|
+
A path that cannot be read is reported as a warning and left alone: unproven means
|
|
22
|
+
untouched.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
10
26
|
## [1.13.1] - 2026-11-06
|
|
11
27
|
|
|
12
28
|
### Fixed
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keber/qa-framework",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.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/qa-framework.config.json
CHANGED
package/scripts/upgrade.js
CHANGED
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
* - qa/07-automation/.env.example -> qa/07-automation/e2e/
|
|
20
20
|
* - qa/07-automation/fixtures/ -> qa/07-automation/e2e/fixtures/
|
|
21
21
|
* - qa/07-automation/e2e/{module}/ -> qa/07-automation/e2e/tests/{module}/
|
|
22
|
+
* (only folders holding *.spec.* files; lib/, node_modules/, dot-folders stay)
|
|
22
23
|
* - Creates integration/ and load/ placeholders * - Patches playwright.config.ts: testDir '.' -> './tests', adds testIgnore
|
|
23
24
|
* - Creates tests/helpers/debug/ and tests/seeds/ if absent
|
|
24
25
|
*
|
|
25
26
|
* MIGRATES (v1.6.x -> v1.7.0, non-destructive):
|
|
26
27
|
* - qa/02-test-plans/automated/ -> qa/02-test-plans/sprints/legacy-automated/
|
|
27
28
|
* - qa/02-test-plans/manual/ -> qa/02-test-plans/sprints/legacy-manual/
|
|
28
|
-
* - qa/02-test-plans
|
|
29
|
+
* - qa/02-test-plans/*-test-plan.md (or "**Plan ID**: TP-" header) -> sprints/legacy/
|
|
29
30
|
* - Creates qa/02-test-plans/sprints/ if absent
|
|
30
31
|
* - Creates qa/03-test-cases/README.md optional marker if absent
|
|
31
32
|
*
|
|
@@ -316,12 +317,37 @@ if (fs.existsSync(oldFixturesDir) && !fs.existsSync(newFixturesDir)) {
|
|
|
316
317
|
}
|
|
317
318
|
|
|
318
319
|
// 5c. Spec stubs: e2e/{module}/*.spec.ts -> e2e/tests/{module}/
|
|
319
|
-
// Moves
|
|
320
|
+
// Moves a directory directly under e2e/ only when it is provably a legacy module
|
|
321
|
+
// folder: not a known scaffold/tooling dir, not a dot-folder, and it contains at
|
|
322
|
+
// least one spec file. Anything else (lib/, node_modules/, docs/...) is user-owned.
|
|
320
323
|
const testsDir = path.join(e2eDir, 'tests');
|
|
321
|
-
const knownE2eDirs = new Set([
|
|
324
|
+
const knownE2eDirs = new Set([
|
|
325
|
+
'tests', 'page-objects', 'fixtures', 'diagnosis', 'scripts', 'seeds', 'helpers',
|
|
326
|
+
'node_modules', 'lib', 'test-results', 'playwright-report', 'blob-report',
|
|
327
|
+
]);
|
|
328
|
+
const SPEC_FILE_RE = /\.spec\.[cm]?[jt]s$/;
|
|
329
|
+
|
|
330
|
+
function containsSpecFile(dir) {
|
|
331
|
+
let entries;
|
|
332
|
+
try {
|
|
333
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
334
|
+
} catch (err) {
|
|
335
|
+
// Unreadable means unproven: leave the folder where it is.
|
|
336
|
+
warnings.push(`Cannot inspect ${path.relative(cwd, dir)} (${err.code}) - not migrated.`);
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
for (const entry of entries) {
|
|
340
|
+
if (entry.isFile() && SPEC_FILE_RE.test(entry.name)) return true;
|
|
341
|
+
if (entry.isDirectory() && entry.name !== 'node_modules' && !entry.name.startsWith('.') &&
|
|
342
|
+
containsSpecFile(path.join(dir, entry.name))) return true;
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
|
|
322
347
|
if (fs.existsSync(e2eDir)) {
|
|
323
348
|
for (const entry of fs.readdirSync(e2eDir, { withFileTypes: true })) {
|
|
324
|
-
if (!entry.isDirectory() || knownE2eDirs.has(entry.name)) continue;
|
|
349
|
+
if (!entry.isDirectory() || knownE2eDirs.has(entry.name) || entry.name.startsWith('.')) continue;
|
|
350
|
+
if (!containsSpecFile(path.join(e2eDir, entry.name))) continue;
|
|
325
351
|
const oldModDir = path.join(e2eDir, entry.name);
|
|
326
352
|
const newModDir = path.join(testsDir, entry.name);
|
|
327
353
|
if (!fs.existsSync(newModDir)) {
|
|
@@ -442,12 +468,28 @@ if (fs.existsSync(testPlansDir)) {
|
|
|
442
468
|
}
|
|
443
469
|
}
|
|
444
470
|
|
|
445
|
-
// Move
|
|
471
|
+
// Move flat .md files in 02-test-plans/ only when they are provably pre-v1.7.0 plans:
|
|
472
|
+
// named {module}-test-plan.md / {module}-{track}-test-plan.md (qa-test-plan <= v1.6.x),
|
|
473
|
+
// or generated from the old templates/test-plan.md (header "**Plan ID**: TP-...").
|
|
474
|
+
// Any other flat .md (README.md, plan-sprint-1.md, notes) is user-owned and stays.
|
|
475
|
+
const LEGACY_PLAN_NAME_RE = /-test-plan\.md$/i;
|
|
476
|
+
const LEGACY_PLAN_HEADER_RE = /^\*\*Plan ID\*\*:\s*TP-/m;
|
|
477
|
+
const isLegacyPlan = (file) => {
|
|
478
|
+
if (LEGACY_PLAN_NAME_RE.test(path.basename(file))) return true;
|
|
479
|
+
try {
|
|
480
|
+
return LEGACY_PLAN_HEADER_RE.test(fs.readFileSync(file, 'utf8'));
|
|
481
|
+
} catch (err) {
|
|
482
|
+
warnings.push(`Cannot read 02-test-plans/${path.basename(file)} (${err.code}) - not migrated.`);
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
446
487
|
if (fs.existsSync(testPlansDir)) {
|
|
447
488
|
const legacyDir = path.join(sprintsDir, 'legacy');
|
|
448
489
|
for (const entry of fs.readdirSync(testPlansDir, { withFileTypes: true })) {
|
|
449
490
|
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
|
|
450
491
|
const oldFile = path.join(testPlansDir, entry.name);
|
|
492
|
+
if (!isLegacyPlan(oldFile)) continue;
|
|
451
493
|
const newFile = path.join(legacyDir, entry.name);
|
|
452
494
|
if (!fs.existsSync(newFile)) {
|
|
453
495
|
if (!dryRun) {
|