@magic/test
Svelte Testing
@magic/test includes built-in support for testing Svelte 5 components. It compiles Svelte components, mounts them in a DOM environment, and provides utilities for interacting with and asserting on component behavior.
Internally uses js-dom to create the DOM and HTML elements.
mount
import { mount, html, tryCatch } from '@magic/test'const component = './path/to/MyComponent.svelte'export default [{component,props: { message: 'Hello' },fn: ({ target }) => html(target).includes('Hello'),expect: true,info: 'renders the message prop',},]
Exported Functions
- mount(filePath, options) - Mounts a Svelte component and returns { target, component, unmount }
- html(target) - Returns innerHTML of a mounted component's target element
- text(target) - Returns textContent of a target element
- component(instance) - Returns the component instance for accessing exported values
- props(target) - Returns an object of attribute name/value pairs from the target element
Interaction Functions
- click(target, selector?) - Clicks an element (optionally filtered by CSS selector)
- dblClick(target) - Double clicks
- contextMenu(target) - Right click
- mouseDown(target) - Mouse down
- mouseUp(target) - Mouse up
- mouseMove(target) - Mouse move
- mouseEnter(target) - Mouse enter
- mouseLeave(target) - Mouse leave
- mouseOver(target) - Mouse over
- mouseOut(target) - Mouse out
- keyDown(target, key) - Key down
- keyPress(target, key) - Key press
- keyUp(target, key) - Key up
- type(target, text) - Type text into input
- input(target, value) - Input value
- change(target, value) - Change event
- blur(target) - Blur event
- focus(target) - Focus event
- submit(target) - Submit form
- pointerDown(target) - Pointer down
- pointerUp(target) - Pointer up
- pointerMove(target) - Pointer move
- touchStart(target) - Touch start
- touchMove(target) - Touch move
- touchEnd(target) - Touch end
- copy(target) - Copy event
- cut(target) - Cut event
- paste(target) - Paste event
- dragStart(target) - Drag start
- drag(target) - Drag
- dragEnd(target) - Drag end
- dragEnter(target) - Drag enter
- dragLeave(target) - Drag leave
- dragOver(target) - Drag over
- drop(target) - Drop
- resize(target, w, h) - Resize
- scroll(target, x, y) - Scroll
- animationStart(target) - Animation start
- animationEnd(target) - Animation end
- transitionEnd(target) - Transition end
- play(target) - Play media
- pause(target) - Pause media
- trigger(target, eventType, options?) - Custom event
- checked(target) - Checkbox state
Test Properties
- component - Path to the .svelte file
- props - Props to pass to the component
- fn - Test function receiving { target, component, unmount }
Accessing Component State
import { mount, html } from '@magic/test'const component = './src/lib/svelte/components/Counter.svelte'export default [{component,fn: async ({ target, component: instance }) => {return instance.count},expect: 0,info: 'initial count is 0',},]
Automatic Test Exports
When testing Svelte 5 components, @magic/test automatically exports $state and $derived variables, making them accessible in tests without requiring manual exports.
**Note:** This automatic export feature is specific to **Svelte 5** only. Svelte 4 components do not have this capability.
<!-- Component.svelte --><script>let count = $state(0)let doubled = $derived(count * 2)<!-- No export needed! --></script><button class="inc">+</button><span>{doubled}</span>
Test - works automatically!
import { mount } from '@magic/test'export default [{component: './Component.svelte',fn: async ({ component }) => component.count, // 0expect: 0,info: 'access $state without manual export',},{component: './Component.svelte',fn: async ({ component }) => component.doubled, // 0 (derived)expect: 0,info: 'access $derived without manual export',},]
This works automatically for all $state and $derived runes. No configuration needed!
Testing Error Handling
import { mount, tryCatch } from '@magic/test'const component = './src/lib/svelte/components/MyComponent.svelte'export default [{fn: tryCatch(mount, component, { props: null }),expect: t => t.message === 'Props must be an object, got object',info: 'throws when props is null',},]
SvelteKit Mocks
Mocks SvelteKit $app modules:
import { browser, dev, prod, createStaticPage } from '@magic/test'export default [{fn: () => browser, // true if in browser environmentexpect: false,info: 'not in browser by default',},{fn: () => dev, // true if in dev modeexpect: process.env.NODE_ENV === 'development',info: 'dev reflects NODE_ENV',},{fn: () => prod, // true if in production modeexpect: false,info: 'not in prod by default',},]
createStaticPage
Creates a static page mock for SvelteKit testing:
import { createStaticPage } from '@magic/test'export default [{fn: createStaticPage,expect: t => typeof t.html === 'string' && typeof t.render === 'function',info: 'createStaticPage returns html string and render function',},]
compileSvelte
Compile Svelte component source to a module for testing:
import { compileSvelte } from '@magic/test'export default [{fn: async () => {const source = `<button>Click</button>`const { js, css } = compileSvelte(source, 'button.svelte')return js.code.includes('button') && css.code === ''},expect: true,info: 'compiles Svelte source to module',},]
Available functions:
- compileSvelte(source, filename) - Compiles Svelte source to JS/CSS modules
- ensureSvelte() - Lazy-loads the Svelte package, throws if not installed
ensureSvelte
Lazy-loads the Svelte package. Throws if Svelte is not installed:
import { ensureSvelte } from '@magic/test'export default [{fn: async () => {const svelte = await ensureSvelte()return svelte.version.startsWith('5')},expect: true,info: 'loads svelte package',},]