@testing-library/svelte 3.2.2 → 4.0.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 CHANGED
@@ -10,8 +10,7 @@
10
10
  />
11
11
  </a>
12
12
 
13
- <p>Simple and complete Svelte testing utilities that encourage good testing
14
- practices.</p>
13
+ <p>Simple and complete Svelte testing utilities that encourage good testing practices.</p>
15
14
 
16
15
  [**Read The Docs**](https://testing-library.com/docs/svelte-testing-library/intro) |
17
16
  [Edit the docs](https://github.com/alexkrolick/testing-library-docs)
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@testing-library/svelte",
3
- "version": "3.2.2",
3
+ "version": "4.0.1",
4
4
  "description": "Simple and complete Svelte testing utilities that encourage good testing practices.",
5
- "main": "dist/index.js",
5
+ "exports": {
6
+ ".": {
7
+ "default": "./src/index.js",
8
+ "types": "./types/index.d.ts"
9
+ }
10
+ },
11
+ "type": "module",
6
12
  "types": "types/index.d.ts",
7
13
  "license": "MIT",
8
14
  "homepage": "https://github.com/testing-library/svelte-testing-library#readme",
@@ -29,57 +35,50 @@
29
35
  "e2e"
30
36
  ],
31
37
  "files": [
32
- "dist",
33
- "dont-cleanup-after-each.js",
34
- "pure.js",
38
+ "src/",
35
39
  "types/index.d.ts"
36
40
  ],
37
41
  "scripts": {
38
42
  "toc": "doctoc README.md",
39
43
  "lint": "eslint src --fix",
40
- "clean": "rimraf dist",
41
- "build": "npm run clean && babel src --out-dir dist --ignore '**/__tests__/**'",
42
- "test": "jest src",
44
+ "test": "vitest run src",
43
45
  "test:watch": "npm run test -- --watch",
44
46
  "test:update": "npm run test -- --updateSnapshot --coverage",
45
47
  "setup": "npm install && npm run validate",
46
- "validate": "npm run clean && npm-run-all lint test build",
48
+ "validate": "npm-run-all lint test",
47
49
  "contributors:add": "all-contributors add",
48
50
  "contributors:generate": "all-contributors generate"
49
51
  },
50
52
  "peerDependencies": {
51
- "svelte": "3.x"
53
+ "svelte": "^3 || ^4"
52
54
  },
53
55
  "dependencies": {
54
56
  "@testing-library/dom": "^8.1.0"
55
57
  },
56
58
  "devDependencies": {
57
- "@babel/cli": "^7.6.2",
58
- "@babel/core": "^7.6.2",
59
- "@babel/plugin-transform-modules-commonjs": "^7.6.0",
60
- "@babel/preset-env": "^7.6.2",
61
59
  "@commitlint/cli": "^13.1.0",
62
60
  "@commitlint/config-conventional": "^13.1.0",
63
- "@testing-library/jest-dom": "^5.0.2",
64
- "@types/jest": "^27.0.0",
61
+ "@sveltejs/vite-plugin-svelte": "^2.4.1",
62
+ "@testing-library/jest-dom": "^5.16.5",
63
+ "@vitest/coverage-c8": "^0.32.0",
65
64
  "all-contributors-cli": "^6.9.0",
66
- "babel-eslint": "^10.0.3",
67
- "babel-jest": "^27.0.6",
68
65
  "doctoc": "^2.0.0",
69
- "eslint": "^7.2.0",
70
- "eslint-config-standard": "^16.0.0",
71
- "eslint-plugin-import": "^2.18.2",
72
- "eslint-plugin-node": "^11.0.0",
73
- "eslint-plugin-promise": "^5.1.0",
74
- "eslint-plugin-simple-import-sort": "^7.0.0",
75
- "eslint-plugin-svelte3": "^3.0.0",
66
+ "eslint": "^8.42.0",
67
+ "eslint-plugin-import": "^2.27.5",
68
+ "eslint-plugin-n": "^16.0.0",
69
+ "eslint-plugin-promise": "^6.1.1",
70
+ "eslint-plugin-simple-import-sort": "^10.0.0",
71
+ "eslint-config-standard": "^17.1.0",
72
+ "eslint-plugin-svelte": "^2.30.0",
73
+ "eslint-plugin-vitest-globals": "^1.3.1",
76
74
  "husky": "^7.0.1",
77
- "jest": "^27.0.0",
75
+ "jsdom": "^22.1.0",
78
76
  "lint-staged": "^11.1.1",
79
77
  "npm-run-all": "^4.1.5",
80
78
  "prettier": "^2.0.1",
81
- "svelte": "^3.0.0",
82
- "svelte-jester": "^2.1.4"
79
+ "svelte": "^3.59.1",
80
+ "vite": "^4.3.9",
81
+ "vitest": "^0.32.0"
83
82
  },
84
83
  "husky": {
85
84
  "hooks": {
@@ -107,26 +106,5 @@
107
106
  "extends": [
108
107
  "@commitlint/config-conventional"
109
108
  ]
110
- },
111
- "jest": {
112
- "testPathIgnorePatterns": [
113
- "src/__tests__/fixtures"
114
- ],
115
- "collectCoverageFrom": [
116
- "src/*.js"
117
- ],
118
- "setupFilesAfterEnv": [
119
- "@testing-library/jest-dom/extend-expect"
120
- ],
121
- "testEnvironment": "jsdom",
122
- "transform": {
123
- "^.+\\.js$": "babel-jest",
124
- "^.+\\.svelte$": "svelte-jester",
125
- "^.+\\.html$": "svelte-jester"
126
- },
127
- "moduleFileExtensions": [
128
- "js",
129
- "svelte"
130
- ]
131
109
  }
132
110
  }
@@ -0,0 +1,3 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`auto-cleanup-skip > second 1`] = `""`;
@@ -0,0 +1,25 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`render > should accept svelte component options 1`] = `
4
+ <body>
5
+ <div>
6
+ <h1
7
+ data-testid="test"
8
+ >
9
+ Hello
10
+ World
11
+ !
12
+ </h1>
13
+
14
+ <div>
15
+ we have context
16
+ </div>
17
+
18
+ <button>
19
+ Button
20
+ </button>
21
+ <!--&lt;Comp&gt;-->
22
+ <div />
23
+ </div>
24
+ </body>
25
+ `;
@@ -0,0 +1,56 @@
1
+ import { beforeEach, describe, expect, test } from 'vitest'
2
+
3
+ import { act, fireEvent, render as stlRender } from '..'
4
+ import Comp from './fixtures/Comp.svelte'
5
+
6
+ describe('act', () => {
7
+ let props
8
+
9
+ const render = () => {
10
+ return stlRender(Comp, {
11
+ props
12
+ })
13
+ }
14
+
15
+ beforeEach(() => {
16
+ props = {
17
+ name: 'World'
18
+ }
19
+ })
20
+
21
+ test('state updates are flushed', async () => {
22
+ const { getByText } = render()
23
+ const button = getByText('Button')
24
+
25
+ expect(button).toHaveTextContent('Button')
26
+
27
+ await act(() => {
28
+ button.click()
29
+ })
30
+
31
+ expect(button).toHaveTextContent('Button Clicked')
32
+ })
33
+
34
+ test('findByTestId returns the element', async () => {
35
+ const { findByTestId } = render()
36
+
37
+ expect(await findByTestId('test')).toHaveTextContent(`Hello ${props.name}!`)
38
+ })
39
+
40
+ test('accepts async functions', async () => {
41
+ const sleep = (ms) =>
42
+ new Promise((resolve) => {
43
+ setTimeout(() => resolve(), ms)
44
+ })
45
+
46
+ const { getByText } = render()
47
+ const button = getByText('Button')
48
+
49
+ await act(async () => {
50
+ await sleep(100)
51
+ await fireEvent.click(button)
52
+ })
53
+
54
+ expect(button).toHaveTextContent('Button Clicked')
55
+ })
56
+ })
@@ -0,0 +1,23 @@
1
+ import { beforeAll, describe, expect, test } from 'vitest'
2
+
3
+ import Comp from './fixtures/Comp.svelte'
4
+
5
+ describe('auto-cleanup-skip', () => {
6
+ let render
7
+
8
+ beforeAll(async () => {
9
+ process.env.STL_SKIP_AUTO_CLEANUP = 'true'
10
+ const stl = await import('..')
11
+ render = stl.render
12
+ })
13
+
14
+ // This one verifies that if STL_SKIP_AUTO_CLEANUP is set
15
+ // then we DON'T auto-wire up the afterEach for folks
16
+ test('first', () => {
17
+ render(Comp, { props: { name: 'world' } })
18
+ })
19
+
20
+ test('second', () => {
21
+ expect(document.body.innerHTML).toMatchSnapshot()
22
+ })
23
+ })
@@ -0,0 +1,31 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import { render } from '..'
4
+ import Comp from './fixtures/Comp.svelte'
5
+
6
+ describe('auto-cleanup', () => {
7
+ // This just verifies that by importing STL in an
8
+ // environment which supports afterEach (like jest)
9
+ // we'll get automatic cleanup between tests.
10
+ test('first', () => {
11
+ render(Comp, { props: { name: 'world' } })
12
+ })
13
+
14
+ test('second', () => {
15
+ expect(document.body.innerHTML).toEqual('')
16
+ })
17
+ })
18
+
19
+ describe('cleanup of two components', () => {
20
+ // This just verifies that by importing STL in an
21
+ // environment which supports afterEach (like jest)
22
+ // we'll get automatic cleanup between tests.
23
+ test('first', () => {
24
+ render(Comp, { props: { name: 'world' } })
25
+ render(Comp, { props: { name: 'universe' } })
26
+ })
27
+
28
+ test('second', () => {
29
+ expect(document.body.innerHTML).toEqual('')
30
+ })
31
+ })
@@ -0,0 +1,24 @@
1
+ import { prettyDOM } from '@testing-library/dom'
2
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
3
+
4
+ import { render } from '..'
5
+ import Comp from './fixtures/Comp.svelte'
6
+
7
+ describe('debug', () => {
8
+ beforeEach(() => {
9
+ vi.spyOn(console, 'log').mockImplementation(() => { })
10
+ })
11
+
12
+ afterEach(() => {
13
+ console.log.mockRestore()
14
+ })
15
+
16
+ test('pretty prints the container', () => {
17
+ const { container, debug } = render(Comp, { props: { name: 'world' } })
18
+
19
+ debug()
20
+
21
+ expect(console.log).toHaveBeenCalledTimes(1)
22
+ expect(console.log).toHaveBeenCalledWith(prettyDOM(container))
23
+ })
24
+ })
@@ -0,0 +1,30 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import { fireEvent, render } from '..'
4
+ import Comp from './fixtures/Comp.svelte'
5
+
6
+ describe('events', () => {
7
+ test('state changes are flushed after firing an event', async () => {
8
+ const { getByText } = render(Comp, { props: { name: 'World' } })
9
+ const button = getByText('Button')
10
+
11
+ await fireEvent.click(button)
12
+
13
+ expect(button).toHaveTextContent('Button Clicked')
14
+ })
15
+
16
+ test('calling `fireEvent` directly works too', async () => {
17
+ const { getByText } = render(Comp, { props: { name: 'World' } })
18
+ const button = getByText('Button')
19
+
20
+ await fireEvent(
21
+ button,
22
+ new MouseEvent('click', {
23
+ bubbles: true,
24
+ cancelable: true
25
+ })
26
+ )
27
+
28
+ expect(button).toHaveTextContent('Button Clicked')
29
+ })
30
+ })
@@ -0,0 +1,23 @@
1
+ <svelte:options accessors />
2
+
3
+ <script>
4
+ import { getContext } from 'svelte'
5
+
6
+ export let name
7
+
8
+ let buttonText = 'Button'
9
+
10
+ const contextName = getContext('name')
11
+
12
+ function handleClick () {
13
+ buttonText = 'Button Clicked'
14
+ }
15
+ </script>
16
+
17
+ <h1 data-testid="test">Hello {name}!</h1>
18
+
19
+ <div>we have {contextName}</div>
20
+
21
+ <button on:click={handleClick}>{buttonText}</button>
22
+
23
+ <style></style>
@@ -0,0 +1,15 @@
1
+ <script>
2
+ export let name
3
+
4
+ let buttonText = 'Button Text'
5
+
6
+ function handleClick () {
7
+ buttonText = 'Button Clicked'
8
+ }
9
+ </script>
10
+
11
+ <style></style>
12
+
13
+ <h1>Hello {name}!</h1>
14
+
15
+ <button on:click={handleClick}>{buttonText}</button>
@@ -0,0 +1,40 @@
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>
@@ -0,0 +1,42 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import { render } from '..'
4
+ import Comp from './fixtures/Comp.svelte'
5
+
6
+ describe('multi-base', () => {
7
+ const treeA = document.createElement('div')
8
+ const treeB = document.createElement('div')
9
+
10
+ test('container isolates trees from one another', () => {
11
+ const { getByText: getByTextInA } = render(
12
+ Comp,
13
+ {
14
+ target: treeA,
15
+ props: {
16
+ name: 'Tree A'
17
+ }
18
+ },
19
+ {
20
+ container: treeA
21
+ }
22
+ )
23
+
24
+ const { getByText: getByTextInB } = render(
25
+ Comp,
26
+ {
27
+ target: treeB,
28
+ props: {
29
+ name: 'Tree B'
30
+ }
31
+ },
32
+ {
33
+ container: treeB
34
+ }
35
+ )
36
+
37
+ expect(() => getByTextInA('Hello Tree A!')).not.toThrow()
38
+ expect(() => getByTextInB('Hello Tree A!')).toThrow()
39
+ expect(() => getByTextInA('Hello Tree B!')).toThrow()
40
+ expect(() => getByTextInB('Hello Tree B!')).not.toThrow()
41
+ })
42
+ })
@@ -0,0 +1,104 @@
1
+ import { beforeEach, describe, expect, test } from 'vitest'
2
+
3
+ import { act, render as stlRender } from '..'
4
+ import Comp from './fixtures/Comp.svelte'
5
+ import CompDefault from './fixtures/Comp2.svelte'
6
+
7
+ describe('render', () => {
8
+ let props
9
+
10
+ const render = (additional = {}) => {
11
+ return stlRender(Comp, {
12
+ target: document.body,
13
+ props,
14
+ ...additional
15
+ })
16
+ }
17
+
18
+ beforeEach(() => {
19
+ props = {
20
+ name: 'World'
21
+ }
22
+ })
23
+
24
+ test('renders component into the document', () => {
25
+ const { getByText } = render()
26
+
27
+ expect(getByText('Hello World!')).toBeInTheDocument()
28
+ })
29
+
30
+ // Dear reader, this is not something you generally want to do in your tests.
31
+ test('programmatically change props', async () => {
32
+ const { component, getByText } = render()
33
+
34
+ expect(getByText('Hello World!')).toBeInTheDocument()
35
+
36
+ await act(() => {
37
+ component.$set({ name: 'Worlds' })
38
+ })
39
+
40
+ expect(getByText('Hello Worlds!')).toBeInTheDocument()
41
+ })
42
+
43
+ test('change props with accessors', async () => {
44
+ const { component, getByText } = render({ accessors: true })
45
+
46
+ expect(getByText('Hello World!')).toBeInTheDocument()
47
+
48
+ expect(component.name).toBe('World')
49
+
50
+ await act(() => {
51
+ component.value = 'Planet'
52
+ })
53
+
54
+ expect(getByText('Hello World!')).toBeInTheDocument()
55
+ })
56
+
57
+ test('should accept props directly', () => {
58
+ const { getByText } = stlRender(Comp, { name: 'World' })
59
+ expect(getByText('Hello World!')).toBeInTheDocument()
60
+ })
61
+
62
+ test('should accept svelte component options', () => {
63
+ const target = document.createElement('div')
64
+ const div = document.createElement('div')
65
+ document.body.appendChild(target)
66
+ target.appendChild(div)
67
+ const { container } = stlRender(Comp, {
68
+ target,
69
+ anchor: div,
70
+ props: { name: 'World' },
71
+ context: new Map([['name', 'context']])
72
+ })
73
+ expect(container).toMatchSnapshot()
74
+ })
75
+
76
+ test('should throw error when mixing svelte component options and props', () => {
77
+ expect(() => {
78
+ stlRender(Comp, { anchor: '', name: 'World' })
79
+ }).toThrow(/Unknown options were found/)
80
+ })
81
+
82
+ test('should return a container object, which contains the DOM of the rendered component', () => {
83
+ const { container } = render()
84
+
85
+ expect(container.innerHTML).toBe(document.body.innerHTML)
86
+ })
87
+
88
+ test('correctly find component constructor on the default property', () => {
89
+ const { getByText } = render(CompDefault, { props: { name: 'World' } })
90
+
91
+ expect(getByText('Hello World!')).toBeInTheDocument()
92
+ })
93
+
94
+ test("accept the 'context' option", () => {
95
+ const { getByText } = stlRender(Comp, {
96
+ props: {
97
+ name: 'Universe'
98
+ },
99
+ context: new Map([['name', 'context']])
100
+ })
101
+
102
+ expect(getByText('we have context')).toBeInTheDocument()
103
+ })
104
+ })
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ import { describe, expect, test } from 'vitest'
5
+
6
+ import { render } from '..'
7
+ import Comp from './fixtures/Comp.svelte'
8
+
9
+ describe('rerender', () => {
10
+ test('mounts new component successfully', () => {
11
+ const { container, rerender } = render(Comp, { props: { name: 'World 1' } })
12
+
13
+ expect(container.firstChild).toHaveTextContent('Hello World 1!')
14
+ rerender({ props: { name: 'World 2' } })
15
+ expect(container.firstChild).toHaveTextContent('Hello World 2!')
16
+ })
17
+
18
+ test('destroys old component', () => {
19
+ let isDestroyed
20
+
21
+ const { rerender, component } = render(Comp, { props: { name: '' } })
22
+
23
+ component.$$.on_destroy.push(() => {
24
+ isDestroyed = true
25
+ })
26
+ rerender({ props: { name: '' } })
27
+ expect(isDestroyed).toBeTruthy()
28
+ })
29
+
30
+ test('destroys old components on multiple rerenders', () => {
31
+ const { rerender, queryByText } = render(Comp, { props: { name: 'Neil' } })
32
+
33
+ rerender({ props: { name: 'Alex' } })
34
+ expect(queryByText('Hello Neil!')).not.toBeInTheDocument()
35
+ rerender({ props: { name: 'Geddy' } })
36
+ expect(queryByText('Hello Alex!')).not.toBeInTheDocument()
37
+ })
38
+ })
@@ -0,0 +1,35 @@
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
+ })
package/src/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import { act, cleanup } from './pure'
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 './pure'
package/src/pure.js ADDED
@@ -0,0 +1,138 @@
1
+ import {
2
+ fireEvent as dtlFireEvent,
3
+ getQueriesForElement,
4
+ prettyDOM
5
+ } from '@testing-library/dom'
6
+ import { tick } from 'svelte'
7
+
8
+ const containerCache = new Set()
9
+ const componentCache = new Set()
10
+
11
+ const svelteComponentOptions = [
12
+ 'accessors',
13
+ 'anchor',
14
+ 'props',
15
+ 'hydrate',
16
+ 'intro',
17
+ 'context'
18
+ ]
19
+
20
+ const render = (
21
+ Component,
22
+ { target, ...options } = {},
23
+ { container, queries } = {}
24
+ ) => {
25
+ container = container || document.body
26
+ target = target || container.appendChild(document.createElement('div'))
27
+
28
+ const ComponentConstructor = Component.default || Component
29
+
30
+ const checkProps = (options) => {
31
+ const isProps = !Object.keys(options).some((option) =>
32
+ svelteComponentOptions.includes(option)
33
+ )
34
+
35
+ // Check if any props and Svelte options were accidentally mixed.
36
+ if (!isProps) {
37
+ const unrecognizedOptions = Object.keys(options).filter(
38
+ (option) => !svelteComponentOptions.includes(option)
39
+ )
40
+
41
+ if (unrecognizedOptions.length > 0) {
42
+ throw Error(`
43
+ Unknown options were found [${unrecognizedOptions}]. This might happen if you've mixed
44
+ passing in props with Svelte options into the render function. Valid Svelte options
45
+ are [${svelteComponentOptions}]. You can either change the prop names, or pass in your
46
+ props for that component via the \`props\` option.\n\n
47
+ Eg: const { /** Results **/ } = render(MyComponent, { props: { /** props here **/ } })\n\n
48
+ `)
49
+ }
50
+
51
+ return options
52
+ }
53
+
54
+ return { props: options }
55
+ }
56
+
57
+ let component = new ComponentConstructor({
58
+ target,
59
+ ...checkProps(options)
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
+ })
81
+
82
+ containerCache.add({ container, target, component })
83
+ componentCache.add(component)
84
+
85
+ component.$$.on_destroy.push(() => {
86
+ componentCache.delete(component)
87
+ })
88
+ },
89
+ unmount: () => {
90
+ if (componentCache.has(component)) component.$destroy()
91
+ },
92
+ ...getQueriesForElement(container, queries)
93
+ }
94
+ }
95
+
96
+ const cleanupAtContainer = (cached) => {
97
+ const { target, component } = cached
98
+
99
+ if (componentCache.has(component)) component.$destroy()
100
+
101
+ if (target.parentNode === document.body) {
102
+ document.body.removeChild(target)
103
+ }
104
+
105
+ containerCache.delete(cached)
106
+ }
107
+
108
+ const cleanup = () => {
109
+ Array.from(containerCache.keys()).forEach(cleanupAtContainer)
110
+ }
111
+
112
+ const act = (fn) => {
113
+ const value = fn && fn()
114
+ if (value !== undefined && typeof value.then === 'function') {
115
+ return value.then(() => tick())
116
+ }
117
+ return tick()
118
+ }
119
+
120
+ const fireEvent = async (...args) => {
121
+ const event = dtlFireEvent(...args)
122
+ await tick()
123
+ return event
124
+ }
125
+
126
+ Object.keys(dtlFireEvent).forEach((key) => {
127
+ fireEvent[key] = async (...args) => {
128
+ const event = dtlFireEvent[key](...args)
129
+ await tick()
130
+ return event
131
+ }
132
+ })
133
+
134
+ /* eslint-disable import/export */
135
+
136
+ export * from '@testing-library/dom'
137
+
138
+ export { render, cleanup, fireEvent, act }
@@ -0,0 +1,11 @@
1
+ import * as matchers from '@testing-library/jest-dom/dist/matchers'
2
+ import { afterEach, expect } from 'vitest'
3
+
4
+ import { act, cleanup } from './pure'
5
+
6
+ expect.extend(matchers)
7
+
8
+ afterEach(async () => {
9
+ await act()
10
+ cleanup()
11
+ })
package/types/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Definitions by: Rahim Alwer <https://github.com/mihar-22>
4
4
 
