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-test/ui

v1.0.1

Published

React component test adapter for kiwa (Vitest + Testing Library + JSDOM)

Readme

@kiwa-test/ui

Multi-framework component test adapter for kiwa — Vitest + Testing Library + JSDOM under a single setupComponentEnv family of helpers.

Overview

@kiwa-test/ui is the Layer 2 adapter that turns a Layer 1 kiwa-design spec (with mode = render | interaction | snapshot) into a runnable Vitest suite. It ships five component adapters that share the same lifecycle contract.

| Framework | Helper | Underlying lib | |---|---|---| | React | setupComponentEnv | @testing-library/react | | Vue 3 | setupVueComponentEnv | @vue/test-utils | | Svelte | setupSvelteComponentEnv | @testing-library/svelte | | SolidJS | setupSolidComponentEnv | @solidjs/testing-library | | Lit (Web Components) | setupLitComponentEnv | @open-wc/testing-helpers | | Qwik (resumable) | setupQwikComponentEnv | @noma.to/qwik-testing-library | | Angular | setupAngularComponentEnv | @testing-library/angular | | Browser (real Chromium) | setupBrowserComponentEnv | @playwright/test |

Install

pnpm add -D @kiwa-test/ui @kiwa-test/core \
  @testing-library/react @testing-library/user-event jsdom \
  react react-dom vitest

@testing-library/react, @testing-library/user-event, and jsdom are declared as optional peer dependencies — install only what your specs need.

Three modes

import { setupComponentEnv } from "@kiwa-test/ui";

// 1) render mode — mount + screen queries, no interaction.
const renderEnv = await setupComponentEnv({ mode: "render", ui: <Counter /> });

// 2) interaction mode — userEvent-driven workflow tests.
const interactionEnv = await setupComponentEnv({
  mode: "interaction",
  ui: <Counter />,
});
await interactionEnv.user.click(interactionEnv.screen.getByRole("button", { name: "increment" }));

// 3) snapshot mode — capture serialized markup for regression diffs.
const snapshotEnv = await setupComponentEnv({ mode: "snapshot", ui: <Counter /> });
expect(snapshotEnv.markup).toContain("data-testid=\"value\"");

await renderEnv.stop(); // unmount + cleanup

Every env exposes result (RTL RenderResult) and either screen (render / interaction) or markup (snapshot). The discriminator is env.kind.

Vitest config

// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({ test: { environment: "jsdom" } });

Example: Counter PoC

See examples/react-component-poc/ for the end-to-end PoC: the Layer 1 spec (tests/spec/integration/test-spec-counter.ui.md) lists 7 cases (render / interaction / snapshot) and the Vitest suite executes all of them against a single Counter component.

SolidJS quickstart

import { createSignal, createComponent } from "solid-js";
import { setupSolidComponentEnv } from "@kiwa-test/ui";

function SolidCounter(props: { initial?: number }) {
  const [count, setCount] = createSignal(props.initial ?? 0);
  // ...build DOM or use JSX with a Solid-aware transform...
}

const env = await setupSolidComponentEnv({
  mode: "render",
  component: () => createComponent(SolidCounter, { initial: 3 }),
});

expect(env.result.getByTestId("value").textContent).toBe("3");
await env.stop();

Make sure Vitest resolves the browser entry of solid-js/web when running under jsdom:

// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  resolve: { conditions: ["browser", "development", "module", "import", "default"] },
  test: { environment: "jsdom" },
});

Lit (Web Components) quickstart

import { LitElement, html } from "lit";
import { setupLitComponentEnv } from "@kiwa-test/ui";

class KiwaCounter extends LitElement {
  static properties = { count: { state: true } };
  declare count: number;
  constructor() { super(); this.count = 0; }
  render() {
    return html`<span data-testid="value">${this.count}</span>`;
  }
}
customElements.define("kiwa-counter", KiwaCounter);

const env = await setupLitComponentEnv({
  mode: "render",
  template: html`<kiwa-counter></kiwa-counter>`,
});

const span = env.handle.shadowQuerySelector('[data-testid="value"]');
expect(span?.textContent).toBe("0");
await env.stop();

The Lit adapter relays the shadow DOM through handle.shadowQuerySelector for ergonomic deep queries, and exposes the upgraded element via handle.element (typed as HTMLElement; cast to LitElement when you need updateComplete).

Qwik quickstart

Qwik requires @builder.io/qwik/optimizer's Vite plugin for its JSX transform, which collides with the React JSX pipeline used by the rest of this package. The expected setup in a downstream Qwik consumer is therefore a Qwik-specific Vitest project that registers the optimizer plugin:

// qwik consumer's vitest.config.ts
import { defineConfig } from "vitest/config";
import { qwikVite } from "@builder.io/qwik/optimizer";

export default defineConfig({
  plugins: [qwikVite()],
  test: { environment: "jsdom" },
});

Then exercise components with the kiwa adapter:

import { component$ } from "@builder.io/qwik";
import { setupQwikComponentEnv } from "@kiwa-test/ui";

const Counter = component$(() => <span data-testid="value">0</span>);

const env = await setupQwikComponentEnv({ mode: "render", component: <Counter /> });
expect(env.result.getByTestId("value").textContent).toBe("0");
await env.stop();

This package's own test suite ships a contract test (tests/qwik.test.ts) that asserts the adapter's missing-peer error message — full Qwik JSX rendering will land in a dedicated example project (examples/qwik-component-poc) in a follow-up PR.

Angular quickstart

Angular requires a TestBed-aware Vitest setup file (zone.js + platformBrowserDynamic). Add to a downstream Angular consumer:

// vitest.setup.ts
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
);
// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: { environment: "jsdom", setupFiles: ["./vitest.setup.ts"] },
});

Then exercise standalone components with the kiwa adapter:

import { Component } from "@angular/core";
import { setupAngularComponentEnv } from "@kiwa-test/ui";

@Component({
  standalone: true,
  selector: "kiwa-counter",
  template: `<span data-testid="value">{{ count }}</span>`,
})
class KiwaCounter {
  count = 0;
}

const env = await setupAngularComponentEnv({ mode: "render", component: KiwaCounter });
expect(env.result.getByTestId("value").textContent?.trim()).toBe("0");
await env.stop();

As with the Qwik adapter, this package ships a contract test (tests/angular.test.ts) that verifies the missing-peer error message. Fully-rendered Angular tests are scoped to a follow-up examples/angular-component-poc PR.

License

MIT