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

@tito10047/stimulus-test-utils

v0.2.0

Published

Zero-config, Testing-Library-flavoured test harness for Stimulus controllers.

Readme

@tito10047/stimulus-test-utils

Test npm version License: MIT

Zero‑config, Testing‑Library‑flavoured test harness for Stimulus controllers.

Write your tests in plain JavaScript or TypeScript, mount a controller with a single call, simulate user interactions, and assert against the DOM / controller state — without ever touching happy‑dom/JSDOM, the Stimulus Application, or MutationObserver timing by hand.

What it's for

Testing Stimulus controllers usually means:

  • setting document.body.innerHTML,
  • creating and starting an Application,
  • registering the controller,
  • waiting for connect() via MutationObserver or await nextTick(),
  • cleaning up after every test.

This library hides all of that behind a single render() call and exposes a familiar Testing Library-style API (getByRole, findByText, user.click, …).

Installation

npm install -D @tito10047/stimulus-test-utils @hotwired/stimulus vitest happy-dom

@hotwired/stimulus is a peer dependency — you bring the version your app uses.

vitest.config.ts:

import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    environment: 'happy-dom',
    setupFiles: ['@tito10047/stimulus-test-utils/register'],
  },
})

The /register module wires up afterEach(cleanup) automatically. If you prefer to clean up manually, omit setupFiles and call cleanup() yourself.

Quick example

Controller:

// hello_controller.js
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['name', 'output']
  static values = { greeting: { type: String, default: 'Hello' } }

  greet() {
    this.outputTarget.textContent = `${this.greetingValue}, ${this.nameTarget.value}!`
  }
}

Test:

import { render, attr } from '@tito10047/stimulus-test-utils'
import { expect, test } from 'vitest'
import HelloController from './hello_controller.js'

test('greets by name', async () => {
  const { element, controller, user, getByRole } = await render(HelloController, {
    html: `
      <div ${attr.controller('hello', { greeting: 'Hi' })}>
        <input ${attr.target('hello', 'name')} />
        <button ${attr.action('hello', 'greet', 'click')}>Greet</button>
        <span ${attr.target('hello', 'output')}></span>
      </div>
    `,
  })

  await user.type(element.querySelector('input'), 'Ada')
  await user.click(getByRole('button', { name: 'Greet' }))

  expect(controller.outputTarget.textContent).toBe('Hi, Ada!')
})

No Application.start(), no document.body.innerHTML = …, no manual await nextTick().

What you get

  • render(ControllerClass, options) — mounts the fixture, starts an Application, registers the controller and waits for connect().
  • Query helpersgetByRole, getByText, getByTestId, findBy*, queryBy*, getAllBy* scoped to the mounted root.
  • user — user‑event simulations: click, type, keyboard, hover, …
  • waitFor / nextTick — async assertions for reactive DOM changes.
  • Attribute helpersattr.controller, attr.target, attr.action, attr.combine produce safe, typo‑free data-* attributes.
  • cleanup() — automatically stops the Application and removes the fixture (via the /register setup, or called manually).

A complete API overview is available in public_api.md and on the documentation site (see Documentation below).

Supported versions

  • Node.js 18.x, 20.x, 22.x
  • @hotwired/stimulus ^3.2
  • Vitest ^2

Contributing

npm ci
npm test          # vitest in watch mode
npm run typecheck # tsc --noEmit
npm run build     # tsup -> dist/

Pull requests are welcome. Before opening a PR, please run npm run typecheck and npx vitest run.

Documentation

The full documentation lives in docs/ and is published at https://tito10047.github.io/stimulus-test-utils/.

It is built with VitePress (prose + navigation) and TypeDoc with typedoc-plugin-markdown (auto‑generated API reference from TSDoc comments in src/).

Working on the docs locally

npm ci
npm run docs:dev       # start dev server on http://localhost:5173

This generates the API reference into docs/api/generated/ (gitignored) and runs the VitePress dev server with hot‑reload. Edit any .md file under docs/ and see the change instantly.

Building a static site

npm run docs:build     # runs docs:api, then vitepress build
npm run docs:preview   # serve the production build locally

The static site is emitted to docs/.vitepress/dist/.

Deploying to GitHub Pages

Deployment is fully automated via .github/workflows/docs.yml:

  • Trigger: every push to main, or a manual run from the Actions tab (workflow_dispatch).
  • Build: npm cinpm run docs:build → upload docs/.vitepress/dist as a Pages artifact.
  • Deploy: actions/deploy-pages@v4 publishes it.

One-time repository setup (only needed once):

  1. Go to Settings → Pages.
  2. Set Source to GitHub Actions.
  3. Push to main (or trigger the workflow manually). The first run will populate the URL shown above.

If you fork the repository, update the base option in docs/.vitepress/config.ts to match your repository name (for example /my-fork/), and tweak the GitHub link in the same file.

License

MIT © tito10047