Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Testing pages with layout dependencies. #426

Answered by mcous
niemyjski asked this question in Q&A
Discussion options

Is there a best practice or a good way to test code that has setup in a parent layout. For example, I used svelte kit latest sample and then tested a page that was using svelte query provider defined in the parent layout.

import { render, screen } from '@testing-library/svelte';
import '@testing-library/jest-dom/vitest';
import { describe, expect, test } from 'vitest';
import Page from './+page.svelte';
describe('/+page.svelte', () => {
 test('should render h1', () => {
 render(Page);
 expect(screen.getByRole('heading', { level: 1 })).toBeInTheDocument();
 });
});

This fails with:

 FAIL client src/routes/status/page.svelte.test.ts > /+page.svelte > should render h1
Error: No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?
 ❯ getQueryClientContext node_modules/@tanstack/svelte-query/dist/context.js:7:15
 5| const client = getContext(_contextKey);
 6| if (!client) {
 7| throw new Error('No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?');
 | ^
 8| }

I'm also noticing other things like dynamic env's are causing issues too.

You must be logged in to vote

@niemyjski this is a very good question! Thanks for taking the time to post it.

I lead a team maintaining a large SvelteKit app that uses svelte-query for its client-side API state management. This is a recommendation from me personally rather than anything "official," but I've found the best1 strategy for component tests is pretty classic Uncle Bob: separate the stuff you want to test away from the framework glue. In practice, this means:

  • No component-level tests for +page.svelte/+layout.svelte
  • No component-level tests for anything that wires into createQuery, createMutation, etc.
  • No/few component-level tests for components that subscribe to context
    • Sometimes, especially if its a conte...

Replies: 1 comment 1 reply

Comment options

@niemyjski this is a very good question! Thanks for taking the time to post it.

I lead a team maintaining a large SvelteKit app that uses svelte-query for its client-side API state management. This is a recommendation from me personally rather than anything "official," but I've found the best1 strategy for component tests is pretty classic Uncle Bob: separate the stuff you want to test away from the framework glue. In practice, this means:

  • No component-level tests for +page.svelte/+layout.svelte
  • No component-level tests for anything that wires into createQuery, createMutation, etc.
  • No/few component-level tests for components that subscribe to context
  • Structure these "framework" components so they delegate all interesting work to props-driven components and/or pure functions, and write tests for those units instead of the glue
  • Include small Playwright E2E suites to validate proper wire-up of your framework glue
    • TypeScript and static analysis are also a great, if incomplete, tools to validate framework wire-up

For a simple, if slightly contrived example, if I wanted to test a user dashboard page's heading, I might write something like:

<!-- dashboard/+page.svelte -->
<script>
import { createUserQuery } from '$lib/api'
import DashboardHeading from './dashboard-heading.svelte'

const userQuery = createUserQuery()
</script>
<DashboardHeading user={$userQuery.data} />
<!-- dashboard/dashboard-heading.svelte -->
<script>
import type { User } from '$lib/api';

const { user }: { user: User | undefined } = $props();
</script>
<h1>Hello {user?.name ?? 'friend'}!</h1>
// dashboard-heading.spec.ts
// ...
it('renders level 1 heading with user name', () => {
 render(DashboardHeading, { user: { name: 'Alice' } })
 const heading = screen.getByRole('heading', { level: 1, name: /helloalice/iu })
 expect(heading).toBeInTheDocument()
})

From there, I would also make sure that I had an E2E test for this page that also checked that there was a level-1 heading on the page matching.

I've seen a number of guides online that recommend mocking out SvelteKit imports in your tests, but I definitely recommend your try to minimize or eliminate mocking in component tests. I'm a huge fan of mocking, but I've gone down the mock-heavy-component-tests path with React and RTL, and all it got me was a very brittle test suite that slowed my team down. Instead, I prefer to acknowledge that component tests are, by nature, highly integrated with code outside my control, and then do my best to minimize how many layers get tested in a given component test.

Footnotes

  1. "Best" meaning "high test coverage of interesting, product-specific logic while prioritizing development speed."

You must be logged in to vote
1 reply
Comment options

I agree with all of this and it was kind of what I was thinking. I just brought over what sveltekit is doing right out of the box with a new project and it's testing +page. I noticed that errored quickly and there really wasn't any diffinitive pointers (your reply should be in the readme).

Thanks again!

Answer selected by niemyjski
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants
Converted from issue

This discussion was converted from issue #425 on February 26, 2025 22:29.

AltStyle によって変換されたページ (->オリジナル) /