Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Testing pages with layout dependencies. #425

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
niemyjski opened this issue Feb 22, 2025 · 1 comment
Closed

Testing pages with layout dependencies. #425

niemyjski opened this issue Feb 22, 2025 · 1 comment

Comments

@niemyjski
Copy link

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.

@mcous
Copy link
Collaborator

mcous commented Feb 22, 2025

@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: /hello alice/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."

@testing-library testing-library locked and limited conversation to collaborators Feb 26, 2025
@mcous mcous converted this issue into discussion #426 Feb 26, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants