install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/test-component-svelte" ~/.claude/skills/intense-visions-harness-engineering-test-component-svelte && rm -rf "$T"
manifest:
agents/skills/claude-code/test-component-svelte/SKILL.mdsource content
Test Component Svelte
Test Svelte components with Testing Library using render, fireEvent, and waitFor
When to Use
- Testing Svelte component rendering and user interactions
- Verifying reactive state updates in response to events
- Testing components that use Svelte stores or slots
- Writing accessible, user-centric component tests
Instructions
- Setup — install dependencies:
npm install -D @testing-library/svelte @testing-library/jest-dom vitest jsdom
Configure Vitest for browser environment:
// vitest.config.ts import { defineConfig } from 'vitest/config'; import { svelte } from '@sveltejs/vite-plugin-svelte'; export default defineConfig({ plugins: [svelte({ hot: false })], test: { environment: 'jsdom' }, });
- Render and query:
import { render, screen } from '@testing-library/svelte'; import Greeting from './Greeting.svelte'; it('displays the name', () => { render(Greeting, { props: { name: 'Alice' } }); expect(screen.getByText('Hello, Alice!')).toBeInTheDocument(); });
- Simulate user interactions:
import { render, screen, fireEvent } from '@testing-library/svelte'; import Counter from './Counter.svelte'; it('increments count on button click', async () => { render(Counter); const button = screen.getByRole('button', { name: 'Increment' }); expect(screen.getByText('Count: 0')).toBeInTheDocument(); await fireEvent.click(button); expect(screen.getByText('Count: 1')).toBeInTheDocument(); });
- Test form inputs:
import { render, screen, fireEvent } from '@testing-library/svelte'; import SearchBox from './SearchBox.svelte'; it('updates search results on input', async () => { render(SearchBox); const input = screen.getByPlaceholderText('Search...'); await fireEvent.input(input, { target: { value: 'hello' } }); expect(await screen.findByText('Results for: hello')).toBeInTheDocument(); });
- Test with props updates:
import { render, screen } from '@testing-library/svelte'; import UserCard from './UserCard.svelte'; it('updates when props change', async () => { const { rerender } = render(UserCard, { props: { name: 'Alice' } }); expect(screen.getByText('Alice')).toBeInTheDocument(); await rerender({ name: 'Bob' }); expect(screen.getByText('Bob')).toBeInTheDocument(); });
- Test component events:
import { render, screen, fireEvent } from '@testing-library/svelte'; import Button from './Button.svelte'; it('dispatches click event with payload', async () => { const { component } = render(Button); const handler = vi.fn(); component.$on('customClick', handler); await fireEvent.click(screen.getByRole('button')); expect(handler).toHaveBeenCalledWith(expect.objectContaining({ detail: { action: 'confirm' } })); });
- Test async/loading states:
it('shows loading then data', async () => { render(UserList); expect(screen.getByText('Loading...')).toBeInTheDocument(); expect(await screen.findByText('Alice')).toBeInTheDocument(); expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); });
- Test with Svelte stores:
import { writable } from 'svelte/store'; it('reacts to store changes', async () => { const user = writable({ name: 'Alice' }); render(UserDisplay, { props: { user } }); expect(screen.getByText('Alice')).toBeInTheDocument(); user.set({ name: 'Bob' }); await screen.findByText('Bob'); });
Details
@testing-library/svelte follows the same user-centric testing philosophy as the React variant. Tests interact with rendered DOM elements, not component internals.
Svelte-specific considerations:
- Svelte components are compiled — the test setup needs the Svelte Vite plugin to process
files.svelte - Reactivity is batched — after
, changes may not be reflected immediately. UsefireEvent
orawait
fromtick()
to wait for updatessvelte - Component events use
— different from React's prop-based callbacks$on('eventName', handler) - Slot testing requires wrapper components that render slots with test content
Query priority (same as React Testing Library):
— accessible role and namegetByRole
— form labelsgetByLabelText
— visible textgetByText
— last resortgetByTestId
Svelte 5 runes: If using Svelte 5 with runes (
$state, $derived), the testing patterns remain the same at the component level — Testing Library interacts with the DOM, which is the output of runes.
Trade-offs:
- Testing Library for Svelte has a smaller ecosystem than React Testing Library
in Svelte requiresfireEvent
for reactivity updates, which is easy to forgetawait- Component event testing with
is less ergonomic than React's callback props$on - Svelte's compilation step means test startup is slightly slower than plain JavaScript tests
Source
https://testing-library.com/docs/svelte-testing-library/intro/
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.