@lvce-editor/test-with-playwright 18.1.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 +469 -13
- package/package.json +2 -2
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';
|
|
@@ -115,12 +121,18 @@ const getHelpMessage = () => {
|
|
|
115
121
|
|
|
116
122
|
Options:
|
|
117
123
|
--browser=<browser> Browser to run tests in: chromium or firefox
|
|
124
|
+
--runtime=<runtime> Runtime to run tests in: browser or electron
|
|
118
125
|
--filter=<pattern> Only run tests matching the filter
|
|
119
126
|
--headless Run the browser in headless mode
|
|
120
127
|
--only-extension=<path> Path to the extension under test
|
|
121
128
|
--server-path=<path> Path to the editor server entrypoint
|
|
122
129
|
--test-path=<path> Path to the test files
|
|
123
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
|
|
124
136
|
-h, --help Show this help message
|
|
125
137
|
|
|
126
138
|
Environment:
|
|
@@ -365,14 +377,35 @@ function requireMinimist () {
|
|
|
365
377
|
var minimistExports = requireMinimist();
|
|
366
378
|
const parseArgv = /*@__PURE__*/getDefaultExportFromCjs(minimistExports);
|
|
367
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
|
+
};
|
|
368
398
|
const parseCliArgs = argv => {
|
|
369
399
|
const parsed = parseArgv(argv);
|
|
370
400
|
const result = Object.create(null);
|
|
371
401
|
if (parsed.browser) {
|
|
372
|
-
result.browser = parsed.browser;
|
|
402
|
+
result.browser = String(parsed.browser);
|
|
403
|
+
}
|
|
404
|
+
if (parsed.runtime) {
|
|
405
|
+
result.runtime = String(parsed.runtime);
|
|
373
406
|
}
|
|
374
407
|
if (parsed.filter) {
|
|
375
|
-
result.filter = parsed.filter;
|
|
408
|
+
result.filter = String(parsed.filter);
|
|
376
409
|
}
|
|
377
410
|
if (parsed.help || parsed.h) {
|
|
378
411
|
result.help = true;
|
|
@@ -381,13 +414,30 @@ const parseCliArgs = argv => {
|
|
|
381
414
|
result.headless = true;
|
|
382
415
|
}
|
|
383
416
|
if (parsed['only-extension']) {
|
|
384
|
-
result.onlyExtension = parsed['only-extension'];
|
|
417
|
+
result.onlyExtension = String(parsed['only-extension']);
|
|
385
418
|
}
|
|
386
419
|
if (parsed['test-path']) {
|
|
387
|
-
result.testPath = parsed['test-path'];
|
|
420
|
+
result.testPath = String(parsed['test-path']);
|
|
388
421
|
}
|
|
389
422
|
if (parsed['server-path']) {
|
|
390
|
-
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;
|
|
391
441
|
}
|
|
392
442
|
if (parsed['trace-focus']) {
|
|
393
443
|
result.traceFocus = true;
|
|
@@ -411,26 +461,404 @@ const defaultOptions = {
|
|
|
411
461
|
extensionPath: '',
|
|
412
462
|
headless: false,
|
|
413
463
|
help: false,
|
|
464
|
+
runtime: 'browser',
|
|
414
465
|
testPath: ''
|
|
415
466
|
};
|
|
416
467
|
const isBrowser = value => {
|
|
417
468
|
return value === 'chromium' || value === 'firefox';
|
|
418
469
|
};
|
|
470
|
+
const isRuntime = value => {
|
|
471
|
+
return value === 'browser' || value === 'electron';
|
|
472
|
+
};
|
|
419
473
|
const getOptions = ({
|
|
420
474
|
argv,
|
|
421
475
|
env
|
|
422
476
|
}) => {
|
|
423
477
|
const parsedEnv = parseEnv(env);
|
|
424
478
|
const parsedArgs = parseCliArgs(argv);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
479
|
+
if (parsedArgs.browser !== undefined && !isBrowser(parsedArgs.browser)) {
|
|
480
|
+
throw new Error(`[test-with-playwright] unsupported browser: ${parsedArgs.browser}`);
|
|
481
|
+
}
|
|
482
|
+
if (parsedArgs.runtime !== undefined && !isRuntime(parsedArgs.runtime)) {
|
|
483
|
+
throw new Error(`[test-with-playwright] unsupported runtime: ${parsedArgs.runtime}`);
|
|
428
484
|
}
|
|
485
|
+
const browser = parsedArgs.browser ?? defaultOptions.browser;
|
|
486
|
+
const runtime = parsedArgs.runtime ?? defaultOptions.runtime;
|
|
429
487
|
return {
|
|
430
488
|
...defaultOptions,
|
|
431
489
|
...parsedEnv,
|
|
432
490
|
...parsedArgs,
|
|
433
|
-
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'
|
|
434
862
|
};
|
|
435
863
|
};
|
|
436
864
|
|
|
@@ -1365,7 +1793,7 @@ const runAllTests = async ({
|
|
|
1365
1793
|
filter,
|
|
1366
1794
|
headless,
|
|
1367
1795
|
onlyExtension,
|
|
1368
|
-
|
|
1796
|
+
runtimeOptions,
|
|
1369
1797
|
testPath,
|
|
1370
1798
|
testWorkerUri,
|
|
1371
1799
|
timeout,
|
|
@@ -1379,7 +1807,7 @@ const runAllTests = async ({
|
|
|
1379
1807
|
path,
|
|
1380
1808
|
stdio: 'inherit'
|
|
1381
1809
|
});
|
|
1382
|
-
await rpc.invoke(RunAllTests, onlyExtension, testPath, cwd, browser, headless, timeout,
|
|
1810
|
+
await rpc.invoke(RunAllTests, onlyExtension, testPath, cwd, browser, headless, timeout, runtimeOptions, traceFocus, filter);
|
|
1383
1811
|
await rpc.dispose();
|
|
1384
1812
|
};
|
|
1385
1813
|
|
|
@@ -1395,10 +1823,16 @@ const handleCliArgs = async ({
|
|
|
1395
1823
|
});
|
|
1396
1824
|
const {
|
|
1397
1825
|
browser,
|
|
1826
|
+
electronArgs,
|
|
1827
|
+
electronCacheDir,
|
|
1828
|
+
electronEnv,
|
|
1829
|
+
electronPath,
|
|
1830
|
+
electronVersion,
|
|
1398
1831
|
filter,
|
|
1399
1832
|
headless,
|
|
1400
1833
|
help,
|
|
1401
1834
|
onlyExtension,
|
|
1835
|
+
runtime,
|
|
1402
1836
|
serverPath,
|
|
1403
1837
|
testPath,
|
|
1404
1838
|
traceFocus
|
|
@@ -1409,6 +1843,28 @@ const handleCliArgs = async ({
|
|
|
1409
1843
|
}
|
|
1410
1844
|
const timeout = 30_000;
|
|
1411
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
|
+
});
|
|
1412
1868
|
await runAllTests({
|
|
1413
1869
|
browser,
|
|
1414
1870
|
commandMap,
|
|
@@ -1417,7 +1873,7 @@ const handleCliArgs = async ({
|
|
|
1417
1873
|
headless,
|
|
1418
1874
|
// @ts-ignore
|
|
1419
1875
|
onlyExtension,
|
|
1420
|
-
|
|
1876
|
+
runtimeOptions,
|
|
1421
1877
|
testPath,
|
|
1422
1878
|
testWorkerUri,
|
|
1423
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,7 +12,7 @@
|
|
|
12
12
|
"main": "dist/main.js",
|
|
13
13
|
"bin": "bin/test-with-playwright.js",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lvce-editor/test-with-playwright-worker": "
|
|
15
|
+
"@lvce-editor/test-with-playwright-worker": "19.0.0",
|
|
16
16
|
"@lvce-editor/test-worker": "^16.2.0"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|