diff --git a/docs/guide/browser/index.md b/docs/guide/browser/index.md index a33310adee8a..d8c8499a539c 100644 --- a/docs/guide/browser/index.md +++ b/docs/guide/browser/index.md @@ -399,6 +399,10 @@ However, Vitest also provides packages to render components for several popular - [`vitest-browser-svelte`](https://github.com/vitest-dev/vitest-browser-svelte) to render [svelte](https://svelte.dev) components - [`vitest-browser-react`](https://github.com/vitest-dev/vitest-browser-react) to render [react](https://react.dev) components +Community packages are available for other frameworks: + +- [`vitest-browser-lit`](https://github.com/EskiMojo14/vitest-browser-lit) to render [lit](https://lit.dev) components + If your framework is not represented, feel free to create your own package - it is a simple wrapper around the framework renderer and `page.elementLocator` API. We will add a link to it on this page. Make sure it has a name starting with `vitest-browser-`. Besides rendering components and locating elements, you will also need to make assertions. Vitest bundles the [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) library to provide a wide range of DOM assertions out of the box. Read more at the [Assertions API](/guide/browser/assertion-api). @@ -473,6 +477,21 @@ test('loads and displays greeting', async () => { await expect.element(screen.getByRole('button')).toBeDisabled() }) ``` +```ts [lit] +import { render } from 'vitest-browser-lit' +import { html } from 'lit' +import './greeter-button' + +test('greeting appears on click', async () => { + const screen = render(html``) + + const button = screen.getByRole('button') + await button.click() + const greeting = screen.getByText(/hello world/iu) + + await expect.element(greeting).toBeInTheDocument() +}) +``` ::: Vitest doesn't support all frameworks out of the box, but you can use external tools to run tests with these frameworks. We also encourage the community to create their own `vitest-browser` wrappers - if you have one, feel free to add it to the examples above. diff --git a/packages/vitest/src/create/browser/creator.ts b/packages/vitest/src/create/browser/creator.ts index f279de678c0e..21d84d629eac 100644 --- a/packages/vitest/src/create/browser/creator.ts +++ b/packages/vitest/src/create/browser/creator.ts @@ -84,6 +84,11 @@ function getFramework(): prompt.Choice[] { value: 'react', description: '"The library for web and native user interfaces"', }, + { + title: 'lit', + value: 'lit', + description: '"A simple library for building fast, lightweight web components."', + }, { title: 'preact', value: 'preact', @@ -112,6 +117,8 @@ function getFrameworkTestPackage(framework: string) { return 'vitest-browser-svelte' case 'react': return 'vitest-browser-react' + case 'lit': + return 'vitest-browser-lit' case 'preact': return '@testing-library/preact' case 'solid': @@ -205,6 +212,9 @@ function getPossibleFramework(dependencies: Record) { if (dependencies.svelte || dependencies['@sveltejs/kit']) { return 'svelte' } + if (dependencies.lit || dependencies['lit-html']) { + return 'lit' + } if (dependencies.preact) { return 'preact' } diff --git a/packages/vitest/src/create/browser/examples.ts b/packages/vitest/src/create/browser/examples.ts index 7e30e29fced9..49ad549f48aa 100644 --- a/packages/vitest/src/create/browser/examples.ts +++ b/packages/vitest/src/create/browser/examples.ts @@ -135,6 +135,62 @@ test('renders name', async () => { `, } +const litExample = { + name: 'HelloWorld.js', + js: ` +import { html, LitElement } from 'lit' + +export class HelloWorld extends LitElement { + static properties = { + name: { type: String }, + } + + constructor() { + super() + this.name = 'World' + } + + render() { + return html\`

Hello \${this.name}!

\` + } +} + +customElements.define('hello-world', HelloWorld) +`, + ts: ` +import { html, LitElement } from 'lit' +import { customElement, property } from 'lit/decorators.js' + +@customElement('hello-world') +export class HelloWorld extends LitElement { + @property({ type: String }) + name = 'World' + + render() { + return html\`

Hello \${this.name}!

\` + } +} + +declare global { + interface HTMLElementTagNameMap { + 'hello-world': HelloWorld + } +} +`, + test: ` +import { expect, test } from 'vitest' +import { render } from 'vitest-browser-lit' +import { html } from 'lit' +import './HelloWorld.js' + +test('renders name', async () => { + const screen = render(html\`\`) + const element = screen.getByText('Hello Vitest!') + await expect.element(element).toBeInTheDocument() +}) +`, +} + const vanillaExample = { name: 'HelloWorld.js', js: ` @@ -191,6 +247,8 @@ function getExampleTest(framework: string) { return vueExample case 'svelte': return svelteExample + case 'lit': + return litExample case 'marko': return markoExample default: