UNPKG

@stencil/playwright

Version:

Testing adapter to use Playwright with Stencil

231 lines (169 loc) 8 kB
# @stencil/playwright > [!NOTE] > The Stencil Playwright adapter is currently an experimental package. Breaking changes may be introduced at any time. > > The Stencil Playwright adapter is designed to only work with **version 4.13.0 and higher** of Stencil! Stencil Playwright is a testing adapter package that allows developers to easily use the [Playwright testing framework](https://playwright.dev/docs/intro) in their Stencil project. For full documentation, please see the [Playwright testing docs on the official Stencil site](https://stenciljs.com/docs/testing/playwright/overview). ## Getting Started 1. Install the necessary dependencies: ```bash npm i @stencil/playwright @playwright/test --save-dev ``` 1. Install the Playwright browser binaries: ```bash npx playwright install ``` 1. Create a Playwright config at the root of your Stencil project: ```ts import { expect } from '@playwright/test'; import { matchers, createConfig } from '@stencil/playwright'; // Add custom Stencil matchers to Playwright assertions expect.extend(matchers); export default createConfig({ // Overwrite Playwright config options here }); ``` The `createConfig()` function is a utility that will create a default Playwright configuration based on your project's Stencil config. Read more about how to use this utility in the [API section](#createconfigoverrides-playwrighttestconfig-promiseplaywrighttestconfig). > [!NOTE] > For `createConfig()` to work correctly, your Stencil config must be named either `stencil.config.ts` or `stencil.config.js`. 1. update your project's `tsconfig.json` to add the `ESNext.Disposable` option to the `lib` array: ```ts title="tsconfig.json" { lib: [ ..., "ESNext.Disposable" ], ... } ``` > [!NOTE] > This will resolve a build error related to `Symbol.asyncDispose`. If this is not added, tests may fail to run since the Stencil dev server will be unable > to start due to the build error. 1. Ensure the Stencil project has a [`www`](https://stenciljs.com/docs/www), `dist`, or `loader-bundle` output target. Playwright relies on pre-compiled output running in a dev server to run tests against. When using the `createConfig()` helper, a configuration for the dev server will be automatically created based on the Stencil project's output target config and [dev server config](https://stenciljs.com/docs/dev-server). The adapter will look for output targets in the following order of priority: `www` > `dist` (Stencil < v5) / `loader-bundle` (Stencil v5). If none of these output targets are specified, tests may not be able to run. 1. Add the `copy` option to the `www` output target config: ```ts title="stencil.config.ts" { type: 'www', serviceWorker: null, copy: [{ src: '**/*.html' }, { src: '**/*.css' }] } ``` This will clone all HTML and CSS files to the `www` output directory so they can be served by the dev server. If you put all testing related files in specific directory(s), you can update the `copy` task glob patterns to only copy those files: ```ts title="stencil.config.ts" { type: 'www', serviceWorker: null, copy: [{ src: '**/test/*.html' }, { src: '**/test/*.css' }] } ``` > [!NOTE] > If the `copy` property is not set, you will not be able to use the `page.goto` testing pattern! 1. Test away! Check out the [e2e testing page on the Stencil docs](https://stenciljs.com/docs/testing/playwright/e2e-testing) for more help getting started writing tests. ## Testing Patterns ### `page.goto()` The `goto()` method allows tests to load a pre-defined HTML template. This pattern is great if a test file has many tests to execute that all use the same HTML code or if additional `script` or `style` tags need to be included in the HTML. However, with this pattern, developers are responsible for defining the necessary `script` tags pointing to the Stencil entry code (so all web components are correctly loaded and registered). ```html <!-- my-component.e2e.html --> <!doctype html> <html lang="en"> <head> <meta charset="utf8" /> <!-- Replace with the path to your entrypoint --> <script src="./build/test-app.esm.js" type="module"></script> <script src="./build/test-app.js" nomodule></script> </head> <body> <my-component first="Stencil"></my-component> </body> </html> ``` ```ts // my-component.e2e.ts import { expect } from '@playwright/test'; import { test } from '@stencil/playwright'; test.describe('my-component', () => { test('should render the correct name', async ({ page }) => { // The path here is the path to the www output relative to the dev server root directory await page.goto('/my-component/my-component.e2e.html'); // Rest of test }); }); ``` ### `page.setContent()` The `setContent()` method allows tests to define their own HTML code on a test-by-test basis. This pattern is helpful if the HTML for a test is small, or to avoid affecting other tests is using the `page.goto()` pattern and modifying a shared HTML template file. With this pattern, the `script` tags pointing to Stencil entry code will be automatically injected into the generated HTML. ```ts // my-component.e2e.ts import { expect } from '@playwright/test'; import { test } from '@stencil/playwright'; test.describe('my-component', () => { test('should render the correct name', async ({ page }) => { await page.setContent('<my-component first="Stencil"></my-component>'); // Rest of test }); }); ``` ## API ### `createConfig(overrides?: PlaywrightTestConfig): Promise<PlaywrightTestConfig>` Returns a [Playwright test configuration](https://playwright.dev/docs/test-configuration#introduction). `overrides`, as the name implies, will overwrite the default configuration value(s) if supplied. These values can include any valid Playwright config option. Changing option values in a nested object will use a "deep merge" to combine the default and overridden values. So, creating a config like the following: ```ts import { expect } from '@playwright/test'; import { matchers, createConfig } from '@stencil/playwright'; expect.extend(matchers); export default createConfig({ // Change which test files Playwright will execute testMatch: '*.spec.ts', webServer: { // Only wait max 30 seconds for server to start timeout: 30000, }, }); ``` Will result in: ```ts { testMatch: '*.spec.ts', use: { baseURL: 'http://localhost:3333', }, webServer: { command: 'npx stencil build --dev --watch --serve --no-open', url: 'http://localhost:3333/ping', reuseExistingServer: !process.env.CI, // Only timeout gets overridden, not the entire object timeout: 30000, }, } ``` ### `test` `test` designates which tests will be executed by Playwright. See the [Playwright API documentation](https://playwright.dev/docs/api/class-test#test-call) regarding usage. This package modifies the [`page` fixture](#page) and offers a [`skip` utility](#skip) as discussed below. #### `page` The page fixture is a class that allows interacting with the current test's browser tab. In addition to the [default Playwright Page API](https://playwright.dev/docs/api/class-page), Stencil extends the class with a few additional methods: - `waitForChanges()`: Waits for Stencil components to re-hydrate before continuing. - `spyOnEvent()`: Creates a new EventSpy and listens on the window for an event to emit. #### `skip` The `skip` utility allows developers to skip tests for certain browsers or [component modes](https://stenciljs.com/docs/styling#style-modes): ```ts test('my-test', ({ page, skip }) => { // Skip tests for certain browsers skip.browser('firefox', 'This behavior is not available on Firefox'); // Skip tests for certain modes skip.mode('md', 'This behavior is not available in Material Design'); ... }) ```