@arcadialdev/arcality 2.2.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/.agents/skills/e2e-testing-expert/SKILL.md +28 -0
- package/.agents/skills/frontend-design/LICENSE.txt +177 -0
- package/.agents/skills/frontend-design/SKILL.md +42 -0
- package/.agents/skills/nodejs-backend-patterns/SKILL.md +639 -0
- package/.agents/skills/nodejs-backend-patterns/references/advanced-patterns.md +430 -0
- package/.agents/skills/playwright-best-practices/LICENSE.md +7 -0
- package/.agents/skills/playwright-best-practices/README.md +147 -0
- package/.agents/skills/playwright-best-practices/SKILL.md +303 -0
- package/.agents/skills/playwright-best-practices/advanced/authentication-flows.md +360 -0
- package/.agents/skills/playwright-best-practices/advanced/authentication.md +871 -0
- package/.agents/skills/playwright-best-practices/advanced/clock-mocking.md +364 -0
- package/.agents/skills/playwright-best-practices/advanced/mobile-testing.md +409 -0
- package/.agents/skills/playwright-best-practices/advanced/multi-context.md +288 -0
- package/.agents/skills/playwright-best-practices/advanced/multi-user.md +393 -0
- package/.agents/skills/playwright-best-practices/advanced/network-advanced.md +452 -0
- package/.agents/skills/playwright-best-practices/advanced/third-party.md +464 -0
- package/.agents/skills/playwright-best-practices/architecture/pom-vs-fixtures.md +363 -0
- package/.agents/skills/playwright-best-practices/architecture/test-architecture.md +369 -0
- package/.agents/skills/playwright-best-practices/architecture/when-to-mock.md +383 -0
- package/.agents/skills/playwright-best-practices/browser-apis/browser-apis.md +391 -0
- package/.agents/skills/playwright-best-practices/browser-apis/iframes.md +403 -0
- package/.agents/skills/playwright-best-practices/browser-apis/service-workers.md +504 -0
- package/.agents/skills/playwright-best-practices/browser-apis/websockets.md +403 -0
- package/.agents/skills/playwright-best-practices/core/annotations.md +424 -0
- package/.agents/skills/playwright-best-practices/core/assertions-waiting.md +361 -0
- package/.agents/skills/playwright-best-practices/core/configuration.md +452 -0
- package/.agents/skills/playwright-best-practices/core/fixtures-hooks.md +417 -0
- package/.agents/skills/playwright-best-practices/core/global-setup.md +434 -0
- package/.agents/skills/playwright-best-practices/core/locators.md +242 -0
- package/.agents/skills/playwright-best-practices/core/page-object-model.md +315 -0
- package/.agents/skills/playwright-best-practices/core/projects-dependencies.md +453 -0
- package/.agents/skills/playwright-best-practices/core/test-data.md +492 -0
- package/.agents/skills/playwright-best-practices/core/test-suite-structure.md +361 -0
- package/.agents/skills/playwright-best-practices/core/test-tags.md +298 -0
- package/.agents/skills/playwright-best-practices/debugging/console-errors.md +420 -0
- package/.agents/skills/playwright-best-practices/debugging/debugging.md +504 -0
- package/.agents/skills/playwright-best-practices/debugging/error-testing.md +360 -0
- package/.agents/skills/playwright-best-practices/debugging/flaky-tests.md +496 -0
- package/.agents/skills/playwright-best-practices/frameworks/angular.md +530 -0
- package/.agents/skills/playwright-best-practices/frameworks/nextjs.md +469 -0
- package/.agents/skills/playwright-best-practices/frameworks/react.md +531 -0
- package/.agents/skills/playwright-best-practices/frameworks/vue.md +574 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/ci-cd.md +468 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/docker.md +283 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/github-actions.md +546 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/gitlab.md +397 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/other-providers.md +521 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/parallel-sharding.md +371 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/performance.md +453 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/reporting.md +424 -0
- package/.agents/skills/playwright-best-practices/infrastructure-ci-cd/test-coverage.md +497 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/accessibility.md +359 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/api-testing.md +719 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/browser-extensions.md +506 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/canvas-webgl.md +493 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/component-testing.md +500 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/drag-drop.md +576 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/electron.md +509 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/file-operations.md +377 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/file-upload-download.md +562 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/forms-validation.md +561 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/graphql-testing.md +331 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/i18n.md +508 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/performance-testing.md +476 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/security-testing.md +430 -0
- package/.agents/skills/playwright-best-practices/testing-patterns/visual-regression.md +634 -0
- package/.env.example +21 -0
- package/README.md +30 -0
- package/bin/arcality.mjs +86 -0
- package/package.json +66 -0
- package/playwright.config.ts +12 -0
- package/scripts/cleanup-qmsdev.mjs +63 -0
- package/scripts/discover-view.mjs +52 -0
- package/scripts/extract-view.mjs +64 -0
- package/scripts/gen-and-run.mjs +838 -0
- package/scripts/init.mjs +290 -0
- package/scripts/migrate-to-central-out.mjs +157 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/rebrand-report.mjs +241 -0
- package/scripts/setup.mjs +166 -0
- package/src/KnowledgeService.ts +239 -0
- package/src/arcalityClient.mjs +266 -0
- package/src/configLoader.mjs +179 -0
- package/src/configManager.mjs +172 -0
- package/src/consoleBanner.ts +32 -0
- package/src/envSetup.ts +205 -0
- package/src/index.ts +25 -0
- package/src/projectInspector.ts +42 -0
- package/src/services/collectiveMemoryService.ts +178 -0
- package/src/testRunner.ts +201 -0
- package/tests/_helpers/ArcalityReporter.ts +490 -0
- package/tests/_helpers/agentic-runner.spec.ts +741 -0
- package/tests/_helpers/ai-agent-helper.ts +1573 -0
- package/tests/_helpers/discover-view.spec.ts +238 -0
- package/tests/_helpers/extract-view.spec.ts +118 -0
- package/tests/_helpers/qa-tools.ts +333 -0
- package/tests/_helpers/smart-action.spec.ts +1458 -0
package/bin/arcality.mjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bin/arcality.mjs — Entry point for the 'arcality' global command
|
|
3
|
+
// Registered as "bin" in package.json → npm creates the global symlink
|
|
4
|
+
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const subcommand = args[0];
|
|
15
|
+
|
|
16
|
+
// ── Subcommand: arcality init ──
|
|
17
|
+
if (subcommand === 'init') {
|
|
18
|
+
const initScript = path.join(PACKAGE_ROOT, 'scripts', 'init.mjs');
|
|
19
|
+
const child = spawn('node', [initScript, ...args.slice(1)], {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
cwd: process.cwd(), // Run in the user's project directory
|
|
22
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
23
|
+
});
|
|
24
|
+
child.on('exit', code => process.exit(code || 0));
|
|
25
|
+
|
|
26
|
+
// ── Subcommand: arcality run ──
|
|
27
|
+
} else if (subcommand === 'run') {
|
|
28
|
+
const mainScript = path.join(PACKAGE_ROOT, 'scripts', 'gen-and-run.mjs');
|
|
29
|
+
const child = spawn('node', [mainScript, '--agent', ...args.slice(1)], {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
cwd: process.cwd(),
|
|
32
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
33
|
+
});
|
|
34
|
+
child.on('exit', code => process.exit(code || 0));
|
|
35
|
+
|
|
36
|
+
// ── Subcommand: arcality setup (legacy) ──
|
|
37
|
+
} else if (subcommand === 'setup') {
|
|
38
|
+
const setupScript = path.join(PACKAGE_ROOT, 'scripts', 'setup.mjs');
|
|
39
|
+
const child = spawn('node', [setupScript, ...args.slice(1)], {
|
|
40
|
+
stdio: 'inherit',
|
|
41
|
+
cwd: PACKAGE_ROOT,
|
|
42
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
43
|
+
});
|
|
44
|
+
child.on('exit', code => process.exit(code || 0));
|
|
45
|
+
|
|
46
|
+
// ── Subcommand: arcality version ──
|
|
47
|
+
} else if (subcommand === '--version' || subcommand === '-v') {
|
|
48
|
+
const fs = await import('node:fs');
|
|
49
|
+
try {
|
|
50
|
+
const pkg = JSON.parse(fs.default.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8'));
|
|
51
|
+
console.log(`arcality v${pkg.version}`);
|
|
52
|
+
} catch {
|
|
53
|
+
console.log('arcality (version unknown)');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Subcommand: arcality help ──
|
|
57
|
+
} else if (subcommand === '--help' || subcommand === '-h' || subcommand === 'help') {
|
|
58
|
+
const fs = await import('node:fs');
|
|
59
|
+
let version = 'unknown';
|
|
60
|
+
try {
|
|
61
|
+
const pkg = JSON.parse(fs.default.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8'));
|
|
62
|
+
version = pkg.version || 'unknown';
|
|
63
|
+
} catch { }
|
|
64
|
+
|
|
65
|
+
console.log(`
|
|
66
|
+
Arcality v${version} — AI-powered QA Testing Agent
|
|
67
|
+
|
|
68
|
+
Usage:
|
|
69
|
+
arcality init Configure project & create arcality.config
|
|
70
|
+
arcality run [prompt] Run the autonomous agent
|
|
71
|
+
arcality Open interactive menu
|
|
72
|
+
arcality setup Legacy setup (API keys + Chromium)
|
|
73
|
+
arcality --version Show version
|
|
74
|
+
arcality --help Show this help
|
|
75
|
+
`);
|
|
76
|
+
|
|
77
|
+
// ── Default: interactive menu (gen-and-run.mjs) ──
|
|
78
|
+
} else {
|
|
79
|
+
const mainScript = path.join(PACKAGE_ROOT, 'scripts', 'gen-and-run.mjs');
|
|
80
|
+
const child = spawn('node', [mainScript, ...args], {
|
|
81
|
+
stdio: 'inherit',
|
|
82
|
+
cwd: process.cwd(),
|
|
83
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
84
|
+
});
|
|
85
|
+
child.on('exit', code => process.exit(code || 0));
|
|
86
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arcadialdev/arcality",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "AI-powered QA testing tool — Autonomous web testing agent by Arcadial",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "node scripts/gen-and-run.mjs",
|
|
8
|
+
"arcality": "node scripts/gen-and-run.mjs",
|
|
9
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
10
|
+
"setup": "node scripts/setup.mjs"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"arcality": "bin/arcality.mjs"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"scripts/",
|
|
18
|
+
"src/",
|
|
19
|
+
"tests/_helpers/",
|
|
20
|
+
".agents/",
|
|
21
|
+
"playwright.config.ts",
|
|
22
|
+
".env.example",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/Azlopez1/arcality.git"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"qa",
|
|
34
|
+
"testing",
|
|
35
|
+
"ai",
|
|
36
|
+
"playwright",
|
|
37
|
+
"autonomous",
|
|
38
|
+
"arcadial"
|
|
39
|
+
],
|
|
40
|
+
"author": "Arcadial",
|
|
41
|
+
"license": "ISC",
|
|
42
|
+
"type": "commonjs",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/Azlopez1/arcality/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/Azlopez1/arcality#readme",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/figlet": "^1.7.0",
|
|
49
|
+
"@types/node": "^25.0.9",
|
|
50
|
+
"@types/prompts": "^2.4.9",
|
|
51
|
+
"tsx": "^4.21.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@clack/prompts": "^1.0.1",
|
|
55
|
+
"@inquirer/prompts": "^8.2.0",
|
|
56
|
+
"@playwright/test": "^1.57.0",
|
|
57
|
+
"axios": "^1.13.6",
|
|
58
|
+
"chalk": "^5.6.2",
|
|
59
|
+
"dotenv": "^17.2.3",
|
|
60
|
+
"figlet": "^1.9.4",
|
|
61
|
+
"js-yaml": "^4.1.1",
|
|
62
|
+
"node-fetch": "^3.3.2",
|
|
63
|
+
"prompts": "^2.4.2",
|
|
64
|
+
"terminal-image": "^1.1.0"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
testDir: './tests',
|
|
5
|
+
reporter: [
|
|
6
|
+
['./tests/_helpers/ArcalityReporter.ts', { outputDir: process.env.REPORTS_DIR || 'tests-report' }]
|
|
7
|
+
],
|
|
8
|
+
use: {
|
|
9
|
+
video: 'on',
|
|
10
|
+
trace: 'retain-on-failure',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const baseDir = 'c:/Users/apulido/OneDrive - Block Networks/Documentos/Arcadial Projects/Char.Dev/out/qmsDev';
|
|
5
|
+
const nestedDir = path.join(baseDir, 'context', 'qmsDev');
|
|
6
|
+
const targetContextDir = path.join(baseDir, 'context');
|
|
7
|
+
const targetMissionsDir = path.join(baseDir, 'missions');
|
|
8
|
+
|
|
9
|
+
function cleanup() {
|
|
10
|
+
if (!fs.existsSync(nestedDir)) {
|
|
11
|
+
console.log('Nested directory not found, skipping.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const files = fs.readdirSync(nestedDir);
|
|
16
|
+
|
|
17
|
+
files.forEach(file => {
|
|
18
|
+
const filePath = path.join(nestedDir, file);
|
|
19
|
+
if (file.startsWith('agent-log-')) {
|
|
20
|
+
console.log(`Moving ${file} to context/`);
|
|
21
|
+
fs.renameSync(filePath, path.join(targetContextDir, file));
|
|
22
|
+
} else if (file === 'memoria-agente.json') {
|
|
23
|
+
const targetMemory = path.join(targetContextDir, 'memoria-agente.json');
|
|
24
|
+
if (fs.existsSync(targetMemory)) {
|
|
25
|
+
console.log('Merging memoria-agente.json...');
|
|
26
|
+
const mainMemory = JSON.parse(fs.readFileSync(targetMemory, 'utf8'));
|
|
27
|
+
const nestedMemory = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
28
|
+
const combined = [...mainMemory, ...nestedMemory];
|
|
29
|
+
fs.writeFileSync(targetMemory, JSON.stringify(combined, null, 2));
|
|
30
|
+
fs.unlinkSync(filePath);
|
|
31
|
+
} else {
|
|
32
|
+
console.log('Moving memoria-agente.json...');
|
|
33
|
+
fs.renameSync(filePath, targetMemory);
|
|
34
|
+
}
|
|
35
|
+
} else if (file === 'saved_missions') {
|
|
36
|
+
const missions = fs.readdirSync(filePath);
|
|
37
|
+
missions.forEach(m => {
|
|
38
|
+
if (m.endsWith('.yaml') || m.endsWith('.yml')) {
|
|
39
|
+
console.log(`Moving mission ${m} to missions/`);
|
|
40
|
+
fs.renameSync(path.join(filePath, m), path.join(targetMissionsDir, m));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
fs.rmdirSync(filePath, { recursive: true });
|
|
44
|
+
} else if (fs.statSync(filePath).isFile()) {
|
|
45
|
+
console.log(`Moving other file ${file} to context/`);
|
|
46
|
+
fs.renameSync(filePath, path.join(targetContextDir, file));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Try to remove the empty nested dir
|
|
51
|
+
try {
|
|
52
|
+
if (fs.readdirSync(nestedDir).length === 0) {
|
|
53
|
+
fs.rmdirSync(nestedDir);
|
|
54
|
+
console.log('Removed empty nested directory.');
|
|
55
|
+
} else {
|
|
56
|
+
console.warn('Nested directory not empty, keeping it.');
|
|
57
|
+
}
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error('Error removing nested dir:', e.message);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
cleanup();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
const targetPath = process.argv[2] || '/';
|
|
8
|
+
const isWin = process.platform === 'win32';
|
|
9
|
+
const cmd = isWin ? 'npx.cmd' : 'npx';
|
|
10
|
+
const testFile = 'tests/_helpers/discover-view.spec.ts';
|
|
11
|
+
|
|
12
|
+
function parseDotEnvFile(p) {
|
|
13
|
+
try {
|
|
14
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
15
|
+
const lines = raw.split(/\r?\n/);
|
|
16
|
+
const out = {};
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
const trimmed = line.trim();
|
|
19
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
20
|
+
const idx = trimmed.indexOf('=');
|
|
21
|
+
if (idx === -1) continue;
|
|
22
|
+
let k = trimmed.slice(0, idx).trim();
|
|
23
|
+
let v = trimmed.slice(idx + 1).trim();
|
|
24
|
+
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
|
|
25
|
+
out[k] = v;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
} catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const fileEnv = parseDotEnvFile(path.join(process.cwd(), '.env'));
|
|
34
|
+
const env = { ...process.env, ...fileEnv, TARGET_PATH: targetPath };
|
|
35
|
+
|
|
36
|
+
const args = ['playwright', 'test', testFile, '--project=chromium'];
|
|
37
|
+
// Debug printing removed to avoid leaking placeholders; command is spawned directly
|
|
38
|
+
|
|
39
|
+
const child = spawn(cmd, args, {
|
|
40
|
+
stdio: 'inherit',
|
|
41
|
+
shell: isWin,
|
|
42
|
+
env,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
child.on('exit', (code) => {
|
|
46
|
+
process.exit(code ?? 0);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
child.on('error', (err) => {
|
|
50
|
+
console.error('Failed to run playwright:', err);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
const targetPath = process.argv[2] || '/';
|
|
8
|
+
const isWin = process.platform === 'win32';
|
|
9
|
+
const cmd = isWin ? 'npx.cmd' : 'npx';
|
|
10
|
+
|
|
11
|
+
// Use POSIX-style forward slashes so Playwright reliably matches the file on all platforms
|
|
12
|
+
const testFile = 'tests/_helpers/extract-view.spec.ts';
|
|
13
|
+
|
|
14
|
+
function parseDotEnvFile(p) {
|
|
15
|
+
try {
|
|
16
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
17
|
+
const lines = raw.split(/\r?\n/);
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const line of lines) {
|
|
20
|
+
const trimmed = line.trim();
|
|
21
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
22
|
+
const idx = trimmed.indexOf('=');
|
|
23
|
+
if (idx === -1) continue;
|
|
24
|
+
let k = trimmed.slice(0, idx).trim();
|
|
25
|
+
let v = trimmed.slice(idx + 1).trim();
|
|
26
|
+
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
|
|
27
|
+
out[k] = v;
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
} catch {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const fileEnv = parseDotEnvFile(path.join(process.cwd(), '.env'));
|
|
36
|
+
const env = { ...process.env, ...fileEnv, TARGET_PATH: targetPath };
|
|
37
|
+
|
|
38
|
+
const args = ['playwright', 'test', testFile, '--project=chromium', '--headed'];
|
|
39
|
+
|
|
40
|
+
// Debug printing removed to avoid leaking placeholders; command is spawned directly
|
|
41
|
+
|
|
42
|
+
const child = spawn(cmd, args, {
|
|
43
|
+
stdio: 'inherit',
|
|
44
|
+
shell: isWin,
|
|
45
|
+
env,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
child.on('exit', (code) => {
|
|
49
|
+
// DESACTIVADO POR PETICIÓN DE USUARIO: Evitar pantallas extras/consolas
|
|
50
|
+
/*
|
|
51
|
+
try {
|
|
52
|
+
const showCmd = isWin ? 'npx.cmd' : 'npx';
|
|
53
|
+
spawn(showCmd, ['playwright', 'show-report'], { stdio: 'ignore', shell: isWin, detached: true });
|
|
54
|
+
} catch (e) {
|
|
55
|
+
// ignore
|
|
56
|
+
}
|
|
57
|
+
*/
|
|
58
|
+
process.exit(code ?? 0);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
child.on('error', (err) => {
|
|
62
|
+
console.error('Failed to run playwright:', err);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|