diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 778d507..326785a 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -25,6 +25,7 @@ module.exports = {
},
rules: {
'no-undef-init': 'off',
+ 'prefer-const': 'off',
},
},
{
@@ -49,5 +50,6 @@ module.exports = {
ecmaVersion: 2022,
sourceType: 'module',
},
+ globals: { $state: 'readonly', $props: 'readonly' },
ignorePatterns: ['!/.*'],
}
diff --git a/src/__tests__/fixtures/Comp.svelte b/src/__tests__/fixtures/Comp.svelte
index ba23d88..18365a4 100644
--- a/src/__tests__/fixtures/Comp.svelte
+++ b/src/__tests__/fixtures/Comp.svelte
@@ -13,5 +13,3 @@
Hello {name}!
-
-
diff --git a/src/__tests__/fixtures/CompRunes.svelte b/src/__tests__/fixtures/CompRunes.svelte
new file mode 100644
index 0000000..77646e3
--- /dev/null
+++ b/src/__tests__/fixtures/CompRunes.svelte
@@ -0,0 +1,13 @@
+
+
+Hello {name}!
+
+
diff --git a/src/__tests__/render.test.js b/src/__tests__/render.test.js
index ea445d5..92fda6d 100644
--- a/src/__tests__/render.test.js
+++ b/src/__tests__/render.test.js
@@ -1,11 +1,15 @@
import { render } from '@testing-library/svelte'
-import { describe, expect, test } from 'vitest'
+import { beforeAll, describe, expect, test } from 'vitest'
-import Comp from './fixtures/Comp.svelte'
-import { IS_SVELTE_5 } from './utils.js'
+import { COMPONENT_FIXTURES, IS_SVELTE_5 } from './utils.js'
-describe('render', () => {
+describe.each(COMPONENT_FIXTURES)('render $name', ({ component }) => {
const props = { name: 'World' }
+ let Comp
+
+ beforeAll(async () => {
+ Comp = await import(component)
+ })
test('renders component into the document', () => {
const { getByText } = render(Comp, { props })
diff --git a/src/__tests__/rerender.test.js b/src/__tests__/rerender.test.js
index ca4b8e8..0cc0941 100644
--- a/src/__tests__/rerender.test.js
+++ b/src/__tests__/rerender.test.js
@@ -1,10 +1,15 @@
import { act, render, screen } from '@testing-library/svelte'
-import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
-import { describe, expect, test, vi } from 'vitest'
+import { beforeAll, describe, expect, test, vi } from 'vitest'
-import Comp from './fixtures/Comp.svelte'
+import { COMPONENT_FIXTURES, IS_SVELTE_5, TYPE_RUNES } from './utils.js'
+
+describe.each(COMPONENT_FIXTURES)('rerender $type', ({ type, component }) => {
+ let Comp
+
+ beforeAll(async () => {
+ Comp = await import(component)
+ })
-describe('rerender', () => {
test('updates props', async () => {
const { rerender } = render(Comp, { name: 'World' })
const element = screen.getByText('Hello World!')
@@ -29,13 +34,12 @@ describe('rerender', () => {
)
})
- test('change props with accessors', async () => {
- const { component, getByText } = render(
- Comp,
- SVELTE_VERSION < '5'
- ? { accessors: true, props: { name: 'World' } }
- : { name: 'World' }
- )
+ test.skipIf(type === TYPE_RUNES)('change props with accessors', async () => {
+ const componentOptions = IS_SVELTE_5
+ ? { name: 'World' }
+ : { accessors: true, props: { name: 'World' } }
+
+ const { component, getByText } = render(Comp, componentOptions)
const element = getByText('Hello World!')
expect(element).toBeInTheDocument()
diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js
index 69be184..4fcefe0 100644
--- a/src/__tests__/utils.js
+++ b/src/__tests__/utils.js
@@ -5,3 +5,14 @@ export const IS_JSDOM = window.navigator.userAgent.includes('jsdom')
export const IS_HAPPYDOM = !IS_JSDOM // right now it's happy or js
export const IS_SVELTE_5 = SVELTE_VERSION >= '5'
+
+export const TYPE_LEGACY = 'legacy'
+
+export const TYPE_RUNES = 'runes'
+
+export const COMPONENT_FIXTURES = [
+ { type: TYPE_LEGACY, component: './fixtures/Comp.svelte' },
+ IS_SVELTE_5
+ ? { type: TYPE_RUNES, component: './fixtures/CompRunes.svelte' }
+ : [],
+].flat()
diff --git a/src/pure.js b/src/pure.js
index 364c225..d144cd5 100644
--- a/src/pure.js
+++ b/src/pure.js
@@ -80,7 +80,8 @@ export class SvelteTestingLibrary {
)
props = props.props
}
- component.$set(props)
+
+ this.rerenderComponent(component, props)
await Svelte.tick()
},
unmount: () => {
@@ -107,6 +108,10 @@ export class SvelteTestingLibrary {
return component
}
+ rerenderComponent(component, nextProps) {
+ component.$set(nextProps)
+ }
+
cleanupComponent(component) {
const inCache = this.componentCache.delete(component)
diff --git a/src/svelte5-index.js b/src/svelte5-index.js
index ab49641..96d9086 100644
--- a/src/svelte5-index.js
+++ b/src/svelte5-index.js
@@ -1,6 +1,6 @@
/* eslint-disable import/export */
import { act } from './pure.js'
-import { cleanup } from './svelte5.js'
+import { cleanup } from './svelte5.svelte.js'
// If we're running in a test runner that supports afterEach
// then we'll automatically run cleanup afterEach test
@@ -20,4 +20,4 @@ export * from '@testing-library/dom'
// export svelte-specific functions and custom `fireEvent`
// `fireEvent` must be a named export to take priority over wildcard export above
export { act, fireEvent } from './pure.js'
-export { cleanup, render } from './svelte5.js'
+export { cleanup, render } from './svelte5.svelte.js'
diff --git a/src/svelte5.js b/src/svelte5.js
deleted file mode 100644
index a8dd494..0000000
--- a/src/svelte5.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { createClassComponent } from 'svelte/legacy'
-
-import { SvelteTestingLibrary } from './pure.js'
-
-class Svelte5TestingLibrary extends SvelteTestingLibrary {
- svelteComponentOptions = [
- 'target',
- 'props',
- 'events',
- 'context',
- 'intro',
- 'recover',
- ]
-
- renderComponent(ComponentConstructor, componentOptions) {
- const component = createClassComponent({
- ...componentOptions,
- component: ComponentConstructor,
- })
-
- this.componentCache.add(component)
-
- return component
- }
-}
-
-const instance = new Svelte5TestingLibrary()
-
-export const render = instance.render.bind(instance)
-export const cleanup = instance.cleanup.bind(instance)
diff --git a/src/svelte5.svelte.js b/src/svelte5.svelte.js
new file mode 100644
index 0000000..b1bb2fc
--- /dev/null
+++ b/src/svelte5.svelte.js
@@ -0,0 +1,49 @@
+/** eslint-global: $state */
+import { mount, unmount } from 'svelte'
+
+import { SvelteTestingLibrary } from './pure.js'
+
+class Svelte5TestingLibrary extends SvelteTestingLibrary {
+ svelteComponentOptions = [
+ 'target',
+ 'props',
+ 'events',
+ 'context',
+ 'intro',
+ 'recover',
+ ]
+
+ propsByComponent = new Map()
+
+ renderComponent(ComponentConstructor, componentOptions) {
+ const props = $state(componentOptions.props ?? {})
+ const component = mount(ComponentConstructor, {
+ ...componentOptions,
+ props,
+ })
+
+ this.componentCache.add(component)
+ this.propsByComponent.set(component, props)
+
+ return component
+ }
+
+ rerenderComponent(component, nextProps) {
+ const prevProps = this.propsByComponent.get(component)
+ Object.assign(prevProps, nextProps)
+ }
+
+ cleanupComponent(component) {
+ const inCache = this.componentCache.delete(component)
+ this.propsByComponent.delete(component)
+
+ if (inCache) {
+ unmount(component)
+ }
+ }
+}
+
+const instance = new Svelte5TestingLibrary()
+
+export const render = instance.render.bind(instance)
+export const cleanup = instance.cleanup.bind(instance)