5
5
  import {queries, Queries, BoundFunction, EventType} from '@testing-library/dom'
6
- import { SvelteComponent, ComponentProps } from 'svelte/types/runtime'
6
+ import { SvelteComponent, ComponentProps } from 'svelte'
7
7
 
8
8
  export * from '@testing-library/dom'
9
9
 
package/dist/index.js DELETED
@@ -1,30 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
-
7
- var _pure = require("./pure");
8
-
9
- Object.keys(_pure).forEach(function (key) {
10
- if (key === "default" || key === "__esModule") return;
11
- if (key in exports && exports[key] === _pure[key]) return;
12
- Object.defineProperty(exports, key, {
13
- enumerable: true,
14
- get: function () {
15
- return _pure[key];
16
- }
17
- });
18
- });
19
-
20
- // If we're running in a test runner that supports afterEach
21
- // then we'll automatically run cleanup afterEach test
22
- // this ensures that tests run in isolation from each other
23
- // if you don't like this then either import the `pure` module
24
- // or set the STL_SKIP_AUTO_CLEANUP env variable to 'true'.
25
- if (typeof afterEach === 'function' && !process.env.STL_SKIP_AUTO_CLEANUP) {
26
- afterEach(async () => {
27
- await (0, _pure.act)();
28
- (0, _pure.cleanup)();
29
- });
30
- }
package/dist/pure.js DELETED
@@ -1,170 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- var _exportNames = {
7
- render: true,
8
- cleanup: true,
9
- fireEvent: true,
10
- act: true
11
- };
12
- exports.render = exports.fireEvent = exports.cleanup = exports.act = void 0;
13
-
14
- var _dom = require("@testing-library/dom");
15
-
16
- Object.keys(_dom).forEach(function (key) {
17
- if (key === "default" || key === "__esModule") return;
18
- if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
19
- if (key in exports && exports[key] === _dom[key]) return;
20
- Object.defineProperty(exports, key, {
21
- enumerable: true,
22
- get: function () {
23
- return _dom[key];
24
- }
25
- });
26
- });
27
-
28
- var _svelte = require("svelte");
29
-
30
- const _excluded = ["target"];
31
-
32
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
33
-
34
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
35
-
36
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
37
-
38
- function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
39
-
40
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
41
-
42
- const containerCache = new Set();
43
- const componentCache = new Set();
44
- const svelteComponentOptions = ['accessors', 'anchor', 'props', 'hydrate', 'intro', 'context'];
45
-
46
- const render = (Component, _ref = {}, {
47
- container,
48
- queries
49
- } = {}) => {
50
- let {
51
- target
52
- } = _ref,
53
- options = _objectWithoutProperties(_ref, _excluded);
54
-
55
- container = container || document.body;
56
- target = target || container.appendChild(document.createElement('div'));
57
- const ComponentConstructor = Component.default || Component;
58
-
59
- const checkProps = options => {
60
- const isProps = !Object.keys(options).some(option => svelteComponentOptions.includes(option)); // Check if any props and Svelte options were accidentally mixed.
61
-
62
- if (!isProps) {
63
- const unrecognizedOptions = Object.keys(options).filter(option => !svelteComponentOptions.includes(option));
64
-
65
- if (unrecognizedOptions.length > 0) {
66
- throw Error(`
67
- Unknown options were found [${unrecognizedOptions}]. This might happen if you've mixed
68
- passing in props with Svelte options into the render function. Valid Svelte options
69
- are [${svelteComponentOptions}]. You can either change the prop names, or pass in your
70
- props for that component via the \`props\` option.\n\n
71
- Eg: const { /** Results **/ } = render(MyComponent, { props: { /** props here **/ } })\n\n
72
- `);
73
- }
74
-
75
- return options;
76
- }
77
-
78
- return {
79
- props: options
80
- };
81
- };
82
-
83
- let component = new ComponentConstructor(_objectSpread({
84
- target
85
- }, checkProps(options)));
86
- containerCache.add({
87
- container,
88
- target,
89
- component
90
- });
91
- componentCache.add(component);
92
- component.$$.on_destroy.push(() => {
93
- componentCache.delete(component);
94
- });
95
- return _objectSpread({
96
- container,
97
- component,
98
- debug: (el = container) => console.log((0, _dom.prettyDOM)(el)),
99
- rerender: options => {
100
- if (componentCache.has(component)) component.$destroy(); // eslint-disable-next-line no-new
101
-
102
- component = new ComponentConstructor(_objectSpread({
103
- target
104
- }, checkProps(options)));
105
- containerCache.add({
106
- container,
107
- target,
108
- component
109
- });
110
- componentCache.add(component);
111
- component.$$.on_destroy.push(() => {
112
- componentCache.delete(component);
113
- });
114
- },
115
- unmount: () => {
116
- if (componentCache.has(component)) component.$destroy();
117
- }
118
- }, (0, _dom.getQueriesForElement)(container, queries));
119
- };
120
-
121
- exports.render = render;
122
-
123
- const cleanupAtContainer = cached => {
124
- const {
125
- target,
126
- component
127
- } = cached;
128
- if (componentCache.has(component)) component.$destroy();
129
-
130
- if (target.parentNode === document.body) {
131
- document.body.removeChild(target);
132
- }
133
-
134
- containerCache.delete(cached);
135
- };
136
-
137
- const cleanup = () => {
138
- Array.from(containerCache.keys()).forEach(cleanupAtContainer);
139
- };
140
-
141
- exports.cleanup = cleanup;
142
-
143
- const act = fn => {
144
- const value = fn && fn();
145
-
146
- if (value !== undefined && typeof value.then === 'function') {
147
- return value.then(() => (0, _svelte.tick)());
148
- }
149
-
150
- return (0, _svelte.tick)();
151
- };
152
-
153
- exports.act = act;
154
-
155
- const fireEvent = async (...args) => {
156
- const event = (0, _dom.fireEvent)(...args);
157
- await (0, _svelte.tick)();
158
- return event;
159
- };
160
-
161
- exports.fireEvent = fireEvent;
162
- Object.keys(_dom.fireEvent).forEach(key => {
163
- fireEvent[key] = async (...args) => {
164
- const event = _dom.fireEvent[key](...args);
165
-
166
- await (0, _svelte.tick)();
167
- return event;
168
- };
169
- });
170
- /* eslint-disable import/export */
package/pure.js DELETED
@@ -1,2 +0,0 @@
1
- // Makes it so people can import from '@testing-library/svelte/pure'
2
- module.exports = require('./dist/pure')