If you use createContext, wrap your component in a wrapper function to create the context.
Note
Setting a context value in a wrapper function requires svelte>=5.50.0.
import { createContext } from 'svelte'
export interface Message {
id: string
text: string
}
export interface MessagesContext {
current: Message[]
}
export const [getMessagesContext, setMessagesContext] =
createContext<MessagesContext>()<script lang="ts">
import { getMessagesContext } from './typesafe-context.js'
let { label } = $props()
const messages = getMessagesContext()
</script>
<div role="status" aria-label={label}>
{#each messages.current as message (message.id)}
<p>{message.text}</p>
<hr />
{/each}
</div>import { render, screen } from '@testing-library/svelte'
import { expect, test } from 'vitest'
import { type MessagesContext, setMessagesContext } from './typesafe-context.js'
import Subject from './typesafe-context.svelte'
test('notifications with messages from context', () => {
const messages: MessagesContext = {
get current() {
return [
{ id: 'abc', text: 'hello' },
{ id: 'def', text: 'world' },
]
},
}
const Wrapper: typeof Subject = (...args) => {
setMessagesContext(messages)
return Subject(...args)
}
render(Wrapper, { label: 'Notifications' })
const status = screen.getByRole('status', { name: 'Notifications' })
expect(status).toHaveTextContent('hello world')
})If you use setContext and getContext, you can use the context option
of render to pass a context in. When using extra component options like
context, be sure to place props under the props key.
<script>
import { getContext } from 'svelte'
let { label } = $props()
const messages = getContext('messages')
</script>
<div role="status" aria-label={label}>
{#each messages.current as message (message.id)}
<p>{message.text}</p>
<hr />
{/each}
</div>import { render, screen } from '@testing-library/svelte'
import { expect, test } from 'vitest'
import Subject from './context.svelte'
test('notifications with messages from context', () => {
const messages = {
get current() {
return [
{ id: 'abc', text: 'hello' },
{ id: 'def', text: 'world' },
]
},
}
render(Subject, {
context: new Map([['messages', messages]]),
props: { label: 'Notifications' },
})
const status = screen.getByRole('status', { name: 'Notifications' })
expect(status).toHaveTextContent('hello world')
})