rstest
A testing utility for Preact apps using Rspack, enforcing correct import patterns and configurations.
Install
mkdir -p .claude/skills/rstest && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19064" && unzip -o skill.zip -d .claude/skills/rstest && rm skill.zipInstalls to .claude/skills/rstest
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Rstest patterns for Rspack-native unit testing with Preact. Trigger: When writing tests with @rstest/core, testing-library/preact, or configuring rstest.config.ts.Key capabilities
- →Write unit tests using `@rstest/core` for Preact components
- →Configure `rstest.config.ts` for Rspack environments
- →Set up `rstest.setup.ts` for automatic cleanup and matcher extension
- →Mock modules and functions using `vi` from `@rstest/core`
- →Handle asynchronous testing with `findBy*` and `waitFor`
How it works
This skill standardizes Preact unit testing in Rspack environments by enforcing the use of `@rstest/core` and `@testing-library/preact`. It provides configuration patterns for test environments and setup files.
Inputs & outputs
When to use rstest
- →Writing Preact component tests
- →Configuring test environments
- →Managing mock APIs
About this skill
Rstest Skill
Critical Rules
- ALWAYS import from
@rstest/core— NEVER fromvitestorjest - Use
@testing-library/preact— NEVER@testing-library/react - JSX runtime is Preact:
"jsxImportSource": "preact"in tsconfig — NEVER React cleanup()is called automatically via setup file — but know it must be inafterEachviis the mock API (same as vitest) — imported from@rstest/coreglobals: truein config meansdescribe/it/expectare available globally, but prefer explicit imports
Config Pattern
// rstest.config.ts
import { pluginPreact } from "@rsbuild/plugin-preact";
import { pluginSass } from "@rsbuild/plugin-sass";
import { defineConfig } from "@rstest/core";
export default defineConfig({
globals: true,
testEnvironment: "jsdom",
setupFiles: ["./rstest.setup.ts"],
plugins: [pluginPreact(), pluginSass()],
exclude: ["node_modules", "automation_test/**"],
});
Setup File Pattern
// rstest.setup.ts
import { afterEach, expect } from "@rstest/core";
import * as jestDomMatchers from "@testing-library/jest-dom/matchers";
import { cleanup } from "@testing-library/preact";
afterEach(() => cleanup());
expect.extend(jestDomMatchers);
Component Test Pattern
import { describe, it, expect, beforeEach } from "@rstest/core";
import { render, screen, fireEvent } from "@testing-library/preact";
import { Counter } from "./Counter";
describe("Counter", () => {
it("renders initial count", () => {
render(<Counter initialCount={0} />);
expect(screen.getByText("Count: 0")).toBeInTheDocument();
});
it("increments on button click", () => {
render(<Counter initialCount={0} />);
fireEvent.click(screen.getByRole("button", { name: /increment/i }));
expect(screen.getByText("Count: 1")).toBeInTheDocument();
});
});
Async Test Pattern
import { describe, it, expect } from "@rstest/core";
import { render, screen, waitFor } from "@testing-library/preact";
import { UserProfile } from "./UserProfile";
describe("UserProfile", () => {
it("loads user data asynchronously", async () => {
render(<UserProfile userId="1" />);
// findBy* = getBy* + waitFor (auto-retries)
const name = await screen.findByText("John Doe");
expect(name).toBeInTheDocument();
});
it("shows error state", async () => {
render(<UserProfile userId="invalid" />);
await waitFor(() => {
expect(screen.getByRole("alert")).toBeInTheDocument();
});
});
});
Mocking Pattern
import { describe, it, expect, vi, beforeEach } from "@rstest/core";
// Module mock
vi.mock("../services/api", () => ({
fetchUser: vi.fn().mockResolvedValue({ id: "1", name: "John" }),
}));
// Spy on method
import * as api from "../services/api";
describe("mocking", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("calls fetchUser with correct id", async () => {
const spy = vi.spyOn(api, "fetchUser").mockResolvedValue({ id: "1", name: "Jane" });
await api.fetchUser("1");
expect(spy).toHaveBeenCalledWith("1");
expect(spy).toHaveBeenCalledTimes(1);
});
it("uses vi.fn for callbacks", () => {
const onChange = vi.fn();
render(<Input onChange={onChange} />);
fireEvent.input(screen.getByRole("textbox"), { target: { value: "hello" } });
expect(onChange).toHaveBeenCalledWith("hello");
});
});
Commands
bun run test # run all tests
bun run test --watch # watch mode
bun run test --coverage # coverage report
Keywords
rstest, testing, preact, unit test, jsdom, testing-library, @rstest/core, vitest-compatible, component test, mocking, vi.mock, vi.fn, vi.spyOn, waitFor, findBy, fireEvent, screen
When not to use it
- →When writing tests with `vitest` or `jest` directly
- →When using `@testing-library/react` instead of `@testing-library/preact`
- →When the JSX runtime is React instead of Preact
Limitations
- →Must import from `@rstest/core`
- →Must use `@testing-library/preact`
- →JSX runtime must be Preact
How it compares
This workflow uses `@rstest/core` and `@testing-library/preact` for testing, providing a specific setup for Preact components in Rspack, unlike a generic testing approach that might use different frameworks or libraries.
Compared to similar skills
rstest side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| rstest (this skill) | 0 | 3mo | Review | Intermediate |
| dependency-upgrade | 26 | 4mo | Review | Intermediate |
| vitest | 41 | 6mo | No flags | Intermediate |
| browser-tools | 6 | 8mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
dependency-upgrade
wshobson
Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.
vitest
antfu
Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.
browser-tools
Whamp
Lightweight Chrome automation toolkit with shared configuration, JSON-first output, and six focused scripts for starting, navigating, inspecting, capturing, evaluating, and cleaning up browser sessions.
validate-typescript
BerryKuipers
Run TypeScript compiler type-checking (tsc --noEmit) to validate type safety and catch type errors. Works with any TypeScript project. Returns structured output with error counts, categories (type/syntax/import errors), and affected files. Used for quality gates and pre-commit validation.
ts-testing
johnlindquist
Design, implement, and maintain high‑value TypeScript test suites using popular JS/TS testing libraries. Use this skill whenever the user is adding tests, debugging failing tests, or refactoring code that should be covered by tests.
react-best-practices
redpanda-data
Client-side React performance optimization patterns.