From 5e5d89794f3d1dd46049b694f33e0acff6ba4489 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 13 Aug 2023 17:15:35 -0700 Subject: [PATCH 1/5] docs: Add instructions for bun/bunx --- docs/src/intro-js.md | 11 +- docs/src/test-components-js.md | 471 +++++++++++++--------- packages/playwright-core/src/cli/cli.ts | 67 +-- packages/playwright-core/src/utils/env.ts | 23 +- 4 files changed, 339 insertions(+), 233 deletions(-) diff --git a/docs/src/intro-js.md b/docs/src/intro-js.md index 30dbfb8abf087..4fbdf6c7665e4 100644 --- a/docs/src/intro-js.md +++ b/docs/src/intro-js.md @@ -22,7 +22,8 @@ Get started by installing Playwright using npm or yarn. Alternatively you can al values={[ {label: 'npm', value: 'npm'}, {label: 'yarn', value: 'yarn'}, - {label: 'pnpm', value: 'pnpm'} + {label: 'pnpm', value: 'pnpm'}, + {label: 'bun', value: 'bun'} ] }> @@ -47,6 +48,14 @@ yarn create playwright pnpm create playwright ``` + + + + +```bash +bunx create-playwright +``` + diff --git a/docs/src/test-components-js.md b/docs/src/test-components-js.md index 3aebace0ad0ce..098126542eb6b 100644 --- a/docs/src/test-components-js.md +++ b/docs/src/test-components-js.md @@ -17,16 +17,21 @@ Playwright Test can now test your components. Here is what a typical component test looks like: ```js -test('event should work', async ({ mount }) => { +test("event should work", async ({ mount }) => { let clicked = false; // Mount a component. Returns locator pointing to the component. const component = await mount( - + ); // As with any Playwright test, assert locator text. - await expect(component).toContainText('Submit'); + await expect(component).toContainText("Submit"); // Perform locator click. This will trigger the event. await component.click(); @@ -43,12 +48,13 @@ Adding Playwright Test to an existing project is easy. Below are the steps to en ### Step 1: Install Playwright Test for components for your respective framework @@ -72,8 +78,16 @@ yarn create playwright --ct pnpm dlx create-playwright --ct ``` - - + + + + +```bash +bunx create-playwright --ct +``` + + + This step creates several files in your workspace: @@ -105,25 +119,25 @@ component is mounted using this script. It can be either a `.js`, `.ts`, `.jsx` ### Step 2. Create a test file `src/App.spec.{ts,tsx}` ```js -import { test, expect } from '@playwright/experimental-ct-react'; -import App from './App'; +import { test, expect } from "@playwright/experimental-ct-react"; +import App from "./App"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(); - await expect(component).toContainText('Learn React'); + await expect(component).toContainText("Learn React"); }); ``` @@ -132,14 +146,14 @@ test('should work', async ({ mount }) => { ```js -import { test, expect } from '@playwright/experimental-ct-vue'; -import App from './App.vue'; +import { test, expect } from "@playwright/experimental-ct-vue"; +import App from "./App.vue"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText('Vite + Vue'); + await expect(component).toContainText("Vite + Vue"); }); ``` @@ -150,18 +164,18 @@ declare module '*.vue'; ``` - + ```js -import { test, expect } from '@playwright/experimental-ct-svelte'; -import App from './App.svelte'; +import { test, expect } from "@playwright/experimental-ct-svelte"; +import App from "./App.svelte"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText('Vite + Svelte'); + await expect(component).toContainText("Vite + Svelte"); }); ``` @@ -170,14 +184,14 @@ test('should work', async ({ mount }) => { ```js -import { test, expect } from '@playwright/experimental-ct-solid'; -import App from './App'; +import { test, expect } from "@playwright/experimental-ct-solid"; +import App from "./App"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(); - await expect(component).toContainText('Learn Solid'); + await expect(component).toContainText("Learn Solid"); }); ``` @@ -206,145 +220,198 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let This includes any config that needs to be run before or after mounting the component. An example of configuring a router is provided below: - + - ```js title="playwright/index.tsx" - import { beforeMount, afterMount } from '@playwright/experimental-ct-react/hooks'; - import { BrowserRouter } from 'react-router-dom'; +```js title="playwright/index.tsx" +import { + beforeMount, + afterMount, +} from "@playwright/experimental-ct-react/hooks"; +import { BrowserRouter } from "react-router-dom"; - export type HooksConfig = { - enableRouting?: boolean; - } +export type HooksConfig = { + enableRouting?: boolean, +}; - beforeMount(async ({ App, hooksConfig }) => { +beforeMount < + HooksConfig > + (async ({ App, hooksConfig }) => { if (hooksConfig?.enableRouting) - return ; + return ( + + + + ); }); - ``` +``` - #### In your test file: +#### In your test file: - ```js title="src/pages/ProductsPage.spec.tsx" - import { test, expect } from '@playwright/experimental-ct-react'; - import type { HooksConfig } from '@playwright/test'; - import { ProductsPage } from './pages/ProductsPage'; +```js title="src/pages/ProductsPage.spec.tsx" +import { test, expect } from "@playwright/experimental-ct-react"; +import type { HooksConfig } from "@playwright/test"; +import { ProductsPage } from "./pages/ProductsPage"; - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(, { +test("configure routing through hooks config", async ({ page, mount }) => { + const component = + (await mount) < + HooksConfig > + ((), + { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` + await expect(component.getByRole("link")).toHaveAttribute( + "href", + "/products/42" + ); +}); +``` - ```js title="playwright/index.tsx" - import { beforeMount, afterMount } from '@playwright/experimental-ct-solid/hooks'; - import { Router } from '@solidjs/router'; +```js title="playwright/index.tsx" +import { + beforeMount, + afterMount, +} from "@playwright/experimental-ct-solid/hooks"; +import { Router } from "@solidjs/router"; - export type HooksConfig = { - enableRouting?: boolean; - } +export type HooksConfig = { + enableRouting?: boolean, +}; - beforeMount(async ({ App, hooksConfig }) => { +beforeMount < + HooksConfig > + (async ({ App, hooksConfig }) => { if (hooksConfig?.enableRouting) - return ; + return ( + + + + ); }); - ``` +``` - #### In your test file: +#### In your test file: - ```js title="src/pages/ProductsPage.spec.tsx" - import { test, expect } from '@playwright/experimental-ct-solid'; - import type { HooksConfig } from '@playwright/test'; - import { ProductsPage } from './pages/ProductsPage'; +```js title="src/pages/ProductsPage.spec.tsx" +import { test, expect } from "@playwright/experimental-ct-solid"; +import type { HooksConfig } from "@playwright/test"; +import { ProductsPage } from "./pages/ProductsPage"; - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(, { +test("configure routing through hooks config", async ({ page, mount }) => { + const component = + (await mount) < + HooksConfig > + ((), + { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` + await expect(component.getByRole("link")).toHaveAttribute( + "href", + "/products/42" + ); +}); +``` - ```js title="playwright/index.ts" - import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks'; - import { router } from '../src/router'; +```js title="playwright/index.ts" +import { beforeMount, afterMount } from "@playwright/experimental-ct-vue/hooks"; +import { router } from "../src/router"; - export type HooksConfig = { - enableRouting?: boolean; - } +export type HooksConfig = { + enableRouting?: boolean, +}; - beforeMount(async ({ app, hooksConfig }) => { - if (hooksConfig?.enableRouting) - app.use(router); +beforeMount < + HooksConfig > + (async ({ app, hooksConfig }) => { + if (hooksConfig?.enableRouting) app.use(router); }); - ``` +``` - #### In your test file: +#### In your test file: - ```js title="src/pages/ProductsPage.spec.ts" - import { test, expect } from '@playwright/experimental-ct-vue'; - import type { HooksConfig } from '@playwright/test'; - import ProductsPage from './pages/ProductsPage.vue'; +```js title="src/pages/ProductsPage.spec.ts" +import { test, expect } from "@playwright/experimental-ct-vue"; +import type { HooksConfig } from "@playwright/test"; +import ProductsPage from "./pages/ProductsPage.vue"; - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(ProductsPage, { +test("configure routing through hooks config", async ({ page, mount }) => { + const component = + (await mount) < + HooksConfig > + (ProductsPage, + { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` + await expect(component.getByRole("link")).toHaveAttribute( + "href", + "/products/42" + ); +}); +``` - - ```js title="playwright/index.ts" - import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks'; - import Router from 'vue-router'; - import { router } from '../src/router'; - export type HooksConfig = { - enableRouting?: boolean; - } +```js title="playwright/index.ts" +import { + beforeMount, + afterMount, +} from "@playwright/experimental-ct-vue2/hooks"; +import Router from "vue-router"; +import { router } from "../src/router"; + +export type HooksConfig = { + enableRouting?: boolean, +}; - beforeMount(async ({ app, hooksConfig }) => { +beforeMount < + HooksConfig > + (async ({ app, hooksConfig }) => { if (hooksConfig?.enableRouting) { Vue.use(Router); - return { router } + return { router }; } }); - ``` - #### In your test file: +``` - ```js title="src/pages/ProductsPage.spec.ts" - import { test, expect } from '@playwright/experimental-ct-vue2'; - import type { HooksConfig } from '@playwright/test'; - import ProductsPage from './pages/ProductsPage.vue'; +#### In your test file: - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(ProductsPage, { +```js title="src/pages/ProductsPage.spec.ts" +import { test, expect } from "@playwright/experimental-ct-vue2"; +import type { HooksConfig } from "@playwright/test"; +import ProductsPage from "./pages/ProductsPage.vue"; + +test("configure routing through hooks config", async ({ page, mount }) => { + const component = + (await mount) < + HooksConfig > + (ProductsPage, + { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` + await expect(component.getByRole("link")).toHaveAttribute( + "href", + "/products/42" + ); +}); +``` @@ -374,11 +441,11 @@ As per above, you can only import your components from your test file. If you ha At this point, Playwright is bundler-agnostic, so it is not reusing your existing Vite config. Your config might have a lot of things we won't be able to reuse. So for now, you would copy your path mappings and other high level settings into the `ctViteConfig` property of Playwright config. ```js -import { defineConfig } from '@playwright/experimental-ct-react'; +import { defineConfig } from "@playwright/experimental-ct-react"; export default defineConfig({ use: { - ctViteConfig: { + ctViteConfig: { // ... }, }, @@ -388,7 +455,7 @@ export default defineConfig({ ### Q) What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`? ```js -test('…', async ({ mount, page, context }) => { +test("…", async ({ mount, page, context }) => { // … }); ``` @@ -396,25 +463,25 @@ test('…', async ({ mount, page, context }) => { `@playwright/experimental-ct-{react,svelte,vue,solid}` wrap `@playwright/test` to provide an additional built-in component-testing specific fixture called `mount`: ```js -import { test, expect } from '@playwright/experimental-ct-react'; -import HelloWorld from './HelloWorld'; +import { test, expect } from "@playwright/experimental-ct-react"; +import HelloWorld from "./HelloWorld"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(); - await expect(component).toContainText('Greetings'); + await expect(component).toContainText("Greetings"); }); ``` @@ -423,38 +490,38 @@ test('should work', async ({ mount }) => { ```js -import { test, expect } from '@playwright/experimental-ct-vue'; -import HelloWorld from './HelloWorld.vue'; +import { test, expect } from "@playwright/experimental-ct-vue"; +import HelloWorld from "./HelloWorld.vue"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(HelloWorld, { props: { - msg: 'Greetings', + msg: "Greetings", }, }); - await expect(component).toContainText('Greetings'); + await expect(component).toContainText("Greetings"); }); ``` - + ```js -import { test, expect } from '@playwright/experimental-ct-svelte'; -import HelloWorld from './HelloWorld.svelte'; +import { test, expect } from "@playwright/experimental-ct-svelte"; +import HelloWorld from "./HelloWorld.svelte"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(HelloWorld, { props: { - msg: 'Greetings', + msg: "Greetings", }, }); - await expect(component).toContainText('Greetings'); + await expect(component).toContainText("Greetings"); }); ``` @@ -463,14 +530,14 @@ test('should work', async ({ mount }) => { ```js -import { test, expect } from '@playwright/experimental-ct-solid'; -import HelloWorld from './HelloWorld'; +import { test, expect } from "@playwright/experimental-ct-solid"; +import HelloWorld from "./HelloWorld"; test.use({ viewport: { width: 500, height: 500 } }); -test('should work', async ({ mount }) => { +test("should work", async ({ mount }) => { const component = await mount(); - await expect(component).toContainText('Greetings'); + await expect(component).toContainText("Greetings"); }); ``` @@ -513,43 +580,43 @@ await mount(); You can specify plugins via Vite config for testing settings. Note that once you start specifying plugins, you are responsible for specifying the framework plugin as well, `vue()` in this case: ```js -import { defineConfig, devices } from '@playwright/experimental-ct-vue'; +import { defineConfig, devices } from "@playwright/experimental-ct-vue"; -import { resolve } from 'path'; -import vue from '@vitejs/plugin-vue'; -import AutoImport from 'unplugin-auto-import/vite'; -import Components from 'unplugin-vue-components/vite'; +import { resolve } from "path"; +import vue from "@vitejs/plugin-vue"; +import AutoImport from "unplugin-auto-import/vite"; +import Components from "unplugin-vue-components/vite"; export default defineConfig({ - testDir: './tests/component', + testDir: "./tests/component", use: { - trace: 'on-first-retry', + trace: "on-first-retry", ctViteConfig: { plugins: [ vue(), AutoImport({ imports: [ - 'vue', - 'vue-router', - '@vueuse/head', - 'pinia', + "vue", + "vue-router", + "@vueuse/head", + "pinia", { - '@/store': ['useStore'], + "@/store": ["useStore"], }, ], - dts: 'src/auto-imports.d.ts', + dts: "src/auto-imports.d.ts", eslintrc: { enabled: true, }, }), Components({ - dirs: ['src/components'], - extensions: ['vue'], + dirs: ["src/components"], + extensions: ["vue"], }), ], resolve: { alias: { - '@': resolve(__dirname, './src'), + "@": resolve(__dirname, "./src"), }, }, }, @@ -562,44 +629,50 @@ export default defineConfig({ Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis: ```js title="playwright/index.ts" -import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks'; -import { createTestingPinia } from '@pinia/testing'; -import type { StoreState } from 'pinia'; -import type { useStore } from '../src/store'; +import { beforeMount, afterMount } from "@playwright/experimental-ct-vue/hooks"; +import { createTestingPinia } from "@pinia/testing"; +import type { StoreState } from "pinia"; +import type { useStore } from "../src/store"; export type HooksConfig = { - store?: StoreState>; -} - -beforeMount(async ({ hooksConfig }) => { - createTestingPinia({ - initialState: hooksConfig?.store, - /** - * Use http intercepting to mock api calls instead: - * https://playwright.dev/docs/mock#mock-api-requests - */ - stubActions: false, - createSpy(args) { - console.log('spy', args) - return () => console.log('spy-returns') - }, + store?: StoreState>, +}; + +beforeMount < + HooksConfig > + (async ({ hooksConfig }) => { + createTestingPinia({ + initialState: hooksConfig?.store, + /** + * Use http intercepting to mock api calls instead: + * https://playwright.dev/docs/mock#mock-api-requests + */ + stubActions: false, + createSpy(args) { + console.log("spy", args); + return () => console.log("spy-returns"); + }, + }); }); -}); ``` - #### In your test file: +#### In your test file: ```js title="src/pinia.spec.ts" -import { test, expect } from '@playwright/experimental-ct-vue'; -import type { HooksConfig } from '@playwright/test'; -import Store from './Store.vue'; - -test('override initialState ', async ({ mount }) => { - const component = await mount(Store, { - hooksConfig: { - store: { name: 'override initialState' } - } - }); - await expect(component).toContainText('override initialState'); +import { test, expect } from "@playwright/experimental-ct-vue"; +import type { HooksConfig } from "@playwright/test"; +import Store from "./Store.vue"; + +test("override initialState ", async ({ mount }) => { + const component = + (await mount) < + HooksConfig > + (Store, + { + hooksConfig: { + store: { name: "override initialState" }, + }, + }); + await expect(component).toContainText("override initialState"); }); ``` diff --git a/packages/playwright-core/src/cli/cli.ts b/packages/playwright-core/src/cli/cli.ts index ac3cacff9d634..cb376123276fe 100755 --- a/packages/playwright-core/src/cli/cli.ts +++ b/packages/playwright-core/src/cli/cli.ts @@ -18,50 +18,69 @@ /* eslint-disable no-console */ -import { getPackageManager, gracefullyProcessExitDoNotHang } from '../utils'; -import program from './program'; +import { getPackageManager, gracefullyProcessExitDoNotHang } from "../utils"; +import program from "./program"; function printPlaywrightTestError(command: string) { const packages: string[] = []; - for (const pkg of ['playwright', 'playwright-chromium', 'playwright-firefox', 'playwright-webkit']) { + for (const pkg of [ + "playwright", + "playwright-chromium", + "playwright-firefox", + "playwright-webkit", + ]) { try { require.resolve(pkg); packages.push(pkg); - } catch (e) { - } + } catch (e) {} } - if (!packages.length) - packages.push('playwright'); + if (!packages.length) packages.push("playwright"); const packageManager = getPackageManager(); - if (packageManager === 'yarn') { - console.error(`Please install @playwright/test package before running "yarn playwright ${command}"`); - console.error(` yarn remove ${packages.join(' ')}`); - console.error(' yarn add -D @playwright/test'); - } else if (packageManager === 'pnpm') { - console.error(`Please install @playwright/test package before running "pnpm exec playwright ${command}"`); - console.error(` pnpm remove ${packages.join(' ')}`); - console.error(' pnpm add -D @playwright/test'); + if (packageManager === "yarn") { + console.error( + `Please install @playwright/test package before running "yarn playwright ${command}"` + ); + console.error(` yarn remove ${packages.join(" ")}`); + console.error(" yarn add -D @playwright/test"); + } else if (packageManager === "pnpm") { + console.error( + `Please install @playwright/test package before running "pnpm exec playwright ${command}"` + ); + console.error(` pnpm remove ${packages.join(" ")}`); + console.error(" pnpm add -D @playwright/test"); + } else if (packageManager === "bun") { + console.error( + `Please install @playwright/test package before running "bunx playwright ${command}"` + ); + console.error(` bun remove ${packages.join(" ")}`); + console.error(" bun add -D @playwright/test"); } else { - console.error(`Please install @playwright/test package before running "npx playwright ${command}"`); - console.error(` npm uninstall ${packages.join(' ')}`); - console.error(' npm install -D @playwright/test'); + console.error( + `Please install @playwright/test package before running "npx playwright ${command}"` + ); + console.error(` npm uninstall ${packages.join(" ")}`); + console.error(" npm install -D @playwright/test"); } } { - const command = program.command('test').allowUnknownOption(true); - command.description('Run tests with Playwright Test. Available in @playwright/test package.'); + const command = program.command("test").allowUnknownOption(true); + command.description( + "Run tests with Playwright Test. Available in @playwright/test package." + ); command.action(async () => { - printPlaywrightTestError('test'); + printPlaywrightTestError("test"); gracefullyProcessExitDoNotHang(1); }); } { - const command = program.command('show-report').allowUnknownOption(true); - command.description('Show Playwright Test HTML report. Available in @playwright/test package.'); + const command = program.command("show-report").allowUnknownOption(true); + command.description( + "Show Playwright Test HTML report. Available in @playwright/test package." + ); command.action(async () => { - printPlaywrightTestError('show-report'); + printPlaywrightTestError("show-report"); gracefullyProcessExitDoNotHang(1); }); } diff --git a/packages/playwright-core/src/utils/env.ts b/packages/playwright-core/src/utils/env.ts index 27f10f384b126..7cbfe24ae153c 100644 --- a/packages/playwright-core/src/utils/env.ts +++ b/packages/playwright-core/src/utils/env.ts @@ -16,21 +16,26 @@ export function getFromENV(name: string): string | undefined { let value = process.env[name]; - value = value === undefined ? process.env[`npm_config_${name.toLowerCase()}`] : value; - value = value === undefined ? process.env[`npm_package_config_${name.toLowerCase()}`] : value; + value = + value === undefined + ? process.env[`npm_config_${name.toLowerCase()}`] + : value; + value = + value === undefined + ? process.env[`npm_package_config_${name.toLowerCase()}`] + : value; return value; } export function getAsBooleanFromENV(name: string): boolean { const value = getFromENV(name); - return !!value && value !== 'false' && value !== '0'; + return !!value && value !== "false" && value !== "0"; } export function getPackageManager() { - const env = process.env.npm_config_user_agent || ''; - if (env.includes('yarn')) - return 'yarn'; - if (env.includes('pnpm')) - return 'pnpm'; - return 'npm'; + const env = process.env.npm_config_user_agent || ""; + if (env.includes("yarn")) return "yarn"; + if (env.includes("pnpm")) return "pnpm"; + if (env.includes("bun")) return "bun"; + return "npm"; } From 91bb1546a4931955a4f94f99b30c2471d314c41a Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 13 Aug 2023 17:18:51 -0700 Subject: [PATCH 2/5] Undo autoformatting --- docs/src/test-components-js.md | 452 ++++++++++++++------------------- 1 file changed, 194 insertions(+), 258 deletions(-) diff --git a/docs/src/test-components-js.md b/docs/src/test-components-js.md index 098126542eb6b..b96df3ba63121 100644 --- a/docs/src/test-components-js.md +++ b/docs/src/test-components-js.md @@ -17,21 +17,16 @@ Playwright Test can now test your components. Here is what a typical component test looks like: ```js -test("event should work", async ({ mount }) => { +test('event should work', async ({ mount }) => { let clicked = false; // Mount a component. Returns locator pointing to the component. const component = await mount( - + ); // As with any Playwright test, assert locator text. - await expect(component).toContainText("Submit"); + await expect(component).toContainText('Submit'); // Perform locator click. This will trigger the event. await component.click(); @@ -48,13 +43,13 @@ Adding Playwright Test to an existing project is easy. Below are the steps to en ### Step 1: Install Playwright Test for components for your respective framework @@ -119,25 +114,25 @@ component is mounted using this script. It can be either a `.js`, `.ts`, `.jsx` ### Step 2. Create a test file `src/App.spec.{ts,tsx}` ```js -import { test, expect } from "@playwright/experimental-ct-react"; -import App from "./App"; +import { test, expect } from '@playwright/experimental-ct-react'; +import App from './App'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(); - await expect(component).toContainText("Learn React"); + await expect(component).toContainText('Learn React'); }); ``` @@ -146,14 +141,14 @@ test("should work", async ({ mount }) => { ```js -import { test, expect } from "@playwright/experimental-ct-vue"; -import App from "./App.vue"; +import { test, expect } from '@playwright/experimental-ct-vue'; +import App from './App.vue'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText("Vite + Vue"); + await expect(component).toContainText('Vite + Vue'); }); ``` @@ -168,14 +163,14 @@ declare module '*.vue'; ```js -import { test, expect } from "@playwright/experimental-ct-svelte"; -import App from "./App.svelte"; +import { test, expect } from '@playwright/experimental-ct-svelte'; +import App from './App.svelte'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText("Vite + Svelte"); + await expect(component).toContainText('Vite + Svelte'); }); ``` @@ -184,14 +179,14 @@ test("should work", async ({ mount }) => { ```js -import { test, expect } from "@playwright/experimental-ct-solid"; -import App from "./App"; +import { test, expect } from '@playwright/experimental-ct-solid'; +import App from './App'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(); - await expect(component).toContainText("Learn Solid"); + await expect(component).toContainText('Learn Solid'); }); ``` @@ -220,198 +215,145 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let This includes any config that needs to be run before or after mounting the component. An example of configuring a router is provided below: - + -```js title="playwright/index.tsx" -import { - beforeMount, - afterMount, -} from "@playwright/experimental-ct-react/hooks"; -import { BrowserRouter } from "react-router-dom"; + ```js title="playwright/index.tsx" + import { beforeMount, afterMount } from '@playwright/experimental-ct-react/hooks'; + import { BrowserRouter } from 'react-router-dom'; -export type HooksConfig = { - enableRouting?: boolean, -}; + export type HooksConfig = { + enableRouting?: boolean; + } -beforeMount < - HooksConfig > - (async ({ App, hooksConfig }) => { + beforeMount(async ({ App, hooksConfig }) => { if (hooksConfig?.enableRouting) - return ( - - - - ); + return ; }); -``` + ``` -#### In your test file: + #### In your test file: -```js title="src/pages/ProductsPage.spec.tsx" -import { test, expect } from "@playwright/experimental-ct-react"; -import type { HooksConfig } from "@playwright/test"; -import { ProductsPage } from "./pages/ProductsPage"; + ```js title="src/pages/ProductsPage.spec.tsx" + import { test, expect } from '@playwright/experimental-ct-react'; + import type { HooksConfig } from '@playwright/test'; + import { ProductsPage } from './pages/ProductsPage'; -test("configure routing through hooks config", async ({ page, mount }) => { - const component = - (await mount) < - HooksConfig > - ((), - { + test('configure routing through hooks config', async ({ page, mount }) => { + const component = await mount(, { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole("link")).toHaveAttribute( - "href", - "/products/42" - ); -}); -``` + await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); + }); + ``` -```js title="playwright/index.tsx" -import { - beforeMount, - afterMount, -} from "@playwright/experimental-ct-solid/hooks"; -import { Router } from "@solidjs/router"; + ```js title="playwright/index.tsx" + import { beforeMount, afterMount } from '@playwright/experimental-ct-solid/hooks'; + import { Router } from '@solidjs/router'; -export type HooksConfig = { - enableRouting?: boolean, -}; + export type HooksConfig = { + enableRouting?: boolean; + } -beforeMount < - HooksConfig > - (async ({ App, hooksConfig }) => { + beforeMount(async ({ App, hooksConfig }) => { if (hooksConfig?.enableRouting) - return ( - - - - ); + return ; }); -``` + ``` -#### In your test file: + #### In your test file: -```js title="src/pages/ProductsPage.spec.tsx" -import { test, expect } from "@playwright/experimental-ct-solid"; -import type { HooksConfig } from "@playwright/test"; -import { ProductsPage } from "./pages/ProductsPage"; + ```js title="src/pages/ProductsPage.spec.tsx" + import { test, expect } from '@playwright/experimental-ct-solid'; + import type { HooksConfig } from '@playwright/test'; + import { ProductsPage } from './pages/ProductsPage'; -test("configure routing through hooks config", async ({ page, mount }) => { - const component = - (await mount) < - HooksConfig > - ((), - { + test('configure routing through hooks config', async ({ page, mount }) => { + const component = await mount(, { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole("link")).toHaveAttribute( - "href", - "/products/42" - ); -}); -``` + await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); + }); + ``` -```js title="playwright/index.ts" -import { beforeMount, afterMount } from "@playwright/experimental-ct-vue/hooks"; -import { router } from "../src/router"; + ```js title="playwright/index.ts" + import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks'; + import { router } from '../src/router'; -export type HooksConfig = { - enableRouting?: boolean, -}; + export type HooksConfig = { + enableRouting?: boolean; + } -beforeMount < - HooksConfig > - (async ({ app, hooksConfig }) => { - if (hooksConfig?.enableRouting) app.use(router); + beforeMount(async ({ app, hooksConfig }) => { + if (hooksConfig?.enableRouting) + app.use(router); }); -``` + ``` -#### In your test file: + #### In your test file: -```js title="src/pages/ProductsPage.spec.ts" -import { test, expect } from "@playwright/experimental-ct-vue"; -import type { HooksConfig } from "@playwright/test"; -import ProductsPage from "./pages/ProductsPage.vue"; + ```js title="src/pages/ProductsPage.spec.ts" + import { test, expect } from '@playwright/experimental-ct-vue'; + import type { HooksConfig } from '@playwright/test'; + import ProductsPage from './pages/ProductsPage.vue'; -test("configure routing through hooks config", async ({ page, mount }) => { - const component = - (await mount) < - HooksConfig > - (ProductsPage, - { + test('configure routing through hooks config', async ({ page, mount }) => { + const component = await mount(ProductsPage, { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole("link")).toHaveAttribute( - "href", - "/products/42" - ); -}); -``` + await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); + }); + ``` -```js title="playwright/index.ts" -import { - beforeMount, - afterMount, -} from "@playwright/experimental-ct-vue2/hooks"; -import Router from "vue-router"; -import { router } from "../src/router"; + ```js title="playwright/index.ts" + import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks'; + import Router from 'vue-router'; + import { router } from '../src/router'; -export type HooksConfig = { - enableRouting?: boolean, -}; + export type HooksConfig = { + enableRouting?: boolean; + } -beforeMount < - HooksConfig > - (async ({ app, hooksConfig }) => { + beforeMount(async ({ app, hooksConfig }) => { if (hooksConfig?.enableRouting) { Vue.use(Router); - return { router }; + return { router } } }); -``` + ``` + #### In your test file: -#### In your test file: + ```js title="src/pages/ProductsPage.spec.ts" + import { test, expect } from '@playwright/experimental-ct-vue2'; + import type { HooksConfig } from '@playwright/test'; + import ProductsPage from './pages/ProductsPage.vue'; -```js title="src/pages/ProductsPage.spec.ts" -import { test, expect } from "@playwright/experimental-ct-vue2"; -import type { HooksConfig } from "@playwright/test"; -import ProductsPage from "./pages/ProductsPage.vue"; - -test("configure routing through hooks config", async ({ page, mount }) => { - const component = - (await mount) < - HooksConfig > - (ProductsPage, - { + test('configure routing through hooks config', async ({ page, mount }) => { + const component = await mount(ProductsPage, { hooksConfig: { enableRouting: true }, }); - await expect(component.getByRole("link")).toHaveAttribute( - "href", - "/products/42" - ); -}); -``` + await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); + }); + ``` @@ -441,7 +383,7 @@ As per above, you can only import your components from your test file. If you ha At this point, Playwright is bundler-agnostic, so it is not reusing your existing Vite config. Your config might have a lot of things we won't be able to reuse. So for now, you would copy your path mappings and other high level settings into the `ctViteConfig` property of Playwright config. ```js -import { defineConfig } from "@playwright/experimental-ct-react"; +import { defineConfig } from '@playwright/experimental-ct-react'; export default defineConfig({ use: { @@ -455,7 +397,7 @@ export default defineConfig({ ### Q) What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`? ```js -test("…", async ({ mount, page, context }) => { +test('…', async ({ mount, page, context }) => { // … }); ``` @@ -463,25 +405,25 @@ test("…", async ({ mount, page, context }) => { `@playwright/experimental-ct-{react,svelte,vue,solid}` wrap `@playwright/test` to provide an additional built-in component-testing specific fixture called `mount`: ```js -import { test, expect } from "@playwright/experimental-ct-react"; -import HelloWorld from "./HelloWorld"; +import { test, expect } from '@playwright/experimental-ct-react'; +import HelloWorld from './HelloWorld'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(); - await expect(component).toContainText("Greetings"); + await expect(component).toContainText('Greetings'); }); ``` @@ -490,18 +432,18 @@ test("should work", async ({ mount }) => { ```js -import { test, expect } from "@playwright/experimental-ct-vue"; -import HelloWorld from "./HelloWorld.vue"; +import { test, expect } from '@playwright/experimental-ct-vue'; +import HelloWorld from './HelloWorld.vue'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(HelloWorld, { props: { - msg: "Greetings", + msg: 'Greetings', }, }); - await expect(component).toContainText("Greetings"); + await expect(component).toContainText('Greetings'); }); ``` @@ -510,18 +452,18 @@ test("should work", async ({ mount }) => { ```js -import { test, expect } from "@playwright/experimental-ct-svelte"; -import HelloWorld from "./HelloWorld.svelte"; +import { test, expect } from '@playwright/experimental-ct-svelte'; +import HelloWorld from './HelloWorld.svelte'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(HelloWorld, { props: { - msg: "Greetings", + msg: 'Greetings', }, }); - await expect(component).toContainText("Greetings"); + await expect(component).toContainText('Greetings'); }); ``` @@ -530,14 +472,14 @@ test("should work", async ({ mount }) => { ```js -import { test, expect } from "@playwright/experimental-ct-solid"; -import HelloWorld from "./HelloWorld"; +import { test, expect } from '@playwright/experimental-ct-solid'; +import HelloWorld from './HelloWorld'; test.use({ viewport: { width: 500, height: 500 } }); -test("should work", async ({ mount }) => { +test('should work', async ({ mount }) => { const component = await mount(); - await expect(component).toContainText("Greetings"); + await expect(component).toContainText('Greetings'); }); ``` @@ -580,43 +522,43 @@ await mount(); You can specify plugins via Vite config for testing settings. Note that once you start specifying plugins, you are responsible for specifying the framework plugin as well, `vue()` in this case: ```js -import { defineConfig, devices } from "@playwright/experimental-ct-vue"; +import { defineConfig, devices } from '@playwright/experimental-ct-vue'; -import { resolve } from "path"; -import vue from "@vitejs/plugin-vue"; -import AutoImport from "unplugin-auto-import/vite"; -import Components from "unplugin-vue-components/vite"; +import { resolve } from 'path'; +import vue from '@vitejs/plugin-vue'; +import AutoImport from 'unplugin-auto-import/vite'; +import Components from 'unplugin-vue-components/vite'; export default defineConfig({ - testDir: "./tests/component", + testDir: './tests/component', use: { - trace: "on-first-retry", + trace: 'on-first-retry', ctViteConfig: { plugins: [ vue(), AutoImport({ imports: [ - "vue", - "vue-router", - "@vueuse/head", - "pinia", + 'vue', + 'vue-router', + '@vueuse/head', + 'pinia', { - "@/store": ["useStore"], + '@/store': ['useStore'], }, ], - dts: "src/auto-imports.d.ts", + dts: 'src/auto-imports.d.ts', eslintrc: { enabled: true, }, }), Components({ - dirs: ["src/components"], - extensions: ["vue"], + dirs: ['src/components'], + extensions: ['vue'], }), ], resolve: { alias: { - "@": resolve(__dirname, "./src"), + '@': resolve(__dirname, './src'), }, }, }, @@ -629,50 +571,44 @@ export default defineConfig({ Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis: ```js title="playwright/index.ts" -import { beforeMount, afterMount } from "@playwright/experimental-ct-vue/hooks"; -import { createTestingPinia } from "@pinia/testing"; -import type { StoreState } from "pinia"; -import type { useStore } from "../src/store"; +import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks'; +import { createTestingPinia } from '@pinia/testing'; +import type { StoreState } from 'pinia'; +import type { useStore } from '../src/store'; export type HooksConfig = { - store?: StoreState>, -}; - -beforeMount < - HooksConfig > - (async ({ hooksConfig }) => { - createTestingPinia({ - initialState: hooksConfig?.store, - /** - * Use http intercepting to mock api calls instead: - * https://playwright.dev/docs/mock#mock-api-requests - */ - stubActions: false, - createSpy(args) { - console.log("spy", args); - return () => console.log("spy-returns"); - }, - }); + store?: StoreState>; +} + +beforeMount(async ({ hooksConfig }) => { + createTestingPinia({ + initialState: hooksConfig?.store, + /** + * Use http intercepting to mock api calls instead: + * https://playwright.dev/docs/mock#mock-api-requests + */ + stubActions: false, + createSpy(args) { + console.log('spy', args) + return () => console.log('spy-returns') + }, }); +}); ``` -#### In your test file: + #### In your test file: ```js title="src/pinia.spec.ts" -import { test, expect } from "@playwright/experimental-ct-vue"; -import type { HooksConfig } from "@playwright/test"; -import Store from "./Store.vue"; - -test("override initialState ", async ({ mount }) => { - const component = - (await mount) < - HooksConfig > - (Store, - { - hooksConfig: { - store: { name: "override initialState" }, - }, - }); - await expect(component).toContainText("override initialState"); +import { test, expect } from '@playwright/experimental-ct-vue'; +import type { HooksConfig } from '@playwright/test'; +import Store from './Store.vue'; + +test('override initialState ', async ({ mount }) => { + const component = await mount(Store, { + hooksConfig: { + store: { name: 'override initialState' } + } + }); + await expect(component).toContainText('override initialState'); }); ``` From de65a8dd1caad5025745976e2343cde9f5a9772e Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 13 Aug 2023 17:19:13 -0700 Subject: [PATCH 3/5] Undo autoformatting --- packages/playwright-core/src/utils/env.ts | 24 ++++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/playwright-core/src/utils/env.ts b/packages/playwright-core/src/utils/env.ts index 7cbfe24ae153c..5add07a41f926 100644 --- a/packages/playwright-core/src/utils/env.ts +++ b/packages/playwright-core/src/utils/env.ts @@ -16,26 +16,22 @@ export function getFromENV(name: string): string | undefined { let value = process.env[name]; - value = - value === undefined - ? process.env[`npm_config_${name.toLowerCase()}`] - : value; - value = - value === undefined - ? process.env[`npm_package_config_${name.toLowerCase()}`] - : value; + value = value === undefined ? process.env[`npm_config_${name.toLowerCase()}`] : value; + value = value === undefined ? process.env[`npm_package_config_${name.toLowerCase()}`] : value; return value; } export function getAsBooleanFromENV(name: string): boolean { const value = getFromENV(name); - return !!value && value !== "false" && value !== "0"; + return !!value && value !== 'false' && value !== '0'; } export function getPackageManager() { - const env = process.env.npm_config_user_agent || ""; - if (env.includes("yarn")) return "yarn"; - if (env.includes("pnpm")) return "pnpm"; - if (env.includes("bun")) return "bun"; - return "npm"; + const env = process.env.npm_config_user_agent || ''; + if (env.includes('yarn')) + return 'yarn'; + if (env.includes('pnpm')) + return 'pnpm'; +if (env.includes("bun")) return "bun"; + return 'npm'; } From 4e8be84de77129dc84769d973d17186c82df6e39 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 13 Aug 2023 17:19:39 -0700 Subject: [PATCH 4/5] Undo autoformatting --- packages/playwright-core/src/cli/cli.ts | 56 +++++++++++------------ packages/playwright-core/src/utils/env.ts | 4 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/playwright-core/src/cli/cli.ts b/packages/playwright-core/src/cli/cli.ts index cb376123276fe..b0079f59e9725 100755 --- a/packages/playwright-core/src/cli/cli.ts +++ b/packages/playwright-core/src/cli/cli.ts @@ -18,69 +18,69 @@ /* eslint-disable no-console */ -import { getPackageManager, gracefullyProcessExitDoNotHang } from "../utils"; -import program from "./program"; +import { getPackageManager, gracefullyProcessExitDoNotHang } from '../utils'; +import program from './program'; function printPlaywrightTestError(command: string) { const packages: string[] = []; for (const pkg of [ - "playwright", - "playwright-chromium", - "playwright-firefox", - "playwright-webkit", + 'playwright', + 'playwright-chromium', + 'playwright-firefox', + 'playwright-webkit', ]) { try { require.resolve(pkg); packages.push(pkg); } catch (e) {} } - if (!packages.length) packages.push("playwright"); + if (!packages.length) packages.push('playwright'); const packageManager = getPackageManager(); - if (packageManager === "yarn") { + if (packageManager === 'yarn') { console.error( - `Please install @playwright/test package before running "yarn playwright ${command}"` + `Please install @playwright/test package before running "yarn playwright ${command}"` ); - console.error(` yarn remove ${packages.join(" ")}`); - console.error(" yarn add -D @playwright/test"); - } else if (packageManager === "pnpm") { + console.error(` yarn remove ${packages.join(' ')}`); + console.error(' yarn add -D @playwright/test'); + } else if (packageManager === 'pnpm') { console.error( - `Please install @playwright/test package before running "pnpm exec playwright ${command}"` + `Please install @playwright/test package before running "pnpm exec playwright ${command}"` ); - console.error(` pnpm remove ${packages.join(" ")}`); - console.error(" pnpm add -D @playwright/test"); - } else if (packageManager === "bun") { + console.error(` pnpm remove ${packages.join(' ')}`); + console.error(' pnpm add -D @playwright/test'); + } else if (packageManager === 'bun') { console.error( - `Please install @playwright/test package before running "bunx playwright ${command}"` + `Please install @playwright/test package before running "bunx playwright ${command}"` ); - console.error(` bun remove ${packages.join(" ")}`); - console.error(" bun add -D @playwright/test"); + console.error(` bun remove ${packages.join(' ')}`); + console.error(' bun add -D @playwright/test'); } else { console.error( - `Please install @playwright/test package before running "npx playwright ${command}"` + `Please install @playwright/test package before running "npx playwright ${command}"` ); - console.error(` npm uninstall ${packages.join(" ")}`); - console.error(" npm install -D @playwright/test"); + console.error(` npm uninstall ${packages.join(' ')}`); + console.error(' npm install -D @playwright/test'); } } { - const command = program.command("test").allowUnknownOption(true); + const command = program.command('test').allowUnknownOption(true); command.description( - "Run tests with Playwright Test. Available in @playwright/test package." + 'Run tests with Playwright Test. Available in @playwright/test package.' ); command.action(async () => { - printPlaywrightTestError("test"); + printPlaywrightTestError('test'); gracefullyProcessExitDoNotHang(1); }); } { - const command = program.command("show-report").allowUnknownOption(true); + const command = program.command('show-report').allowUnknownOption(true); command.description( - "Show Playwright Test HTML report. Available in @playwright/test package." + 'Show Playwright Test HTML report. Available in @playwright/test package.' ); command.action(async () => { - printPlaywrightTestError("show-report"); + printPlaywrightTestError('show-report'); gracefullyProcessExitDoNotHang(1); }); } diff --git a/packages/playwright-core/src/utils/env.ts b/packages/playwright-core/src/utils/env.ts index 5add07a41f926..a52fc9edc3b41 100644 --- a/packages/playwright-core/src/utils/env.ts +++ b/packages/playwright-core/src/utils/env.ts @@ -32,6 +32,6 @@ export function getPackageManager() { return 'yarn'; if (env.includes('pnpm')) return 'pnpm'; -if (env.includes("bun")) return "bun"; - return 'npm'; + if (env.includes('bun')) return 'bun'; + return 'npm'; } From 87c66a91c136a2f37652e8f7f89494930610367c Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Tue, 15 Aug 2023 13:08:04 -0700 Subject: [PATCH 5/5] Remove unnecessary changes --- packages/playwright-core/src/cli/cli.ts | 37 +++++++---------------- packages/playwright-core/src/utils/env.ts | 3 +- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/playwright-core/src/cli/cli.ts b/packages/playwright-core/src/cli/cli.ts index b0079f59e9725..1bb8c763ca28d 100755 --- a/packages/playwright-core/src/cli/cli.ts +++ b/packages/playwright-core/src/cli/cli.ts @@ -23,41 +23,30 @@ import program from './program'; function printPlaywrightTestError(command: string) { const packages: string[] = []; - for (const pkg of [ - 'playwright', - 'playwright-chromium', - 'playwright-firefox', - 'playwright-webkit', - ]) { + for (const pkg of ['playwright', 'playwright-chromium', 'playwright-firefox', 'playwright-webkit']) { try { require.resolve(pkg); packages.push(pkg); - } catch (e) {} + } catch (e) { + } } - if (!packages.length) packages.push('playwright'); + if (!packages.length) + packages.push('playwright'); const packageManager = getPackageManager(); if (packageManager === 'yarn') { - console.error( - `Please install @playwright/test package before running "yarn playwright ${command}"` - ); + console.error(`Please install @playwright/test package before running "yarn playwright ${command}"`); console.error(` yarn remove ${packages.join(' ')}`); console.error(' yarn add -D @playwright/test'); } else if (packageManager === 'pnpm') { - console.error( - `Please install @playwright/test package before running "pnpm exec playwright ${command}"` - ); + console.error(`Please install @playwright/test package before running "pnpm exec playwright ${command}"`); console.error(` pnpm remove ${packages.join(' ')}`); console.error(' pnpm add -D @playwright/test'); } else if (packageManager === 'bun') { - console.error( - `Please install @playwright/test package before running "bunx playwright ${command}"` - ); + console.error(`Please install @playwright/test package before running "bunx playwright ${command}"`); console.error(` bun remove ${packages.join(' ')}`); console.error(' bun add -D @playwright/test'); } else { - console.error( - `Please install @playwright/test package before running "npx playwright ${command}"` - ); + console.error(`Please install @playwright/test package before running "npx playwright ${command}"`); console.error(` npm uninstall ${packages.join(' ')}`); console.error(' npm install -D @playwright/test'); } @@ -65,9 +54,7 @@ function printPlaywrightTestError(command: string) { { const command = program.command('test').allowUnknownOption(true); - command.description( - 'Run tests with Playwright Test. Available in @playwright/test package.' - ); + command.description('Run tests with Playwright Test. Available in @playwright/test package.'); command.action(async () => { printPlaywrightTestError('test'); gracefullyProcessExitDoNotHang(1); @@ -76,9 +63,7 @@ function printPlaywrightTestError(command: string) { { const command = program.command('show-report').allowUnknownOption(true); - command.description( - 'Show Playwright Test HTML report. Available in @playwright/test package.' - ); + command.description('Show Playwright Test HTML report. Available in @playwright/test package.'); command.action(async () => { printPlaywrightTestError('show-report'); gracefullyProcessExitDoNotHang(1); diff --git a/packages/playwright-core/src/utils/env.ts b/packages/playwright-core/src/utils/env.ts index a52fc9edc3b41..ae969df9fcb9c 100644 --- a/packages/playwright-core/src/utils/env.ts +++ b/packages/playwright-core/src/utils/env.ts @@ -32,6 +32,7 @@ export function getPackageManager() { return 'yarn'; if (env.includes('pnpm')) return 'pnpm'; - if (env.includes('bun')) return 'bun'; + if (env.includes('bun')) + return 'bun'; return 'npm'; }