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

@kiwa-lab/solidjs

v2.0.0

Published

SolidJS Signal-based reactivity test adapter for kiwa — invoke Signal / Effect / createResource without a running SolidJS runtime, capture Suspense boundary transitions + error boundary, and render Solid components into a lightweight virtual tree for asse

Readme

@kiwa-lab/solidjs

SolidJS Signal + Effect + createResource + Suspense boundary test adapter for kiwa — model Solid's fine-grained reactivity graph in Vitest without a Solid runtime.

pnpm add -D @kiwa-lab/solidjs

Why

SolidJS is a fine-grained reactive framework where createSignal, createEffect, and createResource form the core primitives. Real Solid needs a runtime with an owner tree + reactive graph. @kiwa-lab/solidjs gives you standalone mock primitives that model the same accessor / setter / effect-run / resource-fetch contract so tests can assert on signal transitions + effect traces + resource state directly.

Quick start

Signal + Effect

import { describe, expect, it } from 'vitest';
import { mockSignal, mockEffect, batch } from '@kiwa-lab/solidjs';

describe('counter', () => {
  it('effect re-runs on signal write', () => {
    const [count, setCount] = mockSignal(0);
    let observed = -1;
    mockEffect(() => {
      observed = count();
    });
    setCount(5);
    expect(observed).toBe(5);
  });

  it('batched writes dedup into a single effect run', () => {
    const [a, setA] = mockSignal(1);
    const [b, setB] = mockSignal(2);
    let runs = 0;
    mockEffect(() => {
      void a();
      void b();
      runs += 1;
    });
    const baseline = runs;
    batch(() => {
      setA(10);
      setB(20);
    });
    expect(runs).toBe(baseline + 1);
  });
});

createResource

import { expect, it } from 'vitest';
import { createResourceStub } from '@kiwa-lab/solidjs';

it('resource lifecycle', async () => {
  const { accessor, actions, initialFetch } = createResourceStub(async () => ({ ok: 1 }));
  expect(accessor.state).toBe('pending');
  await initialFetch;
  expect(accessor.state).toBe('ready');
  expect(accessor()).toEqual({ ok: 1 });

  const refetch = actions.refetch();
  expect(accessor.state).toBe('refreshing');
  await refetch;
  expect(accessor.state).toBe('ready');
});

Suspense boundary

import { expect, it } from 'vitest';
import { renderWithSuspense, h, stringify } from '@kiwa-lab/solidjs';

it('fallback → resolved swap', async () => {
  const boundary = await renderWithSuspense({
    component: () => h('p', null, 'ready'),
    fallback: h('p', null, 'loading'),
    waitFor: Promise.resolve('ok'),
  });
  expect(stringify(boundary.fallback)).toBe('<p>loading</p>');
  expect(boundary.resolved && stringify(boundary.resolved)).toBe('<p>ready</p>');
  expect(boundary.timedOut).toBe(false);
});

SolidStart route

import { expect, it } from 'vitest';
import { invokeSolidRoute, h, stringify, redirect } from '@kiwa-lab/solidjs';

it('renders page with loader data', async () => {
  const { tree, data, redirect: r } = await invokeSolidRoute({
    page: (props) => h('article', null, String(props.data)),
    load: async ({ params }) => `id=${params.id}`,
    params: { id: '42' },
  });
  expect(r).toBeNull();
  expect(data).toBe('id=42');
  expect(tree && stringify(tree)).toBe('<article>id=42</article>');
});

it('loader redirect surfaces on the result', async () => {
  const { redirect: r } = await invokeSolidRoute({
    page: () => h('p', null, 'unreachable'),
    load: async () => {
      throw redirect('/login', 302);
    },
  });
  expect(r?.url).toBe('/login');
});

API

| Export | Purpose | |---|---| | mockSignal(initial) | [getter, setter] with subscribe / Object.is short-circuit / updater-fn form | | mockEffect(fn) | Reactive re-run with runCount() / trace() / dispose() | | batch(fn) | Group writes so subscribed effects dedup to a single run | | track(fn) | Capture signal reads inside the callback | | createResourceStub(fetcher) | unresolved → pending → ready / errored / refreshing state machine | | renderSolid({ component, props }) | Synchronous mount + dispose() + html() | | hydrate({ component, ssrMarkup }) | Client / SSR diff with hydrated + mismatch | | createRoot(fn) | Solid-shaped createRoot(dispose => ...) with scope tracking | | h(type, props, ...children) | Lightweight JSX-shaped factory | | findElements(tree, predicate) | Depth-first virtual DOM walker | | stringify(tree) | SSR-shaped HTML string | | invokeSolidRoute(opts) | SolidStart route runner with redirect() / notFound() signal capture | | renderWithSuspense(opts) | Fallback → resolved swap + timedOut safety gate | | errorBoundary(opts) | Component throws land in a fallback signal |

Brand symbols: SIGNAL_SYMBOL / EFFECT_SYMBOL / RESOURCE_SYMBOL / SOLID_ELEMENT_SYMBOL / SOLID_REDIRECT_SYMBOL / SOLID_NOT_FOUND_SYMBOL / SUSPENSE_BOUNDARY_SYMBOL / ERROR_BOUNDARY_SYMBOL.

Limits

  • Real Solid runtime binding (solid-js package integration) is not in scope for v0.1. Tests use standalone mocks with the same brand symbols.
  • mockEffect only subscribes to signals it reads through the getter — downstream computations are not tracked.
  • renderWithSuspense follows a deterministic 2-phase model (fallback first, then resolved / timedOut). Real Solid can pause mid-render; that's out of scope here.

Companion: v1.19-1a of the kiwa test framework — released alongside @kiwa-lab/fresh (#814) + @kiwa-lab/hono (v1.19-1c) as part of the v1.19 modern framework depth-drive.