@testing-library/svelte 4.1.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -22
- package/package.json +40 -48
- package/src/__tests__/__snapshots__/render.test.js.snap +25 -2
- package/src/__tests__/act.test.js +1 -1
- package/src/__tests__/auto-cleanup-skip.test.js +1 -1
- package/src/__tests__/auto-cleanup.test.js +1 -1
- package/src/__tests__/cleanup.test.js +36 -0
- package/src/__tests__/context.test.js +3 -2
- package/src/__tests__/debug.test.js +1 -1
- package/src/__tests__/events.test.js +1 -1
- package/src/__tests__/fixtures/Mounter.svelte +19 -0
- package/src/__tests__/fixtures/Rerender.svelte +17 -0
- package/src/__tests__/fixtures/Simple.svelte +5 -0
- package/src/__tests__/fixtures/Transitioner.svelte +18 -0
- package/src/__tests__/mount.test.js +34 -0
- package/src/__tests__/multi-base.test.js +1 -1
- package/src/__tests__/render.test.js +42 -23
- package/src/__tests__/rerender.test.js +28 -25
- package/src/__tests__/transition.test.js +32 -0
- package/src/__tests__/utils.js +7 -0
- package/src/index.js +1 -0
- package/src/pure.js +96 -80
- package/src/svelte5-index.js +17 -0
- package/src/svelte5.js +41 -0
- package/src/vitest.js +1 -1
- package/types/index.d.ts +34 -11
- package/src/__tests__/fixtures/Stopwatch.svelte +0 -40
- package/src/__tests__/unmount.test.js +0 -35
package/README.md
CHANGED
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
39
39
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
40
40
|
|
|
41
|
-
|
|
42
41
|
- [The Problem](#the-problem)
|
|
43
42
|
- [This Solution](#this-solution)
|
|
44
43
|
- [Installation](#installation)
|
|
@@ -81,6 +80,21 @@ This library has `peerDependencies` listings for `svelte >= 3`.
|
|
|
81
80
|
You may also be interested in installing `@testing-library/jest-dom` so you can use
|
|
82
81
|
[the custom jest matchers](https://github.com/testing-library/jest-dom).
|
|
83
82
|
|
|
83
|
+
### Svelte 5 support
|
|
84
|
+
|
|
85
|
+
If you are riding the bleeding edge of Svelte 5, you'll need to either
|
|
86
|
+
import from `@testing-library/svelte/svelte5` instead of `@testing-library/svelte`, or have your `vite.config.js` contains the following alias:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
export default defineConfig(({ }) => ({
|
|
90
|
+
test: {
|
|
91
|
+
alias: {
|
|
92
|
+
'@testing-library/svelte': '@testing-library/svelte/svelte5'
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
}))
|
|
96
|
+
```
|
|
97
|
+
|
|
84
98
|
## Docs
|
|
85
99
|
|
|
86
100
|
See the [**docs**](https://testing-library.com/docs/svelte-testing-library/intro) over at the Testing Library website.
|
|
@@ -119,23 +133,29 @@ Thanks goes to these people ([emoji key][emojis]):
|
|
|
119
133
|
<!-- prettier-ignore-start -->
|
|
120
134
|
<!-- markdownlint-disable -->
|
|
121
135
|
<table>
|
|
122
|
-
<
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
<tbody>
|
|
137
|
+
<tr>
|
|
138
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benmonro"><img src="https://avatars3.githubusercontent.com/u/399236?v=4?s=100" width="100px;" alt="Ben Monro"/><br /><sub><b>Ben Monro</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=benmonro" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=benmonro" title="Tests">⚠️</a> <a href="#ideas-benmonro" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=benmonro" title="Documentation">📖</a></td>
|
|
139
|
+
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/EmilTholin"><img src="https://avatars0.githubusercontent.com/u/11573167?v=4?s=100" width="100px;" alt="Emil Tholin"/><br /><sub><b>Emil Tholin</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=EmilTholin" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=EmilTholin" title="Tests">⚠️</a> <a href="#ideas-EmilTholin" title="Ideas, Planning, & Feedback">🤔</a></td>
|
|
140
|
+
<td align="center" valign="top" width="14.28%"><a href="https://medium.com/@oieduardorabelo"><img src="https://avatars1.githubusercontent.com/u/829902?v=4?s=100" width="100px;" alt="Eduardo Rabelo"/><br /><sub><b>Eduardo Rabelo</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=oieduardorabelo" title="Tests">⚠️</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=oieduardorabelo" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=oieduardorabelo" title="Documentation">📖</a> <a href="#example-oieduardorabelo" title="Examples">💡</a></td>
|
|
141
|
+
<td align="center" valign="top" width="14.28%"><a href="http://timdeschryver.dev"><img src="https://avatars1.githubusercontent.com/u/28659384?v=4?s=100" width="100px;" alt="Tim Deschryver"/><br /><sub><b>Tim Deschryver</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=timdeschryver" title="Documentation">📖</a></td>
|
|
142
|
+
<td align="center" valign="top" width="14.28%"><a href="http://www.ematipico.com"><img src="https://avatars3.githubusercontent.com/u/602478?v=4?s=100" width="100px;" alt="Emanuele"/><br /><sub><b>Emanuele</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=ematipico" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=ematipico" title="Tests">⚠️</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=ematipico" title="Documentation">📖</a></td>
|
|
143
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pngwn"><img src="https://avatars1.githubusercontent.com/u/12937446?v=4?s=100" width="100px;" alt="pngwn"/><br /><sub><b>pngwn</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=pngwn" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=pngwn" title="Tests">⚠️</a></td>
|
|
144
|
+
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/sebsilbermann"><img src="https://avatars3.githubusercontent.com/u/12292047?v=4?s=100" width="100px;" alt="Sebastian Silbermann"/><br /><sub><b>Sebastian Silbermann</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=eps1lon" title="Code">💻</a></td>
|
|
145
|
+
</tr>
|
|
146
|
+
<tr>
|
|
147
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mihar-22"><img src="https://avatars3.githubusercontent.com/u/14304599?s=460&v=4?s=100" width="100px;" alt="Rahim Alwer"/><br /><sub><b>Rahim Alwer</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=mihar-22" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=mihar-22" title="Documentation">📖</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=mihar-22" title="Tests">⚠️</a> <a href="https://github.com/testing-library/svelte-testing-library/pulls?q=is%3Apr+reviewed-by%3Amihar-22" title="Reviewed Pull Requests">👀</a></td>
|
|
148
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MirrorBytes"><img src="https://avatars3.githubusercontent.com/u/22119469?v=4?s=100" width="100px;" alt="Bob"/><br /><sub><b>Bob</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/issues?q=author%3AMirrorBytes" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=MirrorBytes" title="Code">💻</a></td>
|
|
149
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ronmerkin"><img src="https://avatars.githubusercontent.com/u/17492527?v=4?s=100" width="100px;" alt="Ron Merkin"/><br /><sub><b>Ron Merkin</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=ronmerkin" title="Code">💻</a></td>
|
|
150
|
+
<td align="center" valign="top" width="14.28%"><a href="http://www.benmccann.com"><img src="https://avatars.githubusercontent.com/u/322311?v=4?s=100" width="100px;" alt="Ben McCann"/><br /><sub><b>Ben McCann</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=benmccann" title="Tests">⚠️</a></td>
|
|
151
|
+
<td align="center" valign="top" width="14.28%"><a href="https://johnbowser.dev/"><img src="https://avatars.githubusercontent.com/u/66637570?v=4?s=100" width="100px;" alt="John Bowser"/><br /><sub><b>John Bowser</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=jgbowser" title="Code">💻</a> <a href="https://github.com/testing-library/svelte-testing-library/commits?author=jgbowser" title="Tests">⚠️</a></td>
|
|
152
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ysitbon"><img src="https://avatars.githubusercontent.com/u/1370679?v=4?s=100" width="100px;" alt="Yoann"/><br /><sub><b>Yoann</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=ysitbon" title="Code">💻</a></td>
|
|
153
|
+
<td align="center" valign="top" width="14.28%"><a href="https://techblog.babyl.ca/"><img src="https://avatars.githubusercontent.com/u/19954?v=4?s=100" width="100px;" alt="Yanick Champoux"/><br /><sub><b>Yanick Champoux</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=yanick" title="Code">💻</a></td>
|
|
154
|
+
</tr>
|
|
155
|
+
<tr>
|
|
156
|
+
<td align="center" valign="top" width="14.28%"><a href="https://michael.cousins.io/"><img src="https://avatars.githubusercontent.com/u/2963448?v=4?s=100" width="100px;" alt="Michael Cousins"/><br /><sub><b>Michael Cousins</b></sub></a><br /><a href="https://github.com/testing-library/svelte-testing-library/commits?author=mcous" title="Code">💻</a></td>
|
|
157
|
+
</tr>
|
|
158
|
+
</tbody>
|
|
139
159
|
</table>
|
|
140
160
|
|
|
141
161
|
<!-- markdownlint-restore -->
|
|
@@ -154,8 +174,8 @@ Contributions of any kind welcome!
|
|
|
154
174
|
|
|
155
175
|
[npm]: https://www.npmjs.com/
|
|
156
176
|
[node]: https://nodejs.org
|
|
157
|
-
[build-badge]: https://img.shields.io/
|
|
158
|
-
[build]: https://
|
|
177
|
+
[build-badge]: https://img.shields.io/github/actions/workflow/status/testing-library/svelte-testing-library/release.yml?style=flat-square
|
|
178
|
+
[build]: https://github.com/testing-library/svelte-testing-library/actions
|
|
159
179
|
[coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/svelte-testing-library.svg?style=flat-square
|
|
160
180
|
[coverage]: https://codecov.io/github/testing-library/svelte-testing-library
|
|
161
181
|
[version-badge]: https://img.shields.io/npm/v/@testing-library/svelte.svg?style=flat-square
|
|
@@ -164,7 +184,7 @@ Contributions of any kind welcome!
|
|
|
164
184
|
[npmtrends]: http://www.npmtrends.com/@testing-library/svelte
|
|
165
185
|
[discord-badge]: https://img.shields.io/discord/723559267868737556.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
|
|
166
186
|
[discord]: https://discord.gg/testing-library
|
|
167
|
-
[license-badge]: https://img.shields.io/github/license/testing-library/svelte-testing-library?color=b
|
|
187
|
+
[license-badge]: https://img.shields.io/github/license/testing-library/svelte-testing-library?color=b&style=flat-square
|
|
168
188
|
[license]: https://github.com/testing-library/svelte-testing-library/blob/main/LICENSE
|
|
169
189
|
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
|
170
190
|
[prs]: http://makeapullrequest.com
|
|
@@ -187,4 +207,3 @@ Contributions of any kind welcome!
|
|
|
187
207
|
[stackoverflow]: https://stackoverflow.com/questions/tagged/svelte-testing-library
|
|
188
208
|
|
|
189
209
|
<!-- prettier-ignore-end -->
|
|
190
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testing-library/svelte",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "Simple and complete Svelte testing utilities that encourage good testing practices.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"types": "./types/index.d.ts",
|
|
9
9
|
"default": "./src/index.js"
|
|
10
10
|
},
|
|
11
|
+
"./svelte5": {
|
|
12
|
+
"types": "./types/index.d.ts",
|
|
13
|
+
"default": "./src/svelte5-index.js"
|
|
14
|
+
},
|
|
11
15
|
"./vitest": {
|
|
12
16
|
"default": "./src/vitest.js"
|
|
13
17
|
}
|
|
@@ -44,73 +48,61 @@
|
|
|
44
48
|
],
|
|
45
49
|
"scripts": {
|
|
46
50
|
"toc": "doctoc README.md",
|
|
47
|
-
"lint": "
|
|
51
|
+
"lint": "prettier . --check && eslint .",
|
|
52
|
+
"lint:delta": "npm-run-all -p prettier:delta eslint:delta",
|
|
53
|
+
"prettier:delta": "prettier --check `./scripts/changed-files`",
|
|
54
|
+
"eslint:delta": "eslint `./scripts/changed-files`",
|
|
48
55
|
"format": "prettier . --write && eslint . --fix",
|
|
56
|
+
"format:delta": "npm-run-all format:prettier:delta format:eslint:delta",
|
|
57
|
+
"format:prettier:delta": "prettier --write `./scripts/changed-files`",
|
|
58
|
+
"format:eslint:delta": "eslint --fix `./scripts/changed-files`",
|
|
59
|
+
"setup": "npm install && npm run validate",
|
|
49
60
|
"test": "vitest run --coverage",
|
|
50
61
|
"test:watch": "vitest",
|
|
51
62
|
"test:update": "vitest run --update",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
63
|
+
"test:vitest:jsdom": "vitest run --coverage --environment jsdom",
|
|
64
|
+
"test:vitest:happy-dom": "vitest run --coverage --environment happy-dom",
|
|
65
|
+
"types": "svelte-check",
|
|
66
|
+
"validate": "npm-run-all test:vitest:* types",
|
|
54
67
|
"contributors:add": "all-contributors add",
|
|
55
68
|
"contributors:generate": "all-contributors generate"
|
|
56
69
|
},
|
|
57
70
|
"peerDependencies": {
|
|
58
|
-
"svelte": "^3 || ^4"
|
|
71
|
+
"svelte": "^3 || ^4 || ^5"
|
|
59
72
|
},
|
|
60
73
|
"dependencies": {
|
|
61
74
|
"@testing-library/dom": "^9.3.1"
|
|
62
75
|
},
|
|
63
76
|
"devDependencies": {
|
|
64
|
-
"@
|
|
65
|
-
"@commitlint/config-conventional": "^17.6.6",
|
|
66
|
-
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
|
77
|
+
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
67
78
|
"@testing-library/jest-dom": "^6.3.0",
|
|
68
|
-
"@
|
|
69
|
-
"@typescript-eslint/
|
|
79
|
+
"@testing-library/user-event": "^14.5.2",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "6.19.1",
|
|
81
|
+
"@typescript-eslint/parser": "6.19.1",
|
|
70
82
|
"@vitest/coverage-v8": "^0.33.0",
|
|
71
|
-
"all-contributors-cli": "^6.26.
|
|
83
|
+
"all-contributors-cli": "^6.26.1",
|
|
72
84
|
"doctoc": "^2.2.1",
|
|
73
|
-
"eslint": "
|
|
74
|
-
"eslint-config-prettier": "
|
|
75
|
-
"eslint-config-standard": "
|
|
76
|
-
"eslint-plugin-import": "
|
|
77
|
-
"eslint-plugin-
|
|
78
|
-
"eslint-plugin-
|
|
79
|
-
"eslint-plugin-
|
|
80
|
-
"eslint-plugin-
|
|
81
|
-
"eslint-plugin-
|
|
82
|
-
"
|
|
85
|
+
"eslint": "8.56.0",
|
|
86
|
+
"eslint-config-prettier": "9.1.0",
|
|
87
|
+
"eslint-config-standard": "17.1.0",
|
|
88
|
+
"eslint-plugin-import": "2.29.1",
|
|
89
|
+
"eslint-plugin-json-files": "^4.1.0",
|
|
90
|
+
"eslint-plugin-n": "16.6.2",
|
|
91
|
+
"eslint-plugin-promise": "6.1.1",
|
|
92
|
+
"eslint-plugin-simple-import-sort": "10.0.0",
|
|
93
|
+
"eslint-plugin-svelte": "2.35.1",
|
|
94
|
+
"eslint-plugin-vitest-globals": "1.4.0",
|
|
95
|
+
"expect-type": "^0.17.3",
|
|
96
|
+
"happy-dom": "^13.3.1",
|
|
83
97
|
"jsdom": "^22.1.0",
|
|
84
|
-
"lint-staged": "^13.2.3",
|
|
85
98
|
"npm-run-all": "^4.1.5",
|
|
86
|
-
"prettier": "
|
|
87
|
-
"prettier-plugin-svelte": "
|
|
88
|
-
"svelte": "^4.
|
|
99
|
+
"prettier": "3.2.4",
|
|
100
|
+
"prettier-plugin-svelte": "3.1.2",
|
|
101
|
+
"svelte": "^4.2.10",
|
|
102
|
+
"svelte-check": "^3.6.3",
|
|
89
103
|
"svelte-jester": "^3.0.0",
|
|
90
104
|
"typescript": "^5.3.3",
|
|
91
|
-
"vite": "^
|
|
105
|
+
"vite": "^5.1.1",
|
|
92
106
|
"vitest": "^0.33.0"
|
|
93
|
-
},
|
|
94
|
-
"lint-staged": {
|
|
95
|
-
"{README.md,.all-contributorsrc}": [
|
|
96
|
-
"npm run toc",
|
|
97
|
-
"npm run contributors:generate",
|
|
98
|
-
"npx --no-install prettier --write README.md .all-contributorsrc",
|
|
99
|
-
"git add README.md .all-contributorsrc"
|
|
100
|
-
],
|
|
101
|
-
"src/**/*": [
|
|
102
|
-
"npx --no-install vitest related --run"
|
|
103
|
-
],
|
|
104
|
-
"*.{js,cjs,ts,svelte,json,yml,yaml}": [
|
|
105
|
-
"npx --no-install prettier --check"
|
|
106
|
-
],
|
|
107
|
-
"*.{js,cjs,ts,svelte}": [
|
|
108
|
-
"npx --no-install eslint"
|
|
109
|
-
]
|
|
110
|
-
},
|
|
111
|
-
"commitlint": {
|
|
112
|
-
"extends": [
|
|
113
|
-
"@commitlint/config-conventional"
|
|
114
|
-
]
|
|
115
107
|
}
|
|
116
108
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`render > should accept svelte component options 1`] = `
|
|
3
|
+
exports[`render > should accept svelte v4 component options 1`] = `
|
|
4
4
|
<body>
|
|
5
5
|
<div>
|
|
6
6
|
<h1
|
|
@@ -18,8 +18,31 @@ exports[`render > should accept svelte component options 1`] = `
|
|
|
18
18
|
<button>
|
|
19
19
|
Button
|
|
20
20
|
</button>
|
|
21
|
-
<!--<Comp>-->
|
|
22
21
|
<div />
|
|
23
22
|
</div>
|
|
24
23
|
</body>
|
|
25
24
|
`;
|
|
25
|
+
|
|
26
|
+
exports[`render > should accept svelte v5 component options 1`] = `
|
|
27
|
+
<body>
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
<section>
|
|
32
|
+
<h1
|
|
33
|
+
data-testid="test"
|
|
34
|
+
>
|
|
35
|
+
Hello World!
|
|
36
|
+
</h1>
|
|
37
|
+
|
|
38
|
+
<div>
|
|
39
|
+
we have context
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<button>
|
|
43
|
+
Button
|
|
44
|
+
</button>
|
|
45
|
+
|
|
46
|
+
</section>
|
|
47
|
+
</body>
|
|
48
|
+
`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import { act, fireEvent, render as stlRender } from '
|
|
3
|
+
import { act, fireEvent, render as stlRender } from '@testing-library/svelte'
|
|
4
4
|
import Comp from './fixtures/Comp.svelte'
|
|
5
5
|
|
|
6
6
|
describe('act', () => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest'
|
|
2
|
+
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
|
|
3
|
+
|
|
4
|
+
import { act, cleanup, render } from '@testing-library/svelte'
|
|
5
|
+
import Mounter from './fixtures/Mounter.svelte'
|
|
6
|
+
|
|
7
|
+
const onExecuted = vi.fn()
|
|
8
|
+
const onDestroyed = vi.fn()
|
|
9
|
+
const renderSubject = () => render(Mounter, { onExecuted, onDestroyed })
|
|
10
|
+
|
|
11
|
+
describe('cleanup', () => {
|
|
12
|
+
test('cleanup deletes element', async () => {
|
|
13
|
+
renderSubject()
|
|
14
|
+
cleanup()
|
|
15
|
+
|
|
16
|
+
expect(document.body).toBeEmptyDOMElement()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test.runIf(SVELTE_VERSION < '5')('cleanup unmounts component', async () => {
|
|
20
|
+
await act(renderSubject)
|
|
21
|
+
cleanup()
|
|
22
|
+
|
|
23
|
+
expect(onDestroyed).toHaveBeenCalledOnce()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('cleanup handles unexpected errors during mount', () => {
|
|
27
|
+
onExecuted.mockImplementation(() => {
|
|
28
|
+
throw new Error('oh no!')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
expect(renderSubject).toThrowError()
|
|
32
|
+
cleanup()
|
|
33
|
+
|
|
34
|
+
expect(document.body).toBeEmptyDOMElement()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { expect, test } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import { render } from '
|
|
3
|
+
import { render } from '@testing-library/svelte'
|
|
4
4
|
import Comp from './fixtures/Context.svelte'
|
|
5
|
+
import { IS_HAPPYDOM, IS_SVELTE_5 } from './utils.js'
|
|
5
6
|
|
|
6
|
-
test('can set a context', () => {
|
|
7
|
+
test.skipIf(IS_SVELTE_5 && IS_HAPPYDOM)('can set a context', () => {
|
|
7
8
|
const message = 'Got it'
|
|
8
9
|
|
|
9
10
|
const { getByText } = render(Comp, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { prettyDOM } from '@testing-library/dom'
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
|
3
3
|
|
|
4
|
-
import { render } from '
|
|
4
|
+
import { render } from '@testing-library/svelte'
|
|
5
5
|
import Comp from './fixtures/Comp.svelte'
|
|
6
6
|
|
|
7
7
|
describe('debug', () => {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onDestroy, onMount } from 'svelte'
|
|
3
|
+
|
|
4
|
+
export let onExecuted = undefined
|
|
5
|
+
export let onMounted = undefined
|
|
6
|
+
export let onDestroyed = undefined
|
|
7
|
+
|
|
8
|
+
onExecuted?.()
|
|
9
|
+
|
|
10
|
+
onMount(() => {
|
|
11
|
+
onMounted?.()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
onDestroy(() => {
|
|
15
|
+
onDestroyed?.()
|
|
16
|
+
})
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<button />
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onDestroy, onMount } from 'svelte'
|
|
3
|
+
|
|
4
|
+
export let onExecuted = undefined
|
|
5
|
+
export let onMounted = undefined
|
|
6
|
+
export let onDestroyed = undefined
|
|
7
|
+
|
|
8
|
+
export let name = ''
|
|
9
|
+
|
|
10
|
+
onExecuted?.()
|
|
11
|
+
|
|
12
|
+
onMount(() => onMounted?.())
|
|
13
|
+
|
|
14
|
+
onDestroy(() => onDestroyed?.())
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div data-testid="test">Hello {name}!</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { blur } from 'svelte/transition'
|
|
3
|
+
|
|
4
|
+
let show = false
|
|
5
|
+
let introDone = false
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<button on:click={() => (show = true)}>Show</button>
|
|
9
|
+
|
|
10
|
+
{#if show}
|
|
11
|
+
<div in:blur={{ duration: 64 }} on:introend={() => (introDone = true)}>
|
|
12
|
+
{#if introDone}
|
|
13
|
+
<p data-testid="intro-done">Done</p>
|
|
14
|
+
{:else}
|
|
15
|
+
<p data-testid="intro-pending">Pending</p>
|
|
16
|
+
{/if}
|
|
17
|
+
</div>
|
|
18
|
+
{/if}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { act, render, screen } from '@testing-library/svelte'
|
|
4
|
+
import Mounter from './fixtures/Mounter.svelte'
|
|
5
|
+
import { IS_HAPPYDOM, IS_SVELTE_5 } from './utils.js'
|
|
6
|
+
|
|
7
|
+
const onMounted = vi.fn()
|
|
8
|
+
const onDestroyed = vi.fn()
|
|
9
|
+
const renderSubject = () => render(Mounter, { onMounted, onDestroyed })
|
|
10
|
+
|
|
11
|
+
describe.skipIf(IS_SVELTE_5 && IS_HAPPYDOM)('mount and destroy', () => {
|
|
12
|
+
test('component is mounted', async () => {
|
|
13
|
+
renderSubject()
|
|
14
|
+
|
|
15
|
+
const content = screen.getByRole('button')
|
|
16
|
+
|
|
17
|
+
expect(content).toBeInTheDocument()
|
|
18
|
+
await act()
|
|
19
|
+
expect(onMounted).toHaveBeenCalledOnce()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('component is destroyed', async () => {
|
|
23
|
+
const { unmount } = renderSubject()
|
|
24
|
+
|
|
25
|
+
await act()
|
|
26
|
+
unmount()
|
|
27
|
+
|
|
28
|
+
const content = screen.queryByRole('button')
|
|
29
|
+
|
|
30
|
+
expect(content).not.toBeInTheDocument()
|
|
31
|
+
await act()
|
|
32
|
+
expect(onDestroyed).toHaveBeenCalledOnce()
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
|
|
1
2
|
import { beforeEach, describe, expect, test } from 'vitest'
|
|
2
3
|
|
|
3
|
-
import { act, render as stlRender } from '
|
|
4
|
+
import { act, render as stlRender } from '@testing-library/svelte'
|
|
4
5
|
import Comp from './fixtures/Comp.svelte'
|
|
5
6
|
import CompDefault from './fixtures/Comp2.svelte'
|
|
6
7
|
|
|
@@ -11,13 +12,13 @@ describe('render', () => {
|
|
|
11
12
|
return stlRender(Comp, {
|
|
12
13
|
target: document.body,
|
|
13
14
|
props,
|
|
14
|
-
...additional
|
|
15
|
+
...additional,
|
|
15
16
|
})
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
beforeEach(() => {
|
|
19
20
|
props = {
|
|
20
|
-
name: 'World'
|
|
21
|
+
name: 'World',
|
|
21
22
|
}
|
|
22
23
|
})
|
|
23
24
|
|
|
@@ -41,7 +42,9 @@ describe('render', () => {
|
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
test('change props with accessors', async () => {
|
|
44
|
-
const { component, getByText } = render(
|
|
45
|
+
const { component, getByText } = render(
|
|
46
|
+
SVELTE_VERSION < '5' ? { accessors: true } : {}
|
|
47
|
+
)
|
|
45
48
|
|
|
46
49
|
expect(getByText('Hello World!')).toBeInTheDocument()
|
|
47
50
|
|
|
@@ -59,23 +62,41 @@ describe('render', () => {
|
|
|
59
62
|
expect(getByText('Hello World!')).toBeInTheDocument()
|
|
60
63
|
})
|
|
61
64
|
|
|
62
|
-
test(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
target
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
test.runIf(SVELTE_VERSION < '5')(
|
|
66
|
+
'should accept svelte v4 component options',
|
|
67
|
+
() => {
|
|
68
|
+
const target = document.createElement('div')
|
|
69
|
+
const div = document.createElement('div')
|
|
70
|
+
document.body.appendChild(target)
|
|
71
|
+
target.appendChild(div)
|
|
72
|
+
const { container } = stlRender(Comp, {
|
|
73
|
+
target,
|
|
74
|
+
anchor: div,
|
|
75
|
+
props: { name: 'World' },
|
|
76
|
+
context: new Map([['name', 'context']]),
|
|
77
|
+
})
|
|
78
|
+
expect(container).toMatchSnapshot()
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
test.runIf(SVELTE_VERSION >= '5')(
|
|
83
|
+
'should accept svelte v5 component options',
|
|
84
|
+
() => {
|
|
85
|
+
const target = document.createElement('section')
|
|
86
|
+
document.body.appendChild(target)
|
|
87
|
+
|
|
88
|
+
const { container } = stlRender(Comp, {
|
|
89
|
+
target,
|
|
90
|
+
props: { name: 'World' },
|
|
91
|
+
context: new Map([['name', 'context']]),
|
|
92
|
+
})
|
|
93
|
+
expect(container).toMatchSnapshot()
|
|
94
|
+
}
|
|
95
|
+
)
|
|
75
96
|
|
|
76
97
|
test('should throw error when mixing svelte component options and props', () => {
|
|
77
98
|
expect(() => {
|
|
78
|
-
stlRender(Comp, {
|
|
99
|
+
stlRender(Comp, { props: {}, name: 'World' })
|
|
79
100
|
}).toThrow(/Unknown options were found/)
|
|
80
101
|
})
|
|
81
102
|
|
|
@@ -86,17 +107,15 @@ describe('render', () => {
|
|
|
86
107
|
})
|
|
87
108
|
|
|
88
109
|
test('correctly find component constructor on the default property', () => {
|
|
89
|
-
const { getByText } =
|
|
110
|
+
const { getByText } = stlRender(CompDefault, { props: { name: 'World' } })
|
|
90
111
|
|
|
91
112
|
expect(getByText('Hello World!')).toBeInTheDocument()
|
|
92
113
|
})
|
|
93
114
|
|
|
94
115
|
test("accept the 'context' option", () => {
|
|
95
116
|
const { getByText } = stlRender(Comp, {
|
|
96
|
-
props: {
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
context: new Map([['name', 'context']])
|
|
117
|
+
props: { name: 'Universe' },
|
|
118
|
+
context: new Map([['name', 'context']]),
|
|
100
119
|
})
|
|
101
120
|
|
|
102
121
|
expect(getByText('we have context')).toBeInTheDocument()
|
|
@@ -1,38 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { expect, test, vi } from 'vitest'
|
|
5
5
|
|
|
6
|
-
import { render } from '
|
|
7
|
-
import Comp from './fixtures/Comp.svelte'
|
|
6
|
+
import { render, waitFor } from '@testing-library/svelte'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
test('mounts new component successfully', () => {
|
|
11
|
-
const { container, rerender } = render(Comp, { props: { name: 'World 1' } })
|
|
8
|
+
import Comp from './fixtures/Rerender.svelte'
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
test('mounts new component successfully', async () => {
|
|
11
|
+
const onMounted = vi.fn()
|
|
12
|
+
const onDestroyed = vi.fn()
|
|
13
|
+
|
|
14
|
+
const { getByTestId, rerender } = render(Comp, {
|
|
15
|
+
props: { name: 'World 1', onMounted, onDestroyed },
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const expectToRender = (content) =>
|
|
19
|
+
waitFor(() => {
|
|
20
|
+
expect(getByTestId('test')).toHaveTextContent(content)
|
|
21
|
+
expect(onMounted).toHaveBeenCalledOnce()
|
|
22
|
+
})
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
await expectToRender('Hello World 1!')
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
isDestroyed = true
|
|
25
|
-
})
|
|
26
|
-
rerender({ props: { name: '' } })
|
|
27
|
-
expect(isDestroyed).toBeTruthy()
|
|
28
|
-
})
|
|
26
|
+
console.warn = vi.fn()
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
rerender({ props: { name: 'World 2' } })
|
|
29
|
+
await expectToRender('Hello World 2!')
|
|
30
|
+
expect(onDestroyed).not.toHaveBeenCalled()
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
})
|
|
32
|
+
expect(console.warn).toHaveBeenCalledOnce()
|
|
33
|
+
|
|
34
|
+
console.warn.mockClear()
|
|
35
|
+
onDestroyed.mockReset()
|
|
36
|
+
rerender({ name: 'World 3' })
|
|
37
|
+
await expectToRender('Hello World 3!')
|
|
38
|
+
expect(onDestroyed).not.toHaveBeenCalled()
|
|
39
|
+
|
|
40
|
+
expect(console.warn).not.toHaveBeenCalled()
|
|
38
41
|
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { userEvent } from '@testing-library/user-event'
|
|
2
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { IS_JSDOM, IS_SVELTE_5 } from './utils.js'
|
|
5
|
+
|
|
6
|
+
import { render, screen, waitFor } from '@testing-library/svelte'
|
|
7
|
+
import Transitioner from './fixtures/Transitioner.svelte'
|
|
8
|
+
|
|
9
|
+
describe.runIf(!IS_SVELTE_5)('transitions', () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
if (!IS_JSDOM) return
|
|
12
|
+
|
|
13
|
+
const raf = (fn) => setTimeout(() => fn(new Date()), 16)
|
|
14
|
+
vi.stubGlobal('requestAnimationFrame', raf)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('on:introend', async () => {
|
|
18
|
+
const user = userEvent.setup()
|
|
19
|
+
|
|
20
|
+
render(Transitioner)
|
|
21
|
+
const start = screen.getByRole('button')
|
|
22
|
+
await user.click(start)
|
|
23
|
+
|
|
24
|
+
const pending = screen.getByTestId('intro-pending')
|
|
25
|
+
expect(pending).toBeInTheDocument()
|
|
26
|
+
|
|
27
|
+
await waitFor(() => {
|
|
28
|
+
const done = screen.queryByTestId('intro-done')
|
|
29
|
+
expect(done).toBeInTheDocument()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
})
|
package/src/index.js
CHANGED
package/src/pure.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fireEvent as dtlFireEvent,
|
|
3
3
|
getQueriesForElement,
|
|
4
|
-
prettyDOM
|
|
4
|
+
prettyDOM,
|
|
5
5
|
} from '@testing-library/dom'
|
|
6
|
-
import {
|
|
6
|
+
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
|
|
7
|
+
import * as Svelte from 'svelte'
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
9
|
+
const IS_SVELTE_5 = /^5\./.test(SVELTE_VERSION)
|
|
10
|
+
export const targetCache = new Set()
|
|
11
|
+
export const componentCache = new Set()
|
|
10
12
|
|
|
11
13
|
const svelteComponentOptions = [
|
|
12
14
|
'accessors',
|
|
@@ -14,124 +16,138 @@ const svelteComponentOptions = [
|
|
|
14
16
|
'props',
|
|
15
17
|
'hydrate',
|
|
16
18
|
'intro',
|
|
17
|
-
'context'
|
|
19
|
+
'context',
|
|
18
20
|
]
|
|
19
21
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) => {
|
|
25
|
-
container = container || document.body
|
|
26
|
-
target = target || container.appendChild(document.createElement('div'))
|
|
22
|
+
export const buildCheckProps = (svelteComponentOptions) => (options) => {
|
|
23
|
+
const isProps = !Object.keys(options).some((option) =>
|
|
24
|
+
svelteComponentOptions.includes(option)
|
|
25
|
+
)
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
svelteComponentOptions.includes(option)
|
|
27
|
+
// Check if any props and Svelte options were accidentally mixed.
|
|
28
|
+
if (!isProps) {
|
|
29
|
+
const unrecognizedOptions = Object.keys(options).filter(
|
|
30
|
+
(option) => !svelteComponentOptions.includes(option)
|
|
33
31
|
)
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const unrecognizedOptions = Object.keys(options).filter(
|
|
38
|
-
(option) => !svelteComponentOptions.includes(option)
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
if (unrecognizedOptions.length > 0) {
|
|
42
|
-
throw Error(`
|
|
33
|
+
if (unrecognizedOptions.length > 0) {
|
|
34
|
+
throw Error(`
|
|
43
35
|
Unknown options were found [${unrecognizedOptions}]. This might happen if you've mixed
|
|
44
36
|
passing in props with Svelte options into the render function. Valid Svelte options
|
|
45
37
|
are [${svelteComponentOptions}]. You can either change the prop names, or pass in your
|
|
46
38
|
props for that component via the \`props\` option.\n\n
|
|
47
39
|
Eg: const { /** Results **/ } = render(MyComponent, { props: { /** props here **/ } })\n\n
|
|
48
40
|
`)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return options
|
|
52
41
|
}
|
|
53
42
|
|
|
54
|
-
return
|
|
43
|
+
return options
|
|
55
44
|
}
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
containerCache.add({ container, target, component })
|
|
63
|
-
componentCache.add(component)
|
|
64
|
-
|
|
65
|
-
component.$$.on_destroy.push(() => {
|
|
66
|
-
componentCache.delete(component)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
container,
|
|
71
|
-
component,
|
|
72
|
-
debug: (el = container) => console.log(prettyDOM(el)),
|
|
73
|
-
rerender: (options) => {
|
|
74
|
-
if (componentCache.has(component)) component.$destroy()
|
|
75
|
-
|
|
76
|
-
// eslint-disable-next-line no-new
|
|
77
|
-
component = new ComponentConstructor({
|
|
78
|
-
target,
|
|
79
|
-
...checkProps(options)
|
|
80
|
-
})
|
|
46
|
+
return { props: options }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const checkProps = buildCheckProps(svelteComponentOptions)
|
|
81
50
|
|
|
82
|
-
|
|
83
|
-
|
|
51
|
+
const buildRenderComponent =
|
|
52
|
+
({ target, ComponentConstructor }) =>
|
|
53
|
+
(options) => {
|
|
54
|
+
options = { target, ...checkProps(options) }
|
|
84
55
|
|
|
56
|
+
if (IS_SVELTE_5)
|
|
57
|
+
throw new Error('for Svelte 5, use `@testing-library/svelte/svelte5`')
|
|
58
|
+
|
|
59
|
+
const component = new ComponentConstructor(options)
|
|
60
|
+
|
|
61
|
+
componentCache.add(component)
|
|
62
|
+
|
|
63
|
+
// TODO(mcous, 2024-02-11): remove this behavior in the next major version
|
|
64
|
+
// It is unnecessary has no path to implementation in Svelte v5
|
|
65
|
+
if (!IS_SVELTE_5) {
|
|
85
66
|
component.$$.on_destroy.push(() => {
|
|
86
67
|
componentCache.delete(component)
|
|
87
68
|
})
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
...getQueriesForElement(container, queries)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return component
|
|
93
72
|
}
|
|
94
|
-
}
|
|
95
73
|
|
|
96
|
-
const
|
|
97
|
-
|
|
74
|
+
export const buildRender =
|
|
75
|
+
(buildRenderComponent) =>
|
|
76
|
+
(Component, { target, ...options } = {}, { container, queries } = {}) => {
|
|
77
|
+
container = container || document.body
|
|
78
|
+
target = target || container.appendChild(document.createElement('div'))
|
|
79
|
+
targetCache.add(target)
|
|
80
|
+
|
|
81
|
+
const ComponentConstructor = Component.default || Component
|
|
82
|
+
|
|
83
|
+
const renderComponent = buildRenderComponent({
|
|
84
|
+
target,
|
|
85
|
+
ComponentConstructor,
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
let component = renderComponent(options)
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
container,
|
|
92
|
+
component,
|
|
93
|
+
debug: (el = container) => console.log(prettyDOM(el)),
|
|
94
|
+
rerender: async (props) => {
|
|
95
|
+
if (props.props) {
|
|
96
|
+
console.warn(
|
|
97
|
+
'rerender({ props: {...} }) deprecated, use rerender({...}) instead'
|
|
98
|
+
)
|
|
99
|
+
props = props.props
|
|
100
|
+
}
|
|
101
|
+
component.$set(props)
|
|
102
|
+
await Svelte.tick()
|
|
103
|
+
},
|
|
104
|
+
unmount: () => {
|
|
105
|
+
cleanupComponent(component)
|
|
106
|
+
},
|
|
107
|
+
...getQueriesForElement(container, queries),
|
|
108
|
+
}
|
|
109
|
+
}
|
|
98
110
|
|
|
99
|
-
|
|
111
|
+
export const render = buildRender(buildRenderComponent)
|
|
100
112
|
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
export const cleanupComponent = (component) => {
|
|
114
|
+
const inCache = componentCache.delete(component)
|
|
115
|
+
|
|
116
|
+
if (inCache) {
|
|
117
|
+
component.$destroy()
|
|
103
118
|
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const cleanupTarget = (target) => {
|
|
122
|
+
const inCache = targetCache.delete(target)
|
|
104
123
|
|
|
105
|
-
|
|
124
|
+
if (inCache && target.parentNode === document.body) {
|
|
125
|
+
document.body.removeChild(target)
|
|
126
|
+
}
|
|
106
127
|
}
|
|
107
128
|
|
|
108
|
-
const cleanup = () => {
|
|
109
|
-
|
|
129
|
+
export const cleanup = () => {
|
|
130
|
+
componentCache.forEach(cleanupComponent)
|
|
131
|
+
targetCache.forEach(cleanupTarget)
|
|
110
132
|
}
|
|
111
133
|
|
|
112
|
-
const act = async (fn) => {
|
|
134
|
+
export const act = async (fn) => {
|
|
113
135
|
if (fn) {
|
|
114
136
|
await fn()
|
|
115
137
|
}
|
|
116
|
-
return tick()
|
|
138
|
+
return Svelte.tick()
|
|
117
139
|
}
|
|
118
140
|
|
|
119
|
-
const fireEvent = async (...args) => {
|
|
141
|
+
export const fireEvent = async (...args) => {
|
|
120
142
|
const event = dtlFireEvent(...args)
|
|
121
|
-
await tick()
|
|
143
|
+
await Svelte.tick()
|
|
122
144
|
return event
|
|
123
145
|
}
|
|
124
146
|
|
|
125
147
|
Object.keys(dtlFireEvent).forEach((key) => {
|
|
126
148
|
fireEvent[key] = async (...args) => {
|
|
127
149
|
const event = dtlFireEvent[key](...args)
|
|
128
|
-
await tick()
|
|
150
|
+
await Svelte.tick()
|
|
129
151
|
return event
|
|
130
152
|
}
|
|
131
153
|
})
|
|
132
|
-
|
|
133
|
-
/* eslint-disable import/export */
|
|
134
|
-
|
|
135
|
-
export * from '@testing-library/dom'
|
|
136
|
-
|
|
137
|
-
export { render, cleanup, fireEvent, act }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { act, cleanup } from './svelte5.js'
|
|
2
|
+
|
|
3
|
+
// If we're running in a test runner that supports afterEach
|
|
4
|
+
// then we'll automatically run cleanup afterEach test
|
|
5
|
+
// this ensures that tests run in isolation from each other
|
|
6
|
+
// if you don't like this then either import the `pure` module
|
|
7
|
+
// or set the STL_SKIP_AUTO_CLEANUP env variable to 'true'.
|
|
8
|
+
if (typeof afterEach === 'function' && !process.env.STL_SKIP_AUTO_CLEANUP) {
|
|
9
|
+
afterEach(async () => {
|
|
10
|
+
await act()
|
|
11
|
+
cleanup()
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export * from './svelte5.js'
|
|
16
|
+
export * from '@testing-library/dom'
|
|
17
|
+
export { act, fireEvent } from './pure.js'
|
package/src/svelte5.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createClassComponent } from 'svelte/legacy'
|
|
2
|
+
import {
|
|
3
|
+
componentCache,
|
|
4
|
+
cleanup,
|
|
5
|
+
buildCheckProps,
|
|
6
|
+
buildRender,
|
|
7
|
+
} from './pure.js'
|
|
8
|
+
|
|
9
|
+
const svelteComponentOptions = [
|
|
10
|
+
'target',
|
|
11
|
+
'props',
|
|
12
|
+
'events',
|
|
13
|
+
'context',
|
|
14
|
+
'intro',
|
|
15
|
+
'recover',
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const checkProps = buildCheckProps(svelteComponentOptions)
|
|
19
|
+
|
|
20
|
+
const buildRenderComponent =
|
|
21
|
+
({ target, ComponentConstructor }) =>
|
|
22
|
+
(options) => {
|
|
23
|
+
options = { target, ...checkProps(options) }
|
|
24
|
+
|
|
25
|
+
const component = createClassComponent({
|
|
26
|
+
component: ComponentConstructor,
|
|
27
|
+
...options,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
componentCache.add(component)
|
|
31
|
+
|
|
32
|
+
return component
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const render = buildRender(buildRenderComponent)
|
|
36
|
+
|
|
37
|
+
/* eslint-disable import/export */
|
|
38
|
+
|
|
39
|
+
import { act, fireEvent } from './pure.js'
|
|
40
|
+
|
|
41
|
+
export { render, cleanup, fireEvent, act }
|
package/src/vitest.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -2,25 +2,42 @@
|
|
|
2
2
|
// Project: https://github.com/testing-library/svelte-testing-library
|
|
3
3
|
// Definitions by: Rahim Alwer <https://github.com/mihar-22>
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
BoundFunction,
|
|
7
|
+
EventType,
|
|
8
|
+
Queries,
|
|
9
|
+
queries,
|
|
10
|
+
} from '@testing-library/dom'
|
|
11
|
+
import {
|
|
12
|
+
ComponentConstructorOptions,
|
|
13
|
+
ComponentProps,
|
|
14
|
+
SvelteComponent,
|
|
15
|
+
} from 'svelte'
|
|
7
16
|
|
|
8
17
|
export * from '@testing-library/dom'
|
|
9
18
|
|
|
10
|
-
type SvelteComponentOptions<C extends SvelteComponent> =
|
|
19
|
+
type SvelteComponentOptions<C extends SvelteComponent> =
|
|
20
|
+
| ComponentProps<C>
|
|
21
|
+
| Pick<
|
|
22
|
+
ComponentConstructorOptions<ComponentProps<C>>,
|
|
23
|
+
'anchor' | 'props' | 'hydrate' | 'intro' | 'context'
|
|
24
|
+
>
|
|
11
25
|
|
|
12
26
|
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
|
|
13
27
|
|
|
14
|
-
type Constructor<T> = new (...args: any[]) => T
|
|
28
|
+
type Constructor<T> = new (...args: any[]) => T
|
|
15
29
|
|
|
16
30
|
/**
|
|
17
31
|
* Render a Component into the Document.
|
|
18
32
|
*/
|
|
19
|
-
export type RenderResult<
|
|
33
|
+
export type RenderResult<
|
|
34
|
+
C extends SvelteComponent,
|
|
35
|
+
Q extends Queries = typeof queries,
|
|
36
|
+
> = {
|
|
20
37
|
container: HTMLElement
|
|
21
38
|
component: C
|
|
22
39
|
debug: (el?: HTMLElement | DocumentFragment) => void
|
|
23
|
-
rerender: (
|
|
40
|
+
rerender: (props: ComponentProps<C>) => Promise<void>
|
|
24
41
|
unmount: () => void
|
|
25
42
|
} & { [P in keyof Q]: BoundFunction<Q[P]> }
|
|
26
43
|
|
|
@@ -38,7 +55,7 @@ export function render<C extends SvelteComponent>(
|
|
|
38
55
|
export function render<C extends SvelteComponent, Q extends Queries>(
|
|
39
56
|
component: Constructor<C>,
|
|
40
57
|
componentOptions?: SvelteComponentOptions<C>,
|
|
41
|
-
renderOptions?: RenderOptions<Q
|
|
58
|
+
renderOptions?: RenderOptions<Q>
|
|
42
59
|
): RenderResult<C, Q>
|
|
43
60
|
|
|
44
61
|
/**
|
|
@@ -50,13 +67,19 @@ export function cleanup(): void
|
|
|
50
67
|
* Fires DOM events on an element provided by @testing-library/dom. Since Svelte needs to flush
|
|
51
68
|
* pending state changes via `tick`, these methods have been override and now return a promise.
|
|
52
69
|
*/
|
|
53
|
-
export type FireFunction = (
|
|
70
|
+
export type FireFunction = (
|
|
71
|
+
element: Document | Element | Window,
|
|
72
|
+
event: Event
|
|
73
|
+
) => Promise<boolean>
|
|
54
74
|
|
|
55
75
|
export type FireObject = {
|
|
56
|
-
[K in EventType]: (
|
|
57
|
-
|
|
76
|
+
[K in EventType]: (
|
|
77
|
+
element: Document | Element | Window,
|
|
78
|
+
options?: {}
|
|
79
|
+
) => Promise<boolean>
|
|
80
|
+
}
|
|
58
81
|
|
|
59
|
-
export const fireEvent: FireFunction & FireObject
|
|
82
|
+
export const fireEvent: FireFunction & FireObject
|
|
60
83
|
|
|
61
84
|
/**
|
|
62
85
|
* Calls a function and notifies Svelte to flush any pending state changes.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { onDestroy } from 'svelte'
|
|
3
|
-
|
|
4
|
-
let timer
|
|
5
|
-
let lapse = 0
|
|
6
|
-
let running = false
|
|
7
|
-
|
|
8
|
-
function handleRunClick () {
|
|
9
|
-
if (running) {
|
|
10
|
-
clearInterval(timer)
|
|
11
|
-
} else {
|
|
12
|
-
const startTime = Date.now() - lapse
|
|
13
|
-
|
|
14
|
-
timer = setInterval(() => {
|
|
15
|
-
lapse = Date.now() - startTime
|
|
16
|
-
}, 1)
|
|
17
|
-
}
|
|
18
|
-
running = true
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function handleClearClick () {
|
|
22
|
-
clearInterval(timer)
|
|
23
|
-
lapse = 0
|
|
24
|
-
running = false
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
onDestroy(() => {
|
|
28
|
-
clearInterval(timer)
|
|
29
|
-
})
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<style></style>
|
|
33
|
-
|
|
34
|
-
<span>{lapse}ms</span>
|
|
35
|
-
|
|
36
|
-
<button on:click={handleRunClick}>
|
|
37
|
-
{running ? 'Stop' : 'Start'}
|
|
38
|
-
</button>
|
|
39
|
-
|
|
40
|
-
<button on:click={handleClearClick}>Clear</button>
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, vi } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { act, fireEvent, render } from '..'
|
|
4
|
-
import Stopwatch from './fixtures/Stopwatch.svelte'
|
|
5
|
-
|
|
6
|
-
describe('unmount', () => {
|
|
7
|
-
test('unmounts component successfully', async () => {
|
|
8
|
-
console.warn = vi.fn()
|
|
9
|
-
|
|
10
|
-
const { unmount, getByText, container } = render(Stopwatch)
|
|
11
|
-
|
|
12
|
-
await fireEvent.click(getByText('Start'))
|
|
13
|
-
|
|
14
|
-
unmount()
|
|
15
|
-
|
|
16
|
-
// Hey there reader! You don't need to have an assertion like this one
|
|
17
|
-
// this is just me making sure that the unmount function works.
|
|
18
|
-
// You don't need to do this in your apps. Just rely on the fact that this works.
|
|
19
|
-
expect(container.innerHTML).toBe('<div></div>')
|
|
20
|
-
|
|
21
|
-
await act()
|
|
22
|
-
expect(console.warn).not.toHaveBeenCalled()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test('destroying component directly and calling unmount does not log warning', async () => {
|
|
26
|
-
console.warn = vi.fn()
|
|
27
|
-
|
|
28
|
-
const { unmount, component } = render(Stopwatch)
|
|
29
|
-
|
|
30
|
-
component.$destroy()
|
|
31
|
-
unmount()
|
|
32
|
-
|
|
33
|
-
expect(console.warn).not.toHaveBeenCalled()
|
|
34
|
-
})
|
|
35
|
-
})
|