ワンクリックで
vitest-testing
Vitest unit and component testing patterns. Use when writing unit tests, component tests, or hook tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Vitest unit and component testing patterns. Use when writing unit tests, component tests, or hook tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Code review of current PR/commit changes against project coding standards. Use when the user asks for a code review or mentions reviewing changes.
Reference for the Tangle component YAML specification format
Guidelines for building well-structured, maintainable ML pipelines in Tangle
Analyzes merged PRs from the past week, identifies user-facing changes, and opens a draft PR to the TangleML/website docs repo with updated documentation. Use when running the weekly documentation sync, or when the user invokes /docs-update.
React and React Compiler patterns for this project. Use when writing React components, hooks, providers, or working with React Compiler compatibility.
Run validation and testing commands for the project. Use when the user asks to validate, lint, typecheck, or run tests.
| name | vitest-testing |
| description | Vitest unit and component testing patterns. Use when writing unit tests, component tests, or hook tests. |
Focus tests on the component/hook under test. Assume that dependencies (services, hooks, utilities) are independently tested in their own test files. Only mock what's necessary to isolate the unit under test — don't re-test dependency behavior or create elaborate mock setups for services that aren't the focus of the test.
describe, it, expect are globally available (no imports needed)@testing-library/jest-dom is configured in vitest-setup.js@testing-library/react with render, screen, fireEvent, waitForvi.mock() and vi.fn(), not HTTP interceptionTests are co-located next to source files:
src/utils/searchUtils.ts
src/utils/searchUtils.test.ts
src/hooks/useIOSelectionPersistence.ts
src/hooks/useIOSelectionPersistence.test.ts
src/components/shared/SuspenseWrapper.tsx
src/components/shared/SuspenseWrapper.test.tsx
describe("formatDuration", () => {
it("formats seconds correctly", () => {
const start = "2024-01-01T10:00:00.000Z";
const end = "2024-01-01T10:00:30.000Z";
expect(formatDuration(start, end)).toBe("30s");
});
});
Render with providers using a wrapper function:
const renderWithProviders = (component: React.ReactElement) => {
return render(component, {
wrapper: ({ children }) => (
<ComponentSpecProvider spec={mockComponentSpec}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</ComponentSpecProvider>
),
});
};
it("renders the toolbar", async () => {
renderWithProviders(<RunToolbar />);
await waitFor(() => {
expect(screen.getByTestId("inspect-pipeline-button")).toBeInTheDocument();
});
});
Use renderHook with a wrapper for hooks that need providers:
const createWrapper = () => {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
return ({ children }: { children: React.ReactNode }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};
it("should hydrate component", async () => {
vi.mocked(hydrateComponentReference).mockResolvedValue(mockHydratedRef);
const { result } = renderHook(
() => useHydrateComponentReference(mockComponent),
{ wrapper: createWrapper() },
);
await waitFor(() => {
expect(result.current).toEqual(mockHydratedRef);
});
});
Use act for state updates in hooks:
act(() => {
result.current.preserveIOSelectionOnSpecChange(initialSpec);
});
expect(mockSetNodes).toHaveBeenCalledWith(expect.any(Function));
vi.mock()vi.mock("@/utils/localforage", () => ({
componentExistsByUrl: vi.fn(),
getComponentByUrl: vi.fn(),
saveComponent: vi.fn(),
}));
// React component mock
vi.mock("@monaco-editor/react", () => ({
default: ({ defaultValue }: { defaultValue: string }) => (
<pre data-testid="monaco-mock">{defaultValue}</pre>
),
}));
// Provider/context mock
vi.mock("@/providers/ComponentSpecProvider", () => ({
useComponentSpec: () => ({
componentSpec: mockSpec,
setComponentSpec: mockSetComponentSpec,
}),
}));
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
// ... test code
expect(consoleSpy).toHaveBeenCalledWith("Error:", expect.any(Error));
const mockFetch = vi.fn();
global.fetch = mockFetch;
mockFetch.mockResolvedValue({
ok: true,
text: () => Promise.resolve(yamlContent),
} as Response);
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
Create inline helper functions for test data — don't over-abstract:
const createMockNode = (
id: string,
type: "input" | "output" | "task",
label: string,
selected = false,
) => ({
id,
type,
position: { x: 0, y: 0 },
data: { label },
selected,
});
beforeEach(() => {
vi.clearAllMocks();
});
afterEach(() => {
cleanup(); // Testing Library cleanup
queryClient.clear(); // Clear query cache if using QueryClient
vi.restoreAllMocks();
});
// DOM assertions
expect(screen.getByTestId("submit")).toBeInTheDocument();
expect(screen.queryByTestId("hidden")).not.toBeInTheDocument();
// Mock assertions
expect(mockFn).toHaveBeenCalledWith(url);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).not.toHaveBeenCalled();
// Partial matching
expect(mockSave).toHaveBeenCalledWith({
id: expect.stringMatching(/^component-\w+$/),
createdAt: expect.any(Number),
});
Prefer fireEvent for simple interactions in this project:
const input = screen.getByLabelText("Name") as HTMLInputElement;
fireEvent.change(input, { target: { value: "NewName" } });
fireEvent.blur(input);
expect(mockCallback).toHaveBeenCalled();
// Wait for state updates
await waitFor(() => {
expect(screen.getByTestId("content")).toBeInTheDocument();
});
// Assert on promises
await expect(promise).resolves.toBe(expectedValue);
pnpm test — Run all unit tests oncepnpm run test:coverage — Run with coverage reportpnpm run validate:test — Full validate + unit tests