@vitest/browser-playwright 5.0.0-beta.6 → 5.0.0-rc.1
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/dist/index.js +114 -22
- package/dist/locators.js +2 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -847,12 +847,105 @@ function playwright(options = {}) {
|
|
|
847
847
|
name: "playwright",
|
|
848
848
|
supportedBrowser: playwrightBrowsers,
|
|
849
849
|
options,
|
|
850
|
+
prewarm(ctx) {
|
|
851
|
+
prewarmBrowser(ctx, options);
|
|
852
|
+
},
|
|
850
853
|
providerFactory(project) {
|
|
851
854
|
return new PlaywrightBrowserProvider(project, options);
|
|
852
855
|
}
|
|
853
856
|
});
|
|
854
857
|
}
|
|
858
|
+
// The resolved config object is passed unchanged to the eventual TestProject,
|
|
859
|
+
// so it identifies the browser this project can adopt.
|
|
860
|
+
const warmBrowsers = new WeakMap();
|
|
861
|
+
const pendingWarmBrowsers = new WeakMap();
|
|
862
|
+
// starts importing playwright and launching the browser while the node side
|
|
863
|
+
// is still creating the vite server, so the launch latency overlaps it. The
|
|
864
|
+
// launch options are resolved by the same code as the real launch — if they
|
|
865
|
+
// still differ by the time the provider opens the browser, the warm instance
|
|
866
|
+
// is discarded, so this is always safe
|
|
867
|
+
function prewarmBrowser(project, options) {
|
|
868
|
+
const browserName = project.config.browser.name;
|
|
869
|
+
if (options.connectOptions || options.persistentContext || project.vitest.config.inspector.enabled) {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if (!browserName || !playwrightBrowsers.includes(browserName)) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
if (warmBrowsers.has(project.config)) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
let pending = pendingWarmBrowsers.get(project.vitest);
|
|
879
|
+
if (!pending) {
|
|
880
|
+
const pendingBrowsers = new Set();
|
|
881
|
+
pending = pendingBrowsers;
|
|
882
|
+
pendingWarmBrowsers.set(project.vitest, pendingBrowsers);
|
|
883
|
+
// Browsers whose projects never initialize a provider (they have no test
|
|
884
|
+
// files to run) are cleaned up when Vitest closes.
|
|
885
|
+
project.vitest.onClose(() => closeWarmBrowsers(pendingBrowsers));
|
|
886
|
+
}
|
|
887
|
+
const launchOptions = resolveLaunchOptions(project.config.browser, project.vitest.config.inspector, options, browserName);
|
|
888
|
+
const entry = {
|
|
889
|
+
launchOptionsJson: JSON.stringify(launchOptions),
|
|
890
|
+
pending,
|
|
891
|
+
promise: (async () => {
|
|
892
|
+
debug?.("[%s] prewarming the browser", browserName);
|
|
893
|
+
const playwright = await import('playwright');
|
|
894
|
+
return playwright[browserName].launch(launchOptions);
|
|
895
|
+
})()
|
|
896
|
+
};
|
|
897
|
+
// if the warm launch fails, drop it so the real launch retries
|
|
898
|
+
// and surfaces the error through the normal path
|
|
899
|
+
entry.promise.catch(() => {
|
|
900
|
+
if (warmBrowsers.get(project.config) === entry) {
|
|
901
|
+
warmBrowsers.delete(project.config);
|
|
902
|
+
entry.pending.delete(entry);
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
pending.add(entry);
|
|
906
|
+
warmBrowsers.set(project.config, entry);
|
|
907
|
+
}
|
|
908
|
+
function takeWarmBrowser(config) {
|
|
909
|
+
const warm = warmBrowsers.get(config);
|
|
910
|
+
if (warm) {
|
|
911
|
+
warmBrowsers.delete(config);
|
|
912
|
+
warm.pending.delete(warm);
|
|
913
|
+
}
|
|
914
|
+
return warm;
|
|
915
|
+
}
|
|
916
|
+
async function closeWarmBrowsers(pending) {
|
|
917
|
+
const closing = Array.from(pending, (warm) => warm.promise.then((browser) => browser.close()).catch(() => {}));
|
|
918
|
+
pending.clear();
|
|
919
|
+
await Promise.all(closing);
|
|
920
|
+
}
|
|
921
|
+
function resolveLaunchOptions(browser, inspector, providerOptions, browserName) {
|
|
922
|
+
const launchOptions = {
|
|
923
|
+
...providerOptions.launchOptions,
|
|
924
|
+
headless: browser.headless
|
|
925
|
+
};
|
|
926
|
+
if (typeof browser.trace === "object" && browser.trace.tracesDir) {
|
|
927
|
+
launchOptions.tracesDir = browser.trace.tracesDir;
|
|
928
|
+
}
|
|
929
|
+
if (inspector.enabled) {
|
|
930
|
+
// NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector
|
|
931
|
+
const port = inspector.port || 9229;
|
|
932
|
+
launchOptions.args ||= [];
|
|
933
|
+
launchOptions.args.push(`--remote-debugging-port=${port}`);
|
|
934
|
+
}
|
|
935
|
+
// start Vitest UI maximized only on supported browsers
|
|
936
|
+
if (browser.ui && browserName === "chromium") {
|
|
937
|
+
if (!launchOptions.args) {
|
|
938
|
+
launchOptions.args = [];
|
|
939
|
+
}
|
|
940
|
+
if (!launchOptions.args.includes("--start-maximized") && !launchOptions.args.includes("--start-fullscreen")) {
|
|
941
|
+
launchOptions.args.push("--start-maximized");
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return launchOptions;
|
|
945
|
+
}
|
|
855
946
|
class PlaywrightBrowserProvider {
|
|
947
|
+
project;
|
|
948
|
+
options;
|
|
856
949
|
name = "playwright";
|
|
857
950
|
supportsParallelism = true;
|
|
858
951
|
browser = null;
|
|
@@ -901,36 +994,17 @@ class PlaywrightBrowserProvider {
|
|
|
901
994
|
return this.browser;
|
|
902
995
|
}
|
|
903
996
|
this.browserPromise = (async () => {
|
|
904
|
-
const options = this.project.config.browser;
|
|
905
997
|
const playwright = await import('playwright');
|
|
906
|
-
const launchOptions =
|
|
907
|
-
...this.options.launchOptions,
|
|
908
|
-
headless: options.headless
|
|
909
|
-
};
|
|
910
|
-
if (typeof options.trace === "object" && options.trace.tracesDir) {
|
|
911
|
-
launchOptions.tracesDir = options.trace?.tracesDir;
|
|
912
|
-
}
|
|
998
|
+
const launchOptions = resolveLaunchOptions(this.project.config.browser, this.project.vitest.config.inspector, this.options, this.browserName);
|
|
913
999
|
const inspector = this.project.vitest.config.inspector;
|
|
914
1000
|
if (inspector.enabled) {
|
|
915
|
-
// NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector
|
|
916
1001
|
const port = inspector.port || 9229;
|
|
917
1002
|
const host = inspector.host || "127.0.0.1";
|
|
918
|
-
launchOptions.args ||= [];
|
|
919
|
-
launchOptions.args.push(`--remote-debugging-port=${port}`);
|
|
920
1003
|
if (host !== "localhost" && host !== "127.0.0.1" && host !== "::1") {
|
|
921
1004
|
this.project.vitest.logger.warn(`Custom inspector host "${host}" will be ignored. Chromium only allows remote debugging on localhost.`);
|
|
922
1005
|
}
|
|
923
1006
|
this.project.vitest.logger.log(`Debugger listening on ws://127.0.0.1:${port}`);
|
|
924
1007
|
}
|
|
925
|
-
// start Vitest UI maximized only on supported browsers
|
|
926
|
-
if (this.project.config.browser.ui && this.browserName === "chromium") {
|
|
927
|
-
if (!launchOptions.args) {
|
|
928
|
-
launchOptions.args = [];
|
|
929
|
-
}
|
|
930
|
-
if (!launchOptions.args.includes("--start-maximized") && !launchOptions.args.includes("--start-fullscreen")) {
|
|
931
|
-
launchOptions.args.push("--start-maximized");
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
1008
|
debug?.("[%s] initializing the browser with launch options: %O", this.browserName, launchOptions);
|
|
935
1009
|
if (this.options.connectOptions) {
|
|
936
1010
|
let { wsEndpoint, headers = {}, ...connectOptions } = this.options.connectOptions;
|
|
@@ -963,6 +1037,19 @@ class PlaywrightBrowserProvider {
|
|
|
963
1037
|
});
|
|
964
1038
|
this.browser = this.persistentContext.browser();
|
|
965
1039
|
} else {
|
|
1040
|
+
const warm = takeWarmBrowser(this.project.config);
|
|
1041
|
+
if (warm && warm.launchOptionsJson === JSON.stringify(launchOptions)) {
|
|
1042
|
+
const browser = await warm.promise.catch(() => null);
|
|
1043
|
+
if (browser?.isConnected()) {
|
|
1044
|
+
debug?.("[%s] adopting the prewarmed browser", this.browserName);
|
|
1045
|
+
this.browser = browser;
|
|
1046
|
+
this.browserPromise = null;
|
|
1047
|
+
return this.browser;
|
|
1048
|
+
}
|
|
1049
|
+
} else if (warm) {
|
|
1050
|
+
debug?.("[%s] discarding the prewarmed browser, launch options changed", this.browserName);
|
|
1051
|
+
void warm.promise.then((browser) => browser.close()).catch(() => {});
|
|
1052
|
+
}
|
|
966
1053
|
this.browser = await playwright[this.browserName].launch(launchOptions);
|
|
967
1054
|
}
|
|
968
1055
|
this.browserPromise = null;
|
|
@@ -1021,8 +1108,8 @@ class PlaywrightBrowserProvider {
|
|
|
1021
1108
|
idPredicates.set(key, predicate);
|
|
1022
1109
|
await page.context().route(predicate, async (route) => {
|
|
1023
1110
|
if (module.type === "manual") {
|
|
1024
|
-
const exports
|
|
1025
|
-
const body = createManualModuleSource(module.url, exports
|
|
1111
|
+
const exports = Object.keys(await module.resolve());
|
|
1112
|
+
const body = createManualModuleSource(module.url, exports);
|
|
1026
1113
|
return route.fulfill({
|
|
1027
1114
|
body,
|
|
1028
1115
|
headers: getHeaders(this.project.browser.vite.config)
|
|
@@ -1217,6 +1304,11 @@ class PlaywrightBrowserProvider {
|
|
|
1217
1304
|
process.off("SIGTERM", this.onSIGTERM);
|
|
1218
1305
|
debug?.("[%s] closing provider", this.browserName);
|
|
1219
1306
|
this.closing = true;
|
|
1307
|
+
// a prewarmed browser that was never adopted must not outlive the provider
|
|
1308
|
+
const warm = takeWarmBrowser(this.project.config);
|
|
1309
|
+
if (warm) {
|
|
1310
|
+
void warm.promise.then((browser) => browser.close()).catch(() => {});
|
|
1311
|
+
}
|
|
1220
1312
|
if (this.browserPromise) {
|
|
1221
1313
|
await this.browserPromise;
|
|
1222
1314
|
this.browserPromise = null;
|
package/dist/locators.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/browser-playwright",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.0.0-
|
|
4
|
+
"version": "5.0.0-rc.1",
|
|
5
5
|
"description": "Browser running for Vitest using playwright",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"playwright": "*",
|
|
45
|
-
"vitest": "5.0.0-
|
|
45
|
+
"vitest": "5.0.0-rc.1"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"playwright": {
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"tinyrainbow": "^3.1.
|
|
54
|
-
"@vitest/browser": "5.0.0-
|
|
55
|
-
"@vitest/mocker": "5.0.0-
|
|
53
|
+
"tinyrainbow": "^3.1.1",
|
|
54
|
+
"@vitest/browser": "5.0.0-rc.1",
|
|
55
|
+
"@vitest/mocker": "5.0.0-rc.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"playwright": "^1.
|
|
59
|
-
"vitest": "5.0.0-
|
|
58
|
+
"playwright": "^1.62.1",
|
|
59
|
+
"vitest": "5.0.0-rc.1"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "premove dist && pnpm rollup -c",
|