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 🙏

© 2024 – Pkg Stats / Ryan Hefner

svelte-component-double

v2.1.0

Published

A test double for Svelte 3 components

Downloads

1,628

Readme

svelte-component-double

An test double for Svelte components. It works with Vitest, Jest and Jasmine.

Installation

First install the package:

npm install --save-dev svelte-component-double

Vitest setup & usage

Create a file in your Vite project, named test/registerSvelteComponentDouble.js, with the followig content:

import { expect } from 'vitest';
import * as matchers from 'svelte-component-double/vitest';

expect.extend(matchers);

import { componentDouble } from 'svelte-component-double';

globalThis.componentDouble = componentDouble;

Then update your vi.config.js file to include this as a setup file for Vitest:

const config = {
  ...,
  test: {
    ...,
    setupFiles: [
      ...,
      './test/registerSvelteComponentDouble.js'
    ]
  }
}

Then you can begin to write mocked tests like this:

import {
	describe,
	it,
	expect,
	beforeEach,
	vi
} from 'vitest';
import {
	render,
	screen
} from '@testing-library/svelte';
import Child from './Child.svelte';
import Parent from './Parent.svelte';

vi.mock('./Child.svelte', async () => ({
	default: componentDouble('Child')
}));

describe('Parent component', () => {
	beforeEach(Child.reset);

  it('renders a Child with the right props', () => {
		render(Parent);

    expect(Child).toBeRenderedWithProps({
      foo: "bar"
    });
  });
});

Since mocks are active for the entire module, you may wish to place mocked tests in a separate test file e.g. parent.mocks.test.js, keeping parent.test.js free for non-mocked tests.

Jasmine setup & usage

Add the following helper in spec/support/jasmine.json.

"helpers": [
  "../node_modules/svelte-component-double/lib/matchers/jasmine.js"
]

You'll need to use a mocking tool like babel-plugin-rewire-exports.

In the example below, Parent is the component under test, and Child is being spied on.

import Child, { rewire as rewire$Child, restore } from '../src/Child.svelte';
import Parent from '../src/Parent.svelte';

import { componentDouble } from 'svelte-component-double';

describe('Parent component', () => {
  it('renders a Child', () => {
    // ensure JSDOM is set up and ready to go

    rewire$Child(componentDouble(Child));

    const el = document.createElement('div');
    new Parent({ target: el });

    expect(Child).toHaveBeenCalled();
    expect(el.querySelector(spySelector(Child))).not.toBeNull();
  });
});

Matchers

The expect(component) function has the following matchers available.

| Matcher | Description | | -------- | ----------- | | toBeRendered() | Passes if there was at least one instance of the component instantiated in the current document. | | toBeRenderedIn(container) | Same but with a specific DOM container instead of | document.body. | | toBeRenderedWithProps(props) | Passes if there was at least one instance of the component instantiated with these exact props. | | toBeRenderedWithPropsIn(props, container) | Same as above but with a specic DOM container instead of document.body. |

Identifying stubbed DOM elements

A spied/stubbed component will be rendered into the DOM like this:

<div class="spy-ComponentName" id="spy-ComponentName-instanceNumber" />

You can use the selector function to return a selector that will match all instances of a rendered double. So for the example above, calling spySelector(Child) will return "div[class=spy-Child]".

You can use the instanceSelector(n) to return a selector that matches a specific instance of the component.

Triggering two-way bindings

If your stubbed component uses a two-way binding you can trigger that binding to update using the updateBoundValue function.

For example, say you have the component TagList which can be used like this:

<TagList bind:tags={tags} />

Then you can test how your component responds to updates to tags like this:

rewire$TagList(componentDouble(TagList));
mount(<your component that uses TagList>);

TagList.firstInstance().updateBoundValue(
  component, "tags", ["a", "b", "c"]);

Warning: updateBoundValue has been tested with Svelte version 3.16. It is incompatible with 3.15 and below.

Component property reference

All of these functions are available on your component double type.

| Property/function | Type | Description | | ----------------- | ---- | ----------- | | instances | Array of instances | Each instance of the component that has been rendered. | | reset() | Function | Resets a mocked component between tests. Call this in your beforeEach block. | | selector() | Function | Selector for all instances of this double. | | instanceSelector(n) | Function | Selector for a single instances of this double. | | findMatching(matchFn) | Function | Find the call whose props match the matchFn predicate | | firstInstance() | Function | Returns the first instance of a component, which you an then manipulate using functions such as updateBoundValue (see note above). | | lastInstance() | Function | Returns the last instance of a component. | | getInstanceFromElement(domElement) | Function | Returns the component instance that rendered the given DOM element. | | mountedInstances() | Function | Returns only the instances that are currently rendered in the DOM. | | propsOfAllInstances() | Function | Returns an array for props for each of the rendered instance of this component.| | dispatch(event) | Function | Dispatches an event to the last rendered component. You can also call dispatch on individual instances. |

Contributing

All contributions are welcome. Please feel free to create issues or raise PRs.