@lvce-editor/test-with-playwright 18.0.0 → 19.0.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/README.md +21 -1
- package/dist/main.js +496 -13
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
```json
|
|
6
6
|
{
|
|
7
7
|
"scripts": {
|
|
8
|
-
"e2e": "node ./node_modules/@lvce-editor/test-with-playwright/bin/test-with-playwright.js --only-extension=. --test-path=./e2e"
|
|
8
|
+
"e2e": "node ./node_modules/@lvce-editor/test-with-playwright/bin/test-with-playwright.js --runtime=browser --only-extension=. --test-path=./e2e"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"scripts": {
|
|
16
|
+
"e2e:electron": "node ./node_modules/@lvce-editor/test-with-playwright/bin/test-with-playwright.js --runtime=electron --electron-version=v0.84.0 --test-path=./e2e"
|
|
9
17
|
}
|
|
10
18
|
}
|
|
11
19
|
```
|
|
@@ -19,6 +27,7 @@ test('sample.hello-world', async () => {
|
|
|
19
27
|
|
|
20
28
|
## CLI Flags
|
|
21
29
|
|
|
30
|
+
- `--runtime`: `browser` (default) or `electron`
|
|
22
31
|
- `--only-extension`: path to the extension under test
|
|
23
32
|
- `--test-path`: path to the test root
|
|
24
33
|
- `--server-path`: explicit server entry point
|
|
@@ -26,6 +35,17 @@ test('sample.hello-world', async () => {
|
|
|
26
35
|
- `--headless`: run Playwright in headless mode
|
|
27
36
|
- `--browser`: browser engine to launch, either `chromium` or `firefox`
|
|
28
37
|
- `--trace-focus`: add `traceFocus=true` to test URLs
|
|
38
|
+
- `--electron-path`: path to an existing Electron app executable
|
|
39
|
+
- `--electron-version`: Lvce release version to download, required for `--runtime=electron` when `--electron-path` is not provided
|
|
40
|
+
- `--electron-cache-dir`: directory for downloaded Electron apps, defaults to `.test-with-playwright/electron`
|
|
41
|
+
- `--electron-arg`: extra Electron app argument, can be provided multiple times
|
|
42
|
+
- `--electron-env`: Electron environment variable in `NAME=value` form, can be provided multiple times
|
|
43
|
+
|
|
44
|
+
## Runtime Notes
|
|
45
|
+
|
|
46
|
+
- `browser` keeps the server-backed HTML test execution flow.
|
|
47
|
+
- `electron` downloads or reuses a Lvce Electron app, launches it with Playwright, and runs each test module against the first window.
|
|
48
|
+
- `--electron-path` skips downloading and is useful for custom local builds.
|
|
29
49
|
|
|
30
50
|
## Environment Variables
|
|
31
51
|
|
package/dist/main.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { join } from 'node:path';
|
|
1
|
+
import { dirname, join, resolve as resolve$1, basename } from 'node:path';
|
|
2
|
+
import { createWriteStream, existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, readdir, stat, readFile, chmod, writeFile, rm, mkdtemp } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { pipeline } from 'node:stream/promises';
|
|
6
|
+
import { execFile as execFile$1 } from 'node:child_process';
|
|
7
|
+
import { promisify } from 'node:util';
|
|
2
8
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
3
9
|
|
|
4
10
|
const HandleResult = 'HandleResult';
|
|
@@ -110,6 +116,30 @@ const commandMap = {
|
|
|
110
116
|
[HandleResult]: handleResult
|
|
111
117
|
};
|
|
112
118
|
|
|
119
|
+
const getHelpMessage = () => {
|
|
120
|
+
return `Usage: test-with-playwright [options]
|
|
121
|
+
|
|
122
|
+
Options:
|
|
123
|
+
--browser=<browser> Browser to run tests in: chromium or firefox
|
|
124
|
+
--runtime=<runtime> Runtime to run tests in: browser or electron
|
|
125
|
+
--filter=<pattern> Only run tests matching the filter
|
|
126
|
+
--headless Run the browser in headless mode
|
|
127
|
+
--only-extension=<path> Path to the extension under test
|
|
128
|
+
--server-path=<path> Path to the editor server entrypoint
|
|
129
|
+
--test-path=<path> Path to the test files
|
|
130
|
+
--trace-focus Log focus changes while tests run
|
|
131
|
+
--electron-path=<path> Path to an existing Electron app executable
|
|
132
|
+
--electron-version=<ver> Lvce release version to download, for example v0.84.0
|
|
133
|
+
--electron-cache-dir=<p> Directory for downloaded Electron apps
|
|
134
|
+
--electron-arg=<arg> Extra Electron app argument, repeatable
|
|
135
|
+
--electron-env=<env> Electron environment variable as NAME=value, repeatable
|
|
136
|
+
-h, --help Show this help message
|
|
137
|
+
|
|
138
|
+
Environment:
|
|
139
|
+
ONLY_EXTENSION Default extension path
|
|
140
|
+
TEST_PATH Default test path`;
|
|
141
|
+
};
|
|
142
|
+
|
|
113
143
|
function getDefaultExportFromCjs (x) {
|
|
114
144
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
115
145
|
}
|
|
@@ -347,26 +377,67 @@ function requireMinimist () {
|
|
|
347
377
|
var minimistExports = requireMinimist();
|
|
348
378
|
const parseArgv = /*@__PURE__*/getDefaultExportFromCjs(minimistExports);
|
|
349
379
|
|
|
380
|
+
const toCliString = value => {
|
|
381
|
+
if (typeof value === 'string') {
|
|
382
|
+
return value;
|
|
383
|
+
}
|
|
384
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
385
|
+
return String(value);
|
|
386
|
+
}
|
|
387
|
+
throw new TypeError('expected cli argument value to be a string, number, or boolean');
|
|
388
|
+
};
|
|
389
|
+
const toStringArray = value => {
|
|
390
|
+
if (value === undefined) {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
if (Array.isArray(value)) {
|
|
394
|
+
return value.map(toCliString);
|
|
395
|
+
}
|
|
396
|
+
return [toCliString(value)];
|
|
397
|
+
};
|
|
350
398
|
const parseCliArgs = argv => {
|
|
351
399
|
const parsed = parseArgv(argv);
|
|
352
400
|
const result = Object.create(null);
|
|
353
401
|
if (parsed.browser) {
|
|
354
|
-
result.browser = parsed.browser;
|
|
402
|
+
result.browser = String(parsed.browser);
|
|
403
|
+
}
|
|
404
|
+
if (parsed.runtime) {
|
|
405
|
+
result.runtime = String(parsed.runtime);
|
|
355
406
|
}
|
|
356
407
|
if (parsed.filter) {
|
|
357
|
-
result.filter = parsed.filter;
|
|
408
|
+
result.filter = String(parsed.filter);
|
|
409
|
+
}
|
|
410
|
+
if (parsed.help || parsed.h) {
|
|
411
|
+
result.help = true;
|
|
358
412
|
}
|
|
359
413
|
if (parsed.headless) {
|
|
360
414
|
result.headless = true;
|
|
361
415
|
}
|
|
362
416
|
if (parsed['only-extension']) {
|
|
363
|
-
result.onlyExtension = parsed['only-extension'];
|
|
417
|
+
result.onlyExtension = String(parsed['only-extension']);
|
|
364
418
|
}
|
|
365
419
|
if (parsed['test-path']) {
|
|
366
|
-
result.testPath = parsed['test-path'];
|
|
420
|
+
result.testPath = String(parsed['test-path']);
|
|
367
421
|
}
|
|
368
422
|
if (parsed['server-path']) {
|
|
369
|
-
result.serverPath = parsed['server-path'];
|
|
423
|
+
result.serverPath = String(parsed['server-path']);
|
|
424
|
+
}
|
|
425
|
+
if (parsed['electron-path']) {
|
|
426
|
+
result.electronPath = String(parsed['electron-path']);
|
|
427
|
+
}
|
|
428
|
+
if (parsed['electron-version']) {
|
|
429
|
+
result.electronVersion = String(parsed['electron-version']);
|
|
430
|
+
}
|
|
431
|
+
if (parsed['electron-cache-dir']) {
|
|
432
|
+
result.electronCacheDir = String(parsed['electron-cache-dir']);
|
|
433
|
+
}
|
|
434
|
+
const electronArgs = toStringArray(parsed['electron-arg']);
|
|
435
|
+
if (electronArgs) {
|
|
436
|
+
result.electronArgs = electronArgs;
|
|
437
|
+
}
|
|
438
|
+
const electronEnv = toStringArray(parsed['electron-env']);
|
|
439
|
+
if (electronEnv) {
|
|
440
|
+
result.electronEnv = electronEnv;
|
|
370
441
|
}
|
|
371
442
|
if (parsed['trace-focus']) {
|
|
372
443
|
result.traceFocus = true;
|
|
@@ -389,26 +460,405 @@ const defaultOptions = {
|
|
|
389
460
|
browser: 'chromium',
|
|
390
461
|
extensionPath: '',
|
|
391
462
|
headless: false,
|
|
463
|
+
help: false,
|
|
464
|
+
runtime: 'browser',
|
|
392
465
|
testPath: ''
|
|
393
466
|
};
|
|
394
467
|
const isBrowser = value => {
|
|
395
468
|
return value === 'chromium' || value === 'firefox';
|
|
396
469
|
};
|
|
470
|
+
const isRuntime = value => {
|
|
471
|
+
return value === 'browser' || value === 'electron';
|
|
472
|
+
};
|
|
397
473
|
const getOptions = ({
|
|
398
474
|
argv,
|
|
399
475
|
env
|
|
400
476
|
}) => {
|
|
401
477
|
const parsedEnv = parseEnv(env);
|
|
402
478
|
const parsedArgs = parseCliArgs(argv);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
throw new Error(`[test-with-playwright] unsupported browser: ${browser}`);
|
|
479
|
+
if (parsedArgs.browser !== undefined && !isBrowser(parsedArgs.browser)) {
|
|
480
|
+
throw new Error(`[test-with-playwright] unsupported browser: ${parsedArgs.browser}`);
|
|
406
481
|
}
|
|
482
|
+
if (parsedArgs.runtime !== undefined && !isRuntime(parsedArgs.runtime)) {
|
|
483
|
+
throw new Error(`[test-with-playwright] unsupported runtime: ${parsedArgs.runtime}`);
|
|
484
|
+
}
|
|
485
|
+
const browser = parsedArgs.browser ?? defaultOptions.browser;
|
|
486
|
+
const runtime = parsedArgs.runtime ?? defaultOptions.runtime;
|
|
407
487
|
return {
|
|
408
488
|
...defaultOptions,
|
|
409
489
|
...parsedEnv,
|
|
410
490
|
...parsedArgs,
|
|
411
|
-
browser
|
|
491
|
+
browser,
|
|
492
|
+
runtime
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
const downloadFile = async ({
|
|
497
|
+
to,
|
|
498
|
+
url
|
|
499
|
+
}) => {
|
|
500
|
+
await mkdir(dirname(to), {
|
|
501
|
+
recursive: true
|
|
502
|
+
});
|
|
503
|
+
const response = await fetch(url);
|
|
504
|
+
if (!response.ok || !response.body) {
|
|
505
|
+
throw new Error(`[test-with-playwright] failed to download ${url}: ${response.status} ${response.statusText}`);
|
|
506
|
+
}
|
|
507
|
+
await pipeline(response.body, createWriteStream(to));
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
const execFileAsync = promisify(execFile$1);
|
|
511
|
+
const execFile = async ({
|
|
512
|
+
args,
|
|
513
|
+
command
|
|
514
|
+
}) => {
|
|
515
|
+
await execFileAsync(command, [...args], {
|
|
516
|
+
windowsHide: true
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const isWindowsExecutable = entry => {
|
|
521
|
+
return entry.toLowerCase().endsWith('.exe') && entry.toLowerCase().includes('lvce');
|
|
522
|
+
};
|
|
523
|
+
const isMacosExecutable = entry => {
|
|
524
|
+
return entry.endsWith('.app');
|
|
525
|
+
};
|
|
526
|
+
const findFile = async (directory, predicate) => {
|
|
527
|
+
const entries = await readdir(directory, {
|
|
528
|
+
withFileTypes: true
|
|
529
|
+
});
|
|
530
|
+
for (const entry of entries) {
|
|
531
|
+
const absolutePath = join(directory, entry.name);
|
|
532
|
+
if (entry.isDirectory()) {
|
|
533
|
+
const nestedResult = await findFile(absolutePath, predicate);
|
|
534
|
+
if (nestedResult) {
|
|
535
|
+
return nestedResult;
|
|
536
|
+
}
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
if (entry.isFile() && predicate(entry.name)) {
|
|
540
|
+
return absolutePath;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return undefined;
|
|
544
|
+
};
|
|
545
|
+
const findApp = async directory => {
|
|
546
|
+
const entries = await readdir(directory, {
|
|
547
|
+
withFileTypes: true
|
|
548
|
+
});
|
|
549
|
+
for (const entry of entries) {
|
|
550
|
+
const absolutePath = join(directory, entry.name);
|
|
551
|
+
if (entry.isDirectory() && isMacosExecutable(entry.name)) {
|
|
552
|
+
return absolutePath;
|
|
553
|
+
}
|
|
554
|
+
if (entry.isDirectory()) {
|
|
555
|
+
const nestedResult = await findApp(absolutePath);
|
|
556
|
+
if (nestedResult) {
|
|
557
|
+
return nestedResult;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return undefined;
|
|
562
|
+
};
|
|
563
|
+
const findMacosExecutable = async directory => {
|
|
564
|
+
const app = await findApp(directory);
|
|
565
|
+
if (!app) {
|
|
566
|
+
return undefined;
|
|
567
|
+
}
|
|
568
|
+
const macosDirectory = join(app, 'Contents', 'MacOS');
|
|
569
|
+
const entries = await readdir(macosDirectory);
|
|
570
|
+
for (const entry of entries) {
|
|
571
|
+
const absolutePath = join(macosDirectory, entry);
|
|
572
|
+
const fileStat = await stat(absolutePath);
|
|
573
|
+
if (fileStat.isFile()) {
|
|
574
|
+
return absolutePath;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return undefined;
|
|
578
|
+
};
|
|
579
|
+
const findElectronExecutable = async ({
|
|
580
|
+
directory,
|
|
581
|
+
platform
|
|
582
|
+
}) => {
|
|
583
|
+
if (platform === 'darwin') {
|
|
584
|
+
const executable = await findMacosExecutable(directory);
|
|
585
|
+
if (executable) {
|
|
586
|
+
return executable;
|
|
587
|
+
}
|
|
588
|
+
} else if (platform === 'win32') {
|
|
589
|
+
const executable = await findFile(directory, isWindowsExecutable);
|
|
590
|
+
if (executable) {
|
|
591
|
+
return executable;
|
|
592
|
+
}
|
|
593
|
+
} else {
|
|
594
|
+
const executable = await findFile(directory, entry => entry === 'lvce');
|
|
595
|
+
if (executable) {
|
|
596
|
+
return executable;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
throw new Error(`[test-with-playwright] failed to locate Electron executable in ${directory}`);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
const getLinuxArch = arch => {
|
|
603
|
+
switch (arch) {
|
|
604
|
+
case 'arm':
|
|
605
|
+
return 'armhf';
|
|
606
|
+
case 'arm64':
|
|
607
|
+
return 'arm64';
|
|
608
|
+
case 'x64':
|
|
609
|
+
return 'amd64';
|
|
610
|
+
default:
|
|
611
|
+
throw new Error(`[test-with-playwright] unsupported electron platform: linux/${arch}`);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
const getWindowsArch = arch => {
|
|
615
|
+
switch (arch) {
|
|
616
|
+
case 'arm64':
|
|
617
|
+
return 'arm64';
|
|
618
|
+
case 'x64':
|
|
619
|
+
return 'x64';
|
|
620
|
+
default:
|
|
621
|
+
throw new Error(`[test-with-playwright] unsupported electron platform: win32/${arch}`);
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
const resolveElectronAsset = ({
|
|
625
|
+
arch = process.arch,
|
|
626
|
+
platform = process.platform,
|
|
627
|
+
version
|
|
628
|
+
}) => {
|
|
629
|
+
switch (platform) {
|
|
630
|
+
case 'darwin':
|
|
631
|
+
if (arch !== 'arm64') {
|
|
632
|
+
throw new Error(`[test-with-playwright] unsupported electron platform: darwin/${arch}`);
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
archiveType: 'dmg',
|
|
636
|
+
assetName: `lvce-${version}_arm64.dmg`
|
|
637
|
+
};
|
|
638
|
+
case 'linux':
|
|
639
|
+
return {
|
|
640
|
+
archiveType: 'deb',
|
|
641
|
+
assetName: `lvce-${version}_${getLinuxArch(arch)}.deb`
|
|
642
|
+
};
|
|
643
|
+
case 'win32':
|
|
644
|
+
return {
|
|
645
|
+
archiveType: 'exe',
|
|
646
|
+
assetName: `Lvce-Setup-${version}-${getWindowsArch(arch)}.exe`
|
|
647
|
+
};
|
|
648
|
+
default:
|
|
649
|
+
throw new Error(`[test-with-playwright] unsupported electron platform: ${platform}/${arch}`);
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
const getDownloadUrl = ({
|
|
654
|
+
assetName,
|
|
655
|
+
version
|
|
656
|
+
}) => {
|
|
657
|
+
return `https://github.com/lvce-editor/lvce-editor/releases/download/${version}/${assetName}`;
|
|
658
|
+
};
|
|
659
|
+
const prepareLinux = async ({
|
|
660
|
+
assetPath,
|
|
661
|
+
cachePath
|
|
662
|
+
}) => {
|
|
663
|
+
await execFile({
|
|
664
|
+
args: ['-x', assetPath, cachePath],
|
|
665
|
+
command: 'dpkg-deb'
|
|
666
|
+
});
|
|
667
|
+
};
|
|
668
|
+
const prepareMacos = async ({
|
|
669
|
+
assetPath,
|
|
670
|
+
cachePath
|
|
671
|
+
}) => {
|
|
672
|
+
const mountRoot = await mkdtemp(join(tmpdir(), 'test-with-playwright-dmg-'));
|
|
673
|
+
try {
|
|
674
|
+
await execFile({
|
|
675
|
+
args: ['attach', assetPath, '-mountpoint', mountRoot, '-nobrowse', '-quiet'],
|
|
676
|
+
command: 'hdiutil'
|
|
677
|
+
});
|
|
678
|
+
const entries = await readdir(mountRoot);
|
|
679
|
+
const appName = entries.find(entry => entry.endsWith('.app'));
|
|
680
|
+
if (!appName) {
|
|
681
|
+
throw new Error(`[test-with-playwright] failed to locate .app in ${assetPath}`);
|
|
682
|
+
}
|
|
683
|
+
await execFile({
|
|
684
|
+
args: ['-R', join(mountRoot, appName), join(cachePath, appName)],
|
|
685
|
+
command: 'cp'
|
|
686
|
+
});
|
|
687
|
+
} finally {
|
|
688
|
+
try {
|
|
689
|
+
await execFile({
|
|
690
|
+
args: ['detach', mountRoot, '-quiet'],
|
|
691
|
+
command: 'hdiutil'
|
|
692
|
+
});
|
|
693
|
+
} catch {
|
|
694
|
+
// ignore detach errors during cleanup
|
|
695
|
+
}
|
|
696
|
+
await rm(mountRoot, {
|
|
697
|
+
force: true,
|
|
698
|
+
recursive: true
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
const prepareWindows = async ({
|
|
703
|
+
assetPath,
|
|
704
|
+
cachePath
|
|
705
|
+
}) => {
|
|
706
|
+
await execFile({
|
|
707
|
+
args: ['/S', `/D=${cachePath}`],
|
|
708
|
+
command: assetPath
|
|
709
|
+
});
|
|
710
|
+
};
|
|
711
|
+
const prepareArchive = async ({
|
|
712
|
+
archiveType,
|
|
713
|
+
assetPath,
|
|
714
|
+
cachePath
|
|
715
|
+
}) => {
|
|
716
|
+
await rm(cachePath, {
|
|
717
|
+
force: true,
|
|
718
|
+
recursive: true
|
|
719
|
+
});
|
|
720
|
+
await mkdir(cachePath, {
|
|
721
|
+
recursive: true
|
|
722
|
+
});
|
|
723
|
+
switch (archiveType) {
|
|
724
|
+
case 'deb':
|
|
725
|
+
await prepareLinux({
|
|
726
|
+
assetPath,
|
|
727
|
+
cachePath
|
|
728
|
+
});
|
|
729
|
+
break;
|
|
730
|
+
case 'dmg':
|
|
731
|
+
await prepareMacos({
|
|
732
|
+
assetPath,
|
|
733
|
+
cachePath
|
|
734
|
+
});
|
|
735
|
+
break;
|
|
736
|
+
case 'exe':
|
|
737
|
+
await prepareWindows({
|
|
738
|
+
assetPath,
|
|
739
|
+
cachePath
|
|
740
|
+
});
|
|
741
|
+
break;
|
|
742
|
+
default:
|
|
743
|
+
throw new Error(`[test-with-playwright] unsupported Electron archive type: ${archiveType}`);
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
const prepareElectronApp = async ({
|
|
747
|
+
cacheDir,
|
|
748
|
+
electronPath,
|
|
749
|
+
version
|
|
750
|
+
}) => {
|
|
751
|
+
if (electronPath) {
|
|
752
|
+
return resolve$1(electronPath);
|
|
753
|
+
}
|
|
754
|
+
if (!version) {
|
|
755
|
+
throw new Error('[test-with-playwright] --electron-version is required when --runtime=electron and --electron-path is not provided');
|
|
756
|
+
}
|
|
757
|
+
const {
|
|
758
|
+
archiveType,
|
|
759
|
+
assetName
|
|
760
|
+
} = resolveElectronAsset({
|
|
761
|
+
version
|
|
762
|
+
});
|
|
763
|
+
const cachePath = resolve$1(cacheDir, version, process.platform, process.arch);
|
|
764
|
+
const downloadsPath = join(cachePath, 'downloads');
|
|
765
|
+
const appPath = join(cachePath, 'app');
|
|
766
|
+
const executableMarkerPath = join(cachePath, 'executable-path.txt');
|
|
767
|
+
if (existsSync(executableMarkerPath)) {
|
|
768
|
+
const cachedExecutablePathContent = await readFile(executableMarkerPath, 'utf8');
|
|
769
|
+
const cachedExecutablePath = cachedExecutablePathContent.trim();
|
|
770
|
+
if (existsSync(cachedExecutablePath)) {
|
|
771
|
+
return cachedExecutablePath;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const assetPath = join(downloadsPath, basename(assetName));
|
|
775
|
+
await mkdir(downloadsPath, {
|
|
776
|
+
recursive: true
|
|
777
|
+
});
|
|
778
|
+
if (!existsSync(assetPath)) {
|
|
779
|
+
await downloadFile({
|
|
780
|
+
to: assetPath,
|
|
781
|
+
url: getDownloadUrl({
|
|
782
|
+
assetName,
|
|
783
|
+
version
|
|
784
|
+
})
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
await prepareArchive({
|
|
788
|
+
archiveType,
|
|
789
|
+
assetPath,
|
|
790
|
+
cachePath: appPath
|
|
791
|
+
});
|
|
792
|
+
const executablePath = await findElectronExecutable({
|
|
793
|
+
directory: appPath,
|
|
794
|
+
platform: process.platform
|
|
795
|
+
});
|
|
796
|
+
if (process.platform !== 'win32') {
|
|
797
|
+
await chmod(executablePath, 0o755);
|
|
798
|
+
}
|
|
799
|
+
await writeFile(executableMarkerPath, executablePath);
|
|
800
|
+
return executablePath;
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
const parseElectronEnv = electronEnv => {
|
|
804
|
+
const env = Object.create(null);
|
|
805
|
+
if (!electronEnv) {
|
|
806
|
+
return env;
|
|
807
|
+
}
|
|
808
|
+
for (const item of electronEnv) {
|
|
809
|
+
const index = item.indexOf('=');
|
|
810
|
+
if (index === -1) {
|
|
811
|
+
env[item] = '';
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
const key = item.slice(0, index);
|
|
815
|
+
const value = item.slice(index + 1);
|
|
816
|
+
env[key] = value;
|
|
817
|
+
}
|
|
818
|
+
return env;
|
|
819
|
+
};
|
|
820
|
+
const getBrowserRuntimeOptions = serverPath => {
|
|
821
|
+
if (serverPath) {
|
|
822
|
+
return {
|
|
823
|
+
serverPath,
|
|
824
|
+
type: 'browser'
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
type: 'browser'
|
|
829
|
+
};
|
|
830
|
+
};
|
|
831
|
+
const getRuntimeOptions = async ({
|
|
832
|
+
cwd,
|
|
833
|
+
electronArgs,
|
|
834
|
+
electronCacheDir,
|
|
835
|
+
electronEnv,
|
|
836
|
+
electronPath,
|
|
837
|
+
electronVersion,
|
|
838
|
+
runtime,
|
|
839
|
+
serverPath
|
|
840
|
+
}) => {
|
|
841
|
+
if (runtime !== undefined && runtime !== 'browser' && runtime !== 'electron') {
|
|
842
|
+
throw new Error(`[test-with-playwright] unsupported runtime: ${runtime}`);
|
|
843
|
+
}
|
|
844
|
+
if (runtime !== 'electron') {
|
|
845
|
+
return getBrowserRuntimeOptions(serverPath);
|
|
846
|
+
}
|
|
847
|
+
const cacheDir = resolve$1(cwd, electronCacheDir || '.test-with-playwright/electron');
|
|
848
|
+
const executablePath = await prepareElectronApp({
|
|
849
|
+
cacheDir,
|
|
850
|
+
...(electronPath && {
|
|
851
|
+
electronPath: resolve$1(cwd, electronPath)
|
|
852
|
+
}),
|
|
853
|
+
...(electronVersion && {
|
|
854
|
+
version: electronVersion
|
|
855
|
+
})
|
|
856
|
+
});
|
|
857
|
+
return {
|
|
858
|
+
args: electronArgs || [],
|
|
859
|
+
env: parseElectronEnv(electronEnv),
|
|
860
|
+
executablePath,
|
|
861
|
+
type: 'electron'
|
|
412
862
|
};
|
|
413
863
|
};
|
|
414
864
|
|
|
@@ -1343,7 +1793,7 @@ const runAllTests = async ({
|
|
|
1343
1793
|
filter,
|
|
1344
1794
|
headless,
|
|
1345
1795
|
onlyExtension,
|
|
1346
|
-
|
|
1796
|
+
runtimeOptions,
|
|
1347
1797
|
testPath,
|
|
1348
1798
|
testWorkerUri,
|
|
1349
1799
|
timeout,
|
|
@@ -1357,7 +1807,7 @@ const runAllTests = async ({
|
|
|
1357
1807
|
path,
|
|
1358
1808
|
stdio: 'inherit'
|
|
1359
1809
|
});
|
|
1360
|
-
await rpc.invoke(RunAllTests, onlyExtension, testPath, cwd, browser, headless, timeout,
|
|
1810
|
+
await rpc.invoke(RunAllTests, onlyExtension, testPath, cwd, browser, headless, timeout, runtimeOptions, traceFocus, filter);
|
|
1361
1811
|
await rpc.dispose();
|
|
1362
1812
|
};
|
|
1363
1813
|
|
|
@@ -1373,15 +1823,48 @@ const handleCliArgs = async ({
|
|
|
1373
1823
|
});
|
|
1374
1824
|
const {
|
|
1375
1825
|
browser,
|
|
1826
|
+
electronArgs,
|
|
1827
|
+
electronCacheDir,
|
|
1828
|
+
electronEnv,
|
|
1829
|
+
electronPath,
|
|
1830
|
+
electronVersion,
|
|
1376
1831
|
filter,
|
|
1377
1832
|
headless,
|
|
1833
|
+
help,
|
|
1378
1834
|
onlyExtension,
|
|
1835
|
+
runtime,
|
|
1379
1836
|
serverPath,
|
|
1380
1837
|
testPath,
|
|
1381
1838
|
traceFocus
|
|
1382
1839
|
} = options;
|
|
1840
|
+
if (help) {
|
|
1841
|
+
console.info(getHelpMessage());
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1383
1844
|
const timeout = 30_000;
|
|
1384
1845
|
const testWorkerUri = getTestWorkerUrl();
|
|
1846
|
+
const runtimeOptions = await getRuntimeOptions({
|
|
1847
|
+
cwd,
|
|
1848
|
+
...(electronArgs && {
|
|
1849
|
+
electronArgs
|
|
1850
|
+
}),
|
|
1851
|
+
...(electronCacheDir && {
|
|
1852
|
+
electronCacheDir
|
|
1853
|
+
}),
|
|
1854
|
+
...(electronEnv && {
|
|
1855
|
+
electronEnv
|
|
1856
|
+
}),
|
|
1857
|
+
...(electronPath && {
|
|
1858
|
+
electronPath
|
|
1859
|
+
}),
|
|
1860
|
+
...(electronVersion && {
|
|
1861
|
+
electronVersion
|
|
1862
|
+
}),
|
|
1863
|
+
runtime,
|
|
1864
|
+
...(serverPath && {
|
|
1865
|
+
serverPath
|
|
1866
|
+
})
|
|
1867
|
+
});
|
|
1385
1868
|
await runAllTests({
|
|
1386
1869
|
browser,
|
|
1387
1870
|
commandMap,
|
|
@@ -1390,7 +1873,7 @@ const handleCliArgs = async ({
|
|
|
1390
1873
|
headless,
|
|
1391
1874
|
// @ts-ignore
|
|
1392
1875
|
onlyExtension,
|
|
1393
|
-
|
|
1876
|
+
runtimeOptions,
|
|
1394
1877
|
testPath,
|
|
1395
1878
|
testWorkerUri,
|
|
1396
1879
|
timeout,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/test-with-playwright",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "CLI tool for running Playwright tests",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"main": "dist/main.js",
|
|
13
13
|
"bin": "bin/test-with-playwright.js",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lvce-editor/test-with-playwright-worker": "
|
|
16
|
-
"@lvce-editor/test-worker": "^16.
|
|
15
|
+
"@lvce-editor/test-with-playwright-worker": "19.0.0",
|
|
16
|
+
"@lvce-editor/test-worker": "^16.2.0"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|
|
19
19
|
"node": ">=24"
|