@vitest/browser-playwright 4.1.0-beta.1 → 4.1.0-beta.2

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.d.ts CHANGED
@@ -31,6 +31,18 @@ interface PlaywrightProviderOptions {
31
31
  * @default 0 (no timeout)
32
32
  */
33
33
  actionTimeout?: number;
34
+ /**
35
+ * Use a persistent context instead of a regular browser context.
36
+ * This allows browser state (cookies, localStorage, DevTools settings, etc.) to persist between test runs.
37
+ * When set to `true`, the user data is stored in `./node_modules/.cache/vitest-playwright-user-data`.
38
+ * When set to a string, the value is used as the path to the user data directory.
39
+ *
40
+ * Note: This option is ignored when running tests in parallel (e.g. headless with fileParallelism enabled)
41
+ * because persistent context cannot be shared across parallel sessions.
42
+ * @default false
43
+ * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context}
44
+ */
45
+ persistentContext?: boolean | string;
34
46
  }
35
47
  declare function playwright(options?: PlaywrightProviderOptions): BrowserProviderOption<PlaywrightProviderOptions>;
36
48
  declare class PlaywrightBrowserProvider implements BrowserProvider {
@@ -39,6 +51,7 @@ declare class PlaywrightBrowserProvider implements BrowserProvider {
39
51
  name: "playwright";
40
52
  supportsParallelism: boolean;
41
53
  browser: Browser | null;
54
+ persistentContext: BrowserContext | null;
42
55
  contexts: Map<string, BrowserContext>;
43
56
  pages: Map<string, Page>;
44
57
  mocker: BrowserModuleMocker;
@@ -52,6 +65,7 @@ declare class PlaywrightBrowserProvider implements BrowserProvider {
52
65
  private openBrowser;
53
66
  private createMocker;
54
67
  private createContext;
68
+ private getContextOptions;
55
69
  getPage(sessionId: string): Page;
56
70
  getCommandsContext(sessionId: string): {
57
71
  page: Page;
@@ -60,7 +74,9 @@ declare class PlaywrightBrowserProvider implements BrowserProvider {
60
74
  readonly iframe: FrameLocator;
61
75
  };
62
76
  private openBrowserPage;
63
- openPage(sessionId: string, url: string): Promise<void>;
77
+ openPage(sessionId: string, url: string, options: {
78
+ parallel: boolean;
79
+ }): Promise<void>;
64
80
  private _throwIfClosing;
65
81
  getCDPSession(sessionid: string): Promise<CDPSession$1>;
66
82
  close(): Promise<void>;
package/dist/index.js CHANGED
@@ -753,6 +753,7 @@ class PlaywrightBrowserProvider {
753
753
  name = "playwright";
754
754
  supportsParallelism = true;
755
755
  browser = null;
756
+ persistentContext = null;
756
757
  contexts = new Map();
757
758
  pages = new Map();
758
759
  mocker;
@@ -785,7 +786,7 @@ class PlaywrightBrowserProvider {
785
786
  return Promise.allSettled(promises);
786
787
  });
787
788
  }
788
- async openBrowser() {
789
+ async openBrowser(openBrowserOptions) {
789
790
  await this._throwIfClosing();
790
791
  if (this.browserPromise) {
791
792
  debug?.("[%s] the browser is resolving, reusing the promise", this.browserName);
@@ -836,7 +837,22 @@ class PlaywrightBrowserProvider {
836
837
  }
837
838
  }
838
839
  debug?.("[%s] initializing the browser with launch options: %O", this.browserName, launchOptions);
839
- this.browser = await playwright[this.browserName].launch(launchOptions);
840
+ let persistentContextOption = this.options.persistentContext;
841
+ if (persistentContextOption && openBrowserOptions.parallel) {
842
+ persistentContextOption = false;
843
+ this.project.vitest.logger.warn(c.yellow(`The persistentContext option is ignored because tests are running in parallel.`));
844
+ }
845
+ if (persistentContextOption) {
846
+ const userDataDir = typeof this.options.persistentContext === "string" ? this.options.persistentContext : "./node_modules/.cache/vitest-playwright-user-data";
847
+ // TODO: how to avoid default "about" page?
848
+ this.persistentContext = await playwright[this.browserName].launchPersistentContext(userDataDir, {
849
+ ...launchOptions,
850
+ ...this.getContextOptions()
851
+ });
852
+ this.browser = this.persistentContext.browser();
853
+ } else {
854
+ this.browser = await playwright[this.browserName].launch(launchOptions);
855
+ }
840
856
  this.browserPromise = null;
841
857
  return this.browser;
842
858
  })();
@@ -956,29 +972,22 @@ class PlaywrightBrowserProvider {
956
972
  }
957
973
  };
958
974
  }
959
- async createContext(sessionId) {
975
+ async createContext(sessionId, openBrowserOptions) {
960
976
  await this._throwIfClosing();
961
977
  if (this.contexts.has(sessionId)) {
962
978
  debug?.("[%s][%s] the context already exists, reusing it", sessionId, this.browserName);
963
979
  return this.contexts.get(sessionId);
964
980
  }
965
- const browser = await this.openBrowser();
981
+ const browser = await this.openBrowser(openBrowserOptions);
966
982
  await this._throwIfClosing(browser);
967
983
  const actionTimeout = this.options.actionTimeout;
968
- const contextOptions = this.options.contextOptions ?? {};
969
- const options = {
970
- ...contextOptions,
971
- ignoreHTTPSErrors: true
972
- };
973
- if (this.project.config.browser.ui) {
974
- options.viewport = null;
975
- }
984
+ const options = this.getContextOptions();
976
985
  // TODO: investigate the consequences for Vitest 5
977
986
  // else {
978
987
  // if UI is disabled, keep the iframe scale to 1
979
988
  // options.viewport ??= this.project.config.browser.viewport
980
989
  // }
981
- const context = await browser.newContext(options);
990
+ const context = this.persistentContext ?? await browser.newContext(options);
982
991
  await this._throwIfClosing(context);
983
992
  if (actionTimeout != null) {
984
993
  context.setDefaultTimeout(actionTimeout);
@@ -987,6 +996,17 @@ class PlaywrightBrowserProvider {
987
996
  this.contexts.set(sessionId, context);
988
997
  return context;
989
998
  }
999
+ getContextOptions() {
1000
+ const contextOptions = this.options.contextOptions ?? {};
1001
+ const options = {
1002
+ ...contextOptions,
1003
+ ignoreHTTPSErrors: true
1004
+ };
1005
+ if (this.project.config.browser.ui) {
1006
+ options.viewport = null;
1007
+ }
1008
+ return options;
1009
+ }
990
1010
  getPage(sessionId) {
991
1011
  const page = this.pages.get(sessionId);
992
1012
  if (!page) {
@@ -1020,7 +1040,7 @@ class PlaywrightBrowserProvider {
1020
1040
  }
1021
1041
  };
1022
1042
  }
1023
- async openBrowserPage(sessionId) {
1043
+ async openBrowserPage(sessionId, options) {
1024
1044
  await this._throwIfClosing();
1025
1045
  if (this.pages.has(sessionId)) {
1026
1046
  debug?.("[%s][%s] the page already exists, closing the old one", sessionId, this.browserName);
@@ -1028,7 +1048,7 @@ class PlaywrightBrowserProvider {
1028
1048
  await page.close();
1029
1049
  this.pages.delete(sessionId);
1030
1050
  }
1031
- const context = await this.createContext(sessionId);
1051
+ const context = await this.createContext(sessionId, options);
1032
1052
  const page = await context.newPage();
1033
1053
  debug?.("[%s][%s] the page is ready", sessionId, this.browserName);
1034
1054
  await this._throwIfClosing(page);
@@ -1040,9 +1060,9 @@ class PlaywrightBrowserProvider {
1040
1060
  }
1041
1061
  return page;
1042
1062
  }
1043
- async openPage(sessionId, url) {
1063
+ async openPage(sessionId, url, options) {
1044
1064
  debug?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
1045
- const browserPage = await this.openBrowserPage(sessionId);
1065
+ const browserPage = await this.openBrowserPage(sessionId, options);
1046
1066
  debug?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
1047
1067
  await browserPage.goto(url, { timeout: 0 });
1048
1068
  await this._throwIfClosing(browserPage);
@@ -1088,7 +1108,11 @@ class PlaywrightBrowserProvider {
1088
1108
  this.browser = null;
1089
1109
  await Promise.all([...this.pages.values()].map((p) => p.close()));
1090
1110
  this.pages.clear();
1091
- await Promise.all([...this.contexts.values()].map((c) => c.close()));
1111
+ if (this.persistentContext) {
1112
+ await this.persistentContext.close();
1113
+ } else {
1114
+ await Promise.all([...this.contexts.values()].map((c) => c.close()));
1115
+ }
1092
1116
  this.contexts.clear();
1093
1117
  await browser?.close();
1094
1118
  debug?.("[%s] provider is closed", this.browserName);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/browser-playwright",
3
3
  "type": "module",
4
- "version": "4.1.0-beta.1",
4
+ "version": "4.1.0-beta.2",
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": "4.1.0-beta.1"
45
+ "vitest": "4.1.0-beta.2"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "playwright": {
@@ -51,12 +51,12 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "tinyrainbow": "^3.0.3",
54
- "@vitest/browser": "4.1.0-beta.1",
55
- "@vitest/mocker": "4.1.0-beta.1"
54
+ "@vitest/browser": "4.1.0-beta.2",
55
+ "@vitest/mocker": "4.1.0-beta.2"
56
56
  },
57
57
  "devDependencies": {
58
58
  "playwright": "^1.57.0",
59
- "vitest": "4.1.0-beta.1"
59
+ "vitest": "4.1.0-beta.2"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "premove dist && pnpm rollup -c",