npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svelte-declarative-testing

v0.3.3

Published

A way to mount your Svelte test components declaratively

Readme

svelte-declarative-testing

One of the great things about Svelte is its compiler, producing a minimal runtime and providing a great, declarative way to build components. Unfortunately, unlike many other JavaScript frameworks, which use jsx or tagged template functions to render components in a declarative manner inside JavaScript files, Svelte has no such feature. Consider the following structure of composed components:

<Popover>
  <PopoverTrigger>Open Menu</PopoverTrigger>
  <PopoverMenu>
    <PopoverMenuItem href="/account">Account</PopoverMenuItem>
    <PopoverMenuItem href="/logout">Log out</PopoverMenuItem>
  </PopoverMenu>
</Popover>

There are existing ways to render this in your tests, but none of them are ergonomic. You can:

  • create a separate .svelte file for each configuration of your composed components you want to test and pass that component to render(); or
  • create a single .svelte file and wrap all of your configurations in {#snippet <name>()}...{/snippet}, along with a {@render children()}. You export all the snippets and import them along with the default export, pass the default export to render(...) and the snippet to the children property; or
  • Use something like vite-plugin-svelte-inline-component which allows you to use tagged template literals along with some directive comments in your test files.

Using this library, you can write your tests in Svelte syntax. This gives you much greater ergonomics and flexibility, especially for the above composition. Your tests can look like this:

<!-- Popover.test.svelte -->
<script>
  import { Test, Check } from 'svelte-declarative-testing/vitest-browser-svelte';
  import { Popover, PopoverTrigger, PopoverMenu, PopoverMenuItem } from './';
</script>

<Test it="opens the menu when the trigger is clicked">
  <!-- Anything passed via the mount() snippet is rendered for each test -->
  {#snippet mount()}
    <Popover>
      <PopoverTrigger>Open Menu</PopoverTrigger>
      <PopoverMenu>
        <PopoverMenuItem href="/account">Account</PopoverMenuItem>
        <PopoverMenuItem href="/logout">Log out</PopoverMenuItem>
      </PopoverMenu>
    </Popover>
  {/snippet}

  <!-- one or more test functions can be provided as checks -->
  <Check
    fn={async (screen) => {
      expect(screen.getByRole('menu', { includeHidden: true })).not.toBeVisible();
      await screen.getByRole('button', { name: 'Open Menu' }).click();
      expect(screen.getByRole('menu')).toBeVisible();
    }}
  />
</Test>

Installation

Install as part of your project's devDependencies through your preferred package manager.

npm install --save-dev svelte-declarative-testing

Setup

There are 2 ways to activate your declarative svelte test files, using the provided Vite plugins or by importing them directly into another test file to mount them.

Using the plugins

In order to work with the VSCode Vitest extension, 2 plugins are provided to instrument the source code. You will also need to make sure Vitest includes your test files:

import svelteDeclarativeTesting from 'svelte-declarative-testing/vitest';

export default defineConfig({
  plugins: [
    // ...

    ...svelteDeclarativeTesting(),
  ],

  // ...

  test: {
    include: [
      'src/**/*.svelte.{test,spec}.{js,ts}',

      // Includes .test.svelte and .spec.svelte
      'src/**/*.{test,spec}.svelte',
    ],
  },
});

Importing directly into your other tests

[!WARNING] This approach will not allow you to trigger test runs using the Vitest extension for VSCode. There may be some other side effects also.

If you don't want to use the plugins, simply import your Svelte-syntax test files into your existing unit tests:

// Popover.test.js
import PopoverIntegrationTests from './Popover.test.svelte';
import { render } from '@testing-library/svelte'; // or vitest-browser-svelte

describe('Unit tests', () => {
  // ... existing unit tests
});

describe('Integration tests', () => {
  render(PopoverIntegrationTests);
});

Writing tests

Writing tests is quite intuitive. It is a similar structure to JavaScript test files, with describe() and test() being replaced by <Describe ...> and <Test ...> respectively. Additionally, there is a <Check> function that allows you to provide the test functions.

Convenience wrappers are provided for @testing-library/svelte and vitest-browser-svelte.

import { Describe, Test, Check } from 'svelte-declarative-testing/testing-library';
import { Describe, Test, Check } from 'svelte-declarative-testing/vitest-browser-svelte';

Alternatively, you can import the core functions and provide a custom render() function to the Test component.

import { Describe, Test, Check } from 'svelte-declarative-testing';

<Describe ...>

Wraps your tests in a suite, similare to describe().

<Describe label="My Integration Tests">

Inside Describe, tests go in a tests() snippet. Any other children will be rendered for each test.

| Properties | Type | Description | | ---------- | ---------- | ------------------------------------------------------------------------------------- | | label | string | The descriptive label for the test suite | | mount | Snippet | Any component(s) that you wish to render for the tests | | children | Snippet | A snippet block containing one or more <Test> elements | | skip | any | Skips the suite if truthy, just like describe.skip() | | only | any | Only run this suite if truthy, just like describe.only() | | todo | any | Mark the suite as todo if truthy, just like describe.todo() | | shuffle | any | Mark the suite as todo if truthy, just like describe.todo() | | skipIf | function | Skips the suite if the function returns a truthy value, just like describe.skipIf() | | runIf | function | Runs the suite if the function returns a truthy value, just like describe.runIf() |

<Describe label="My Integration Tests">
  {#snippet mount()}
    <Button>My button</Button>
  {/snippet}

  <Test it="renders an accessible button">
    <!-- Test body goes here -->
  </Test>

  <Test it="does something when I click the button">
    <!-- Test body goes here -->
  </Test>
</Describe>

<Test ...>

Describes a test.

<Test it="does what I expect it to do">

Inside Test, checks go in a checks() snippet. Any other children will be rendered for each test. If no other children are provided, the children of the parent <Describe> are rendered.

| Properties | Type | Description | | ---------- | ---------- | -------------------------------------------------------------------------------- | | it | string | The description of the test | | mount | Snippet | Any component(s) that you wish to render for the test | | children | Snippet | A snippet block containing one or more <Check> elements | | skip | any | Skips the test if truthy, just like test.skip() | | only | any | Only run this test if truthy, just like test.only() | | todo | any | Mark the test as todo if truthy, just like test.todo() | | fails | any | Passes the test on failure if truthy, just like test.fails() | | skipIf | function | Skips the test if the function returns a truthy value, just like test.skipIf() | | runIf | function | Runs the test if the function returns a truthy value, just like test.runIf() | | render() | function | Provides a custom render function (not available on the wrapper components` |

<Test it="renders an accessible button">
  <Button>My button</Button>

  {#snippet checks()}
    <Check fn={ /* ... */ } />
    <Check fn={ /* ... */ } />
  {/snippet}
</Describe>

<Check ...>

Provides a test function.

<Check fn={() => expect(1 + 1).toBe(2)} />

You can provide as many checks as you like and they will run sequentially.

| Properties | Type | Description | | ---------- | ---------- | -------------------------------------------------- | | fn | function | A function to be executed as part of the test body |

<Test it="renders an accessible button">
  <Button>My button</Button>

  {#snippet checks()}
    <Check fn={({queryByRole}) => {
      expect(queryByRole("button")).toBeIntheDocument();
    }}/>
  {/snippet}
</Describe>

Credits

This is not a new idea and was originally posited by @7nik and @paoloricciuti on the Svelte bug tracker. Thanks also to @sheremet-va, who assisted with the Vitest test detection plugins.