Skip to content

Commit b3374d0

Browse files
committed
feat(core): create standalone core module
1 parent dc415ae commit b3374d0

File tree

19 files changed

+288
-42
lines changed

19 files changed

+288
-42
lines changed

.editorconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,4 @@ insert_final_newline = true
88
trim_trailing_whitespace = true
99

1010
[*.md]
11-
max_line_length = off
1211
trim_trailing_whitespace = false

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
"test:all": "pnpm test:vitest:jsdom && pnpm test:vitest:happy-dom && pnpm test:jest && pnpm test:examples",
2121
"test:all:legacy": "pnpm test:vitest:jsdom && pnpm test:vitest:happy-dom && pnpm test:jest",
2222
"build": "pnpm build:types && pnpm build:docs",
23-
"build:types": "tsc --build && cp packages/svelte/src/core/types.d.ts packages/svelte/dist/core",
24-
"build:docs": "remark --output --use remark-toc --use remark-code-import --use unified-prettier README.md examples && cp -f README.md packages/svelte",
23+
"build:types": "tsc --build",
24+
"build:docs": "remark --output --use remark-toc --use remark-code-import --use unified-prettier README.md packages/*/README.md examples && cp -f README.md packages/svelte",
2525
"contributors:add": "all-contributors add",
2626
"contributors:generate": "all-contributors generate",
2727
"install:3": "./scripts/install-dependencies 3",

packages/svelte-core/README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# @testing-library/svelte-core
2+
3+
Do you want to build your own Svelte testing library? You may want to use our
4+
rendering core, which abstracts away differences in Svelte versions to provide a
5+
simple API to render Svelte components into the document and clean them up
6+
afterwards
7+
8+
## Table of Contents
9+
10+
- [Example Usage](#example-usage)
11+
- [API](#api)
12+
- [`setup`](#setup)
13+
- [`mount`](#mount)
14+
- [`cleanup`](#cleanup)
15+
- [`addCleanupTask`](#addcleanuptask)
16+
- [`removeCleanupTask`](#removecleanuptask)
17+
- [Utility types](#utility-types)
18+
19+
## Example Usage
20+
21+
```ts
22+
import { beforeEach } from 'vitest'
23+
import { cleanup, mount, setup } from '@testing-library/svelte-core'
24+
import type {
25+
Component,
26+
ComponentType,
27+
ComponentOptions,
28+
Props,
29+
Exports,
30+
} from '@testing-library/svelte-core/types'
31+
32+
import { bindQueries, type Screen } from './bring-your-own-queries.js'
33+
34+
beforeEach(() => {
35+
cleanup()
36+
})
37+
38+
export interface RenderResult<C extends Component> {
39+
screen: Screen
40+
component: Exports<C>
41+
target: HTMLElement
42+
rerender: (props: Partial<Props<C>>) => Promise<void>
43+
unmount: () => void
44+
}
45+
46+
export const render = <C extends Component>(
47+
component: ComponentType<C>,
48+
options: ComponentOptions<C>
49+
): RenderResult<C> => {
50+
const { baseElement, target, mountOptions } = setup(options)
51+
const { component, unmount, rerender } = mount(component, mountOptions)
52+
const screen = bindQueries(baseElement)
53+
54+
return { screen, component, target, rerender, unmount }
55+
}
56+
```
57+
58+
## API
59+
60+
### `setup`
61+
62+
Validate options and prepare document elements for rendering.
63+
64+
```ts
65+
const { baseElement, target, mountOptions } = setup(options, renderOptions)
66+
```
67+
68+
| Argument | Type | Description |
69+
| ------------------ | ---------------------------------------- | ---------------------------------------------- |
70+
| `componentOptions` | `Props` or partial [component options][] | Options for how the component will be rendered |
71+
| `setupOptions` | `{ baseElement?: HTMLElement }` | Optionally override `baseElement` |
72+
73+
| Result | Type | Description | Default |
74+
| -------------- | --------------------- | ------------------------------------------- | ----------------------------------- |
75+
| `baseElement` | `HTMLElement` | The base element | `document.body` |
76+
| `target` | `HTMLElement` | The component's `target` element | `<div>` appended to `document.body` |
77+
| `mountOptions` | [component options][] | Validated Svelte options to pass to `mount` | `{ target, props: {} }` |
78+
79+
[component options]: https://svelte.dev/docs/client-side-component-api
80+
81+
### `mount`
82+
83+
Mount a Svelte component into the document.
84+
85+
```ts
86+
const { component, unmount, rerender } = mount(Component, options)
87+
```
88+
89+
| Argument | Type | Description |
90+
| ----------- | --------------------- | ---------------------------- |
91+
| `Component` | [Svelte component][] | An imported Svelte component |
92+
| `options` | [component options][] | Svelte component options |
93+
94+
| Result | Type | Description |
95+
| ----------- | ------------------------------------------ | -------------------------------------------------- |
96+
| `component` | [component instance][] | The component instance |
97+
| `unmount` | `() => void` | Unmount the component from the document |
98+
| `rerender` | `(props: Partial<Props>) => Promise<void>` | Update the component's props and wait for rerender |
99+
100+
[Svelte component]: https://svelte.dev/docs/svelte-components
101+
[component instance]: https://svelte.dev/docs/client-side-component-api
102+
103+
### `cleanup`
104+
105+
Cleanup rendered components and added elements. Call this when your tests are
106+
over.
107+
108+
```ts
109+
cleanup()
110+
```
111+
112+
### `addCleanupTask`
113+
114+
Add a custom cleanup task to be called with `cleanup()`
115+
116+
```ts
117+
addCleanupTask(() => {
118+
// ...reset something
119+
})
120+
```
121+
122+
### `removeCleanupTask`
123+
124+
Remove a cleanup task from `cleanup()`. Useful if a cleanup task can only be run
125+
once and may be run outside of `cleanup`
126+
127+
```ts
128+
const customCleanup = () => {
129+
// ...reset something
130+
}
131+
132+
addCleanupTask(customCleanup)
133+
134+
const manuallyCleanupEarly = () => {
135+
customCleanup()
136+
removeCleanupTask(customCleanup)
137+
}
138+
```
139+
140+
### Utility types
141+
142+
This module exports various utility types from
143+
`@testing-library/svelte-core/types`. They adapt to whatever Svelte version is
144+
installed, and can be used to get type signatures for imported components,
145+
props, events, etc.
146+
147+
See [`./types.d.ts`](./types.d.ts) for the full list of types available.

packages/svelte-core/package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@testing-library/svelte-core",
3+
"version": "0.0.0-semantically-released",
4+
"description": "Core rendering and cleanup logic for Svelte testing utilities.",
5+
"exports": {
6+
".": {
7+
"types": "./dist/index.d.ts",
8+
"default": "./src/index.js"
9+
},
10+
"./types": {
11+
"types": "./types.d.ts"
12+
}
13+
},
14+
"type": "module",
15+
"license": "MIT",
16+
"homepage": "https://github.com/testing-library/svelte-testing-library#readme",
17+
"repository": {
18+
"type": "git",
19+
"url": "git+https://github.com/testing-library/svelte-testing-library.git",
20+
"directory": "packages/svelte-core"
21+
},
22+
"bugs": {
23+
"url": "https://github.com/testing-library/svelte-testing-library/issues"
24+
},
25+
"engines": {
26+
"node": ">=16"
27+
},
28+
"keywords": [
29+
"testing",
30+
"svelte",
31+
"ui",
32+
"dom",
33+
"jsdom",
34+
"unit",
35+
"integration",
36+
"functional",
37+
"end-to-end",
38+
"e2e"
39+
],
40+
"files": [
41+
"dist",
42+
"src",
43+
"types.d.ts"
44+
],
45+
"peerDependencies": {
46+
"svelte": "^3 || ^4 || ^5 || ^5.0.0-next.0"
47+
}
48+
}
File renamed without changes.
File renamed without changes.

packages/svelte/src/core/mount.js renamed to packages/svelte-core/src/mount.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ const mountComponent = IS_MODERN_SVELTE ? mountModern : mountLegacy
6262
/**
6363
* Render a Svelte component into the document.
6464
*
65-
* @template {import('./types.js').Component} C
66-
* @param {import('./types.js').ComponentType<C>} Component
67-
* @param {import('./types.js').MountOptions<C>} options
65+
* @template {import('../types.js').Component} C
66+
* @param {import('../types.js').ComponentType<C>} Component
67+
* @param {import('../types.js').MountOptions<C>} options
6868
* @returns {{
6969
* component: C
7070
* unmount: () => void
71-
* rerender: (props: Partial<import('./types.js').Props<C>>) => Promise<void>
71+
* rerender: (props: Partial<import('../types.js').Props<C>>) => Promise<void>
7272
* }}
7373
*/
7474
const mount = (Component, options) => {

packages/svelte/src/core/setup.js renamed to packages/svelte-core/src/setup.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ class UnknownSvelteOptionsError extends TypeError {
2727
/**
2828
* Validate a component's mount options.
2929
*
30-
* @template {import('./types.js').Component} C
31-
* @param {import('./types.js').ComponentOptions<C>} options - props or mount options
32-
* @returns {Partial<import('./types.js').MountOptions<C>>}
30+
* @template {import('../types.js').Component} C
31+
* @param {import('../types.js').ComponentOptions<C>} options - props or mount options
32+
* @returns {Partial<import('../types.js').MountOptions<C>>}
3333
*/
3434
const validateOptions = (options) => {
3535
const isProps = !Object.keys(options).some((option) =>
@@ -55,16 +55,16 @@ const validateOptions = (options) => {
5555
/**
5656
* Set up the document to render a component.
5757
*
58-
* @template {import('./types.js').Component} C
59-
* @param {import('./types.js').ComponentOptions<C>} componentOptions - props or mount options
58+
* @template {import('../types.js').Component} C
59+
* @param {import('../types.js').ComponentOptions<C>} componentOptions - props or mount options
6060
* @param {{ baseElement?: HTMLElement | undefined }} setupOptions - base element of the document to bind any queries
6161
* @returns {{
6262
* baseElement: HTMLElement,
6363
* target: HTMLElement,
64-
* mountOptions: import('./types.js).MountOptions<C>
64+
* mountOptions: import('../types.js').MountOptions<C>
6565
* }}
6666
*/
67-
const setup = (componentOptions, setupOptions) => {
67+
const setup = (componentOptions, setupOptions = {}) => {
6868
const mountOptions = validateOptions(componentOptions)
6969

7070
const baseElement =

0 commit comments

Comments
 (0)