@toolstackhq/create-qa-patterns 1.0.2 → 1.0.4
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 +11 -0
- package/index.js +129 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,3 +41,14 @@ When run in a terminal, the CLI shows:
|
|
|
41
41
|
- `npm install`
|
|
42
42
|
- `npx playwright install`
|
|
43
43
|
- `npm test`
|
|
44
|
+
|
|
45
|
+
## Prerequisite checks
|
|
46
|
+
|
|
47
|
+
The CLI checks:
|
|
48
|
+
|
|
49
|
+
- required Node.js version
|
|
50
|
+
- `npm` availability for install and test actions
|
|
51
|
+
- `npx` availability for Playwright browser installation
|
|
52
|
+
- `docker` availability and warns if it is missing
|
|
53
|
+
|
|
54
|
+
If `npx playwright install` fails because the host is missing browser dependencies, the CLI keeps the generated project and prints the recovery steps instead of treating scaffold generation as failed.
|
package/index.js
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const readline = require("node:readline");
|
|
6
|
-
const { spawn } = require("node:child_process");
|
|
6
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
7
7
|
|
|
8
8
|
const DEFAULT_TEMPLATE = "playwright-template";
|
|
9
|
+
const MIN_NODE_VERSION = {
|
|
10
|
+
major: 18,
|
|
11
|
+
minor: 18,
|
|
12
|
+
patch: 0
|
|
13
|
+
};
|
|
9
14
|
const DEFAULT_GITIGNORE = `node_modules/
|
|
10
15
|
|
|
11
16
|
.env
|
|
@@ -53,6 +58,39 @@ Supported templates:
|
|
|
53
58
|
`);
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
function parseNodeVersion(version) {
|
|
62
|
+
const normalized = version.replace(/^v/, "");
|
|
63
|
+
const [major = "0", minor = "0", patch = "0"] = normalized.split(".");
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
major: Number.parseInt(major, 10),
|
|
67
|
+
minor: Number.parseInt(minor, 10),
|
|
68
|
+
patch: Number.parseInt(patch, 10)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isNodeVersionSupported(version) {
|
|
73
|
+
if (version.major !== MIN_NODE_VERSION.major) {
|
|
74
|
+
return version.major > MIN_NODE_VERSION.major;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (version.minor !== MIN_NODE_VERSION.minor) {
|
|
78
|
+
return version.minor > MIN_NODE_VERSION.minor;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return version.patch >= MIN_NODE_VERSION.patch;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function assertSupportedNodeVersion() {
|
|
85
|
+
const currentVersion = parseNodeVersion(process.version);
|
|
86
|
+
|
|
87
|
+
if (!isNodeVersionSupported(currentVersion)) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Node ${MIN_NODE_VERSION.major}.${MIN_NODE_VERSION.minor}.${MIN_NODE_VERSION.patch}+ is required. Current version: ${process.version}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
56
94
|
function resolveTemplate(value) {
|
|
57
95
|
return TEMPLATE_ALIASES.get(value);
|
|
58
96
|
}
|
|
@@ -65,6 +103,40 @@ function sleep(ms) {
|
|
|
65
103
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
66
104
|
}
|
|
67
105
|
|
|
106
|
+
function commandExists(command) {
|
|
107
|
+
const result = spawnSync(getCommandName(command), ["--version"], {
|
|
108
|
+
stdio: "ignore"
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return !result.error && result.status === 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function collectPrerequisites() {
|
|
115
|
+
return {
|
|
116
|
+
npm: commandExists("npm"),
|
|
117
|
+
npx: commandExists("npx"),
|
|
118
|
+
docker: commandExists("docker")
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function printPrerequisiteWarnings(prerequisites) {
|
|
123
|
+
if (!prerequisites.npm) {
|
|
124
|
+
process.stdout.write("Warning: npm was not found. Automated install and test steps will be unavailable.\n");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!prerequisites.npx) {
|
|
128
|
+
process.stdout.write("Warning: npx was not found. Playwright browser installation will be unavailable.\n");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!prerequisites.docker) {
|
|
132
|
+
process.stdout.write("Warning: docker was not found. Docker-based template flows will not run until Docker is installed.\n");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!prerequisites.npm || !prerequisites.npx || !prerequisites.docker) {
|
|
136
|
+
process.stdout.write("\n");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
68
140
|
function createLineInterface() {
|
|
69
141
|
return readline.createInterface({
|
|
70
142
|
input: process.stdin,
|
|
@@ -372,6 +444,26 @@ function getCommandName(base) {
|
|
|
372
444
|
return base;
|
|
373
445
|
}
|
|
374
446
|
|
|
447
|
+
function printPlaywrightInstallRecovery(targetDirectory) {
|
|
448
|
+
process.stdout.write(`
|
|
449
|
+
Playwright browser installation did not complete.
|
|
450
|
+
|
|
451
|
+
Common cause:
|
|
452
|
+
Missing OS packages required to run Playwright browsers.
|
|
453
|
+
|
|
454
|
+
Recommended next steps:
|
|
455
|
+
cd ${path.relative(process.cwd(), targetDirectory) || "."}
|
|
456
|
+
sudo npx playwright install-deps
|
|
457
|
+
npx playwright install
|
|
458
|
+
|
|
459
|
+
If you already know the missing package name, install it with your system package manager and then rerun:
|
|
460
|
+
npx playwright install
|
|
461
|
+
|
|
462
|
+
The template was generated successfully. You can complete browser setup later.
|
|
463
|
+
|
|
464
|
+
`);
|
|
465
|
+
}
|
|
466
|
+
|
|
375
467
|
function runCommand(command, args, cwd) {
|
|
376
468
|
return new Promise((resolve, reject) => {
|
|
377
469
|
const child = spawn(getCommandName(command), args, {
|
|
@@ -421,34 +513,61 @@ async function runPostGenerateActions(targetDirectory) {
|
|
|
421
513
|
return;
|
|
422
514
|
}
|
|
423
515
|
|
|
424
|
-
const
|
|
516
|
+
const prerequisites = collectPrerequisites();
|
|
425
517
|
|
|
426
|
-
if (
|
|
427
|
-
await
|
|
518
|
+
if (prerequisites.npm) {
|
|
519
|
+
const shouldInstallDependencies = await askYesNo("Run npm install now?", true);
|
|
520
|
+
|
|
521
|
+
if (shouldInstallDependencies) {
|
|
522
|
+
await runCommand("npm", ["install"], targetDirectory);
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
process.stdout.write("Skipping npm install prompt because npm is not available.\n");
|
|
428
526
|
}
|
|
429
527
|
|
|
430
|
-
|
|
528
|
+
if (prerequisites.npx) {
|
|
529
|
+
const shouldInstallPlaywright = await askYesNo("Run npx playwright install now?", true);
|
|
530
|
+
|
|
531
|
+
if (shouldInstallPlaywright) {
|
|
532
|
+
try {
|
|
533
|
+
await runCommand("npx", ["playwright", "install"], targetDirectory);
|
|
534
|
+
} catch (error) {
|
|
535
|
+
printPlaywrightInstallRecovery(targetDirectory);
|
|
431
536
|
|
|
432
|
-
|
|
433
|
-
|
|
537
|
+
const shouldContinue = await askYesNo("Continue without completing Playwright browser install?", true);
|
|
538
|
+
|
|
539
|
+
if (!shouldContinue) {
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
process.stdout.write("Skipping Playwright browser install prompt because npx is not available.\n");
|
|
434
546
|
}
|
|
435
547
|
|
|
436
|
-
|
|
548
|
+
if (prerequisites.npm) {
|
|
549
|
+
const shouldRunTests = await askYesNo("Run npm test now?", false);
|
|
437
550
|
|
|
438
|
-
|
|
439
|
-
|
|
551
|
+
if (shouldRunTests) {
|
|
552
|
+
await runCommand("npm", ["test"], targetDirectory);
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
process.stdout.write("Skipping npm test prompt because npm is not available.\n");
|
|
440
556
|
}
|
|
441
557
|
}
|
|
442
558
|
|
|
443
559
|
async function main() {
|
|
444
560
|
const args = process.argv.slice(2);
|
|
445
561
|
|
|
562
|
+
assertSupportedNodeVersion();
|
|
563
|
+
|
|
446
564
|
if (args.includes("--help") || args.includes("-h")) {
|
|
447
565
|
printHelp();
|
|
448
566
|
return;
|
|
449
567
|
}
|
|
450
568
|
|
|
451
569
|
const { templateName, targetDirectory, generatedInCurrentDirectory } = await resolveScaffoldArgs(args);
|
|
570
|
+
printPrerequisiteWarnings(collectPrerequisites());
|
|
452
571
|
await scaffoldProject(templateName, targetDirectory);
|
|
453
572
|
printSuccess(templateName, targetDirectory, generatedInCurrentDirectory);
|
|
454
573
|
await runPostGenerateActions(targetDirectory);
|