diff --git a/README.md b/README.md index c3ad49b..0648a69 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ To do your own cleanup, or if you're using another framework, call the `setup` a import { cleanup, render, setup } from '@testing-library/svelte' // before -setup() +await setup() // test render(/* ... */) @@ -159,7 +159,7 @@ render(/* ... */) cleanup() ``` -To disable auto-cleanup in Vitest, set the `autoCleanup` option of the plugin to false: +To disable auto-setup and cleanup in Vitest, set the `autoCleanup` option of the plugin to false: ```js svelteTesting({ autoCleanup: false }) diff --git a/packages/svelte-core/README.md b/packages/svelte-core/README.md index 8010664..c856305 100644 --- a/packages/svelte-core/README.md +++ b/packages/svelte-core/README.md @@ -11,6 +11,7 @@ afterwards. - [API](#api) - [`render`](#render) - [`setup`](#setup) + - [`wrapperSetup`](#wrappersetup) - [`mount`](#mount) - [`cleanup`](#cleanup) - [`addCleanupTask`](#addcleanuptask) @@ -30,7 +31,9 @@ import type { import { bindQueries, type Queries } from './bring-your-own-queries.js' -beforeEach(() => { +beforeEach(async () => { + // Required to use the `wrapper` render option + await SvelteCore.wrapperSetup() SvelteCore.cleanup() }) @@ -125,12 +128,30 @@ const { baseElement, container, mountOptions } = setup( | `wrapper` | [Svelte component][svelte-component-docs] | A component to wrap the component under test, e.g. a context provider | `undefined` | | `wrapperProps` | `Props` | Props to pass to the `wrapper` component | `undefined` | +> \[!IMPORTANT] +> Using the `wrapper` option requires awaiting [`wrapperSetup`](#wrappersetup) +> beforehand, e.g. in a `beforeEach` hook. + | Result | Type | Description | Default | | -------------- | ------------------------------------ | ---------------------------------------- | ----------------------------------- | | `baseElement` | `HTMLElement` | The base element | `document.body` | | `container` | `HTMLElement` | The component's immediate parent element | `
` appended to `document.body` | | `mountOptions` | [`mount` options][svelte-mount-docs] | Validated options to pass to `mount` | `{ target, props: {} }` | +### `wrapperSetup` + +Load the wrapper scaffold for the installed version of Svelte. Await this before +rendering with the [`wrapper`](#setup) option, e.g. in a `beforeEach` hook. +Rendering with a `wrapper` before `wrapperSetup` resolves throws a +`WrapperNotSetupError`. + +```ts +await wrapperSetup() +``` + +The scaffold is loaded once and cached, so calling `wrapperSetup` repeatedly is +cheap. + ### `mount` Mount a Svelte component into the document. diff --git a/packages/svelte-core/src/index.js b/packages/svelte-core/src/index.js index ce20a67..f5f5d8b 100644 --- a/packages/svelte-core/src/index.js +++ b/packages/svelte-core/src/index.js @@ -9,3 +9,4 @@ export * from './cleanup.js' export * from './mount.js' export * from './render.js' export * from './setup.js' +export { wrapperSetup } from './wrapper.js' diff --git a/packages/svelte-core/src/mount.js b/packages/svelte-core/src/mount.js index e21ae9c..66d87bd 100644 --- a/packages/svelte-core/src/mount.js +++ b/packages/svelte-core/src/mount.js @@ -6,7 +6,7 @@ import * as Svelte from 'svelte' import { addCleanupTask, removeCleanupTask } from './cleanup.js' import { createProps } from './props.svelte.js' import { IS_MODERN_SVELTE } from './svelte-version.js' -import WrapperScaffold from './wrapper-scaffold.svelte' +import { getWrapperScaffold } from './wrapper.js' /** * Mount a modern Svelte 5 component into the DOM. @@ -108,7 +108,7 @@ const setupComponent = (Component, mountOptions, setupOptions = {}) => { if (wrapper) { return { isWrapper: true, - componentToMount: WrapperScaffold, + componentToMount: getWrapperScaffold(), mountOptions: { ...mountOptions, props: { diff --git a/packages/svelte-core/src/wrapper-scaffold-legacy.svelte b/packages/svelte-core/src/wrapper-scaffold-legacy.svelte new file mode 100644 index 0000000..7679834 --- /dev/null +++ b/packages/svelte-core/src/wrapper-scaffold-legacy.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/packages/svelte-core/src/wrapper-scaffold.svelte b/packages/svelte-core/src/wrapper-scaffold.svelte index 7679834..03cf3d9 100644 --- a/packages/svelte-core/src/wrapper-scaffold.svelte +++ b/packages/svelte-core/src/wrapper-scaffold.svelte @@ -1,21 +1,19 @@ - - - + + + diff --git a/packages/svelte-core/src/wrapper.js b/packages/svelte-core/src/wrapper.js new file mode 100644 index 0000000..080c5e2 --- /dev/null +++ b/packages/svelte-core/src/wrapper.js @@ -0,0 +1,50 @@ +import { IS_MODERN_SVELTE } from './svelte-version.js' + +/** @type {import('../types.js').Component | undefined} */ +let WrapperScaffold + +/** @type {Promise | undefined} */ +let scaffoldInitialization + +class WrapperNotSetupError extends Error { + constructor() { + super( + 'Ensure `setup()` runs (e.g. in `beforeEach`) before using `wrapper` option.' + ) + this.name = 'WrapperNotSetupError' + } +} + +/** + * Import the proper wrapper scaffolding for the current version of Svelte. + * + * Supports the `wrapper` option of `render` / `mount`. + */ +const wrapperSetup = async () => { + if (!scaffoldInitialization) { + scaffoldInitialization = initializeScaffold() + } + + await scaffoldInitialization +} + +/** Import the scaffold component and set up module singletons. */ +const initializeScaffold = async () => { + const scaffoldImport = IS_MODERN_SVELTE + ? import('./wrapper-scaffold.svelte') + : import('./wrapper-scaffold-legacy.svelte') + + const { default: Scaffold } = await scaffoldImport + WrapperScaffold = Scaffold +} + +/** Get the wrapper scaffolding component. */ +const getWrapperScaffold = () => { + if (!WrapperScaffold) { + throw new WrapperNotSetupError() + } + + return WrapperScaffold +} + +export { getWrapperScaffold, wrapperSetup } diff --git a/packages/svelte/src/index.js b/packages/svelte/src/index.js index b7f76b3..1398536 100644 --- a/packages/svelte/src/index.js +++ b/packages/svelte/src/index.js @@ -6,8 +6,8 @@ import { act, cleanup, setup } from './pure.js' // if you don't like this then set the STL_SKIP_AUTO_CLEANUP env variable. if (typeof process !== 'undefined' && !process.env.STL_SKIP_AUTO_CLEANUP) { if (typeof beforeEach === 'function') { - beforeEach(() => { - setup() + beforeEach(async () => { + await setup() }) } diff --git a/packages/svelte/src/pure.js b/packages/svelte/src/pure.js index 8b0281d..493511d 100644 --- a/packages/svelte/src/pure.js +++ b/packages/svelte/src/pure.js @@ -71,13 +71,15 @@ const render = (Component, options = {}, renderOptions = {}) => { } /** - * Configure `@testing-library/dom` for usage with Svelte. + * Set up the test environment * * Ensures events fired from `@testing-library/dom` * and `@testing-library/user-event` wait for Svelte * to flush changes to the DOM before proceeding. + * + * Sets up the rendering core for the `wrapper` option. */ -const setup = () => { +const setup = async () => { const originalConfig = DomTestingLibrary.getConfig() DomTestingLibrary.configure({ @@ -88,6 +90,8 @@ const setup = () => { Core.addCleanupTask(() => { DomTestingLibrary.configure(originalConfig) }) + + return Core.wrapperSetup() } /** Unmount components, remove elements added to ``, and reset `@testing-library/dom`. */ diff --git a/packages/svelte/src/vitest.js b/packages/svelte/src/vitest.js index 5b80032..40b712b 100644 --- a/packages/svelte/src/vitest.js +++ b/packages/svelte/src/vitest.js @@ -6,7 +6,7 @@ const afterEach = async () => { cleanup() } -beforeEach(() => { - setup() +beforeEach(async () => { + await setup() return afterEach }) diff --git a/tests/envs/svelte3/node16/package.json b/tests/envs/svelte3/node16/package.json index c62b79a..03d103e 100644 --- a/tests/envs/svelte3/node16/package.json +++ b/tests/envs/svelte3/node16/package.json @@ -12,6 +12,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@vitest/coverage-v8": "0.x.x", + "browserslist": "4.28.2", "expect-type": "^1.2.1", "happy-dom": "14.x.x", "jest": "^29.7.0", diff --git a/tests/envs/svelte4/node16/package.json b/tests/envs/svelte4/node16/package.json index 3167aef..f25e69e 100644 --- a/tests/envs/svelte4/node16/package.json +++ b/tests/envs/svelte4/node16/package.json @@ -12,6 +12,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@vitest/coverage-v8": "0.x.x", + "browserslist": "4.28.2", "expect-type": "^1.2.1", "happy-dom": "14.x.x", "jest": "^29.7.0",