From frontend-craft
Guides authoring and reviewing frontend unit, component, and lightweight integration tests using React Testing Library, Vue Test Utils, accessible queries, user-event interactions, and controlled mocks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/frontend-craft:fec-component-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use tests close to the code and user behavior to verify pure logic, component contracts, and lightweight module collaboration to reduce refactoring and UI interaction regression.
#Component testing
Use tests close to the code and user behavior to verify pure logic, component contracts, and lightweight module collaboration to reduce refactoring and UI interaction regression.
The cross-page real browser process is offloaded to the E2E workflow; if the test layer selection is unclear, do the test layering planning first.
Each test keeps Arrange / Act / Assert clearly segmented: preparing data and rendering, performing user actions, asserting user-visible results or exposing contracts.
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { SearchBox } from "./SearchBox";
test("submits the entered keyword", async () => {
const user = userEvent.setup();
const onSearch = vi.fn();
render(<SearchBox onSearch={onSearch} />);
await user.type(screen.getByRole("searchbox", { name: /keyword/i }), "orders");
await user.click(screen.getByRole("button", { name: /search/i }));
expect(onSearch).toHaveBeenCalledWith("orders");
});
import { mount } from "@vue/test-utils";
import UserMenu from "./UserMenu.vue";
test("emits logout when the logout item is clicked", async () => {
const wrapper = mount(UserMenu, {
props: { userName: "Ada" },
});
await wrapper.get('[data-testid="logout-button"]').trigger("click");
expect(wrapper.emitted("logout")).toHaveLength(1);
});
Prefer roles, labels, and visible text; only use data-testid when there is no stable semantics.
vi.mock("../api/users", () => ({
fetchUsers: vi.fn(async () => [{ id: "1", name: "Ada" }]),
}));
Each complex component covers at least:
function setup() {
const user = userEvent.setup();
const onSubmit = vi.fn();
render(<ProfileForm onSubmit={onSubmit} />);
return { user, onSubmit };
}
Put the repetitive rendering logic into setup, but don't hide the core actions and assertions of the test.
findBy* or waitFor for asynchronous assertions, do not use fixed delays.Produce test files in the same directory as the component or in the directory agreed upon by the project, covering core interactions, status and regression scenarios. During verification, run the existing test command of the project to confirm that the failure information can be located to user behavior or component contract.
npx claudepluginhub bovinphang/frontend-craftGenerates component tests (React Testing Library, Vue Test Utils, snapshot) for existing components. Use when adding test coverage after component creation.
Tests React components with React Testing Library, Vitest/Jest, MSW for network mocking, and axe accessibility assertions. Guides test vs E2E decisions.
Guides React component testing with React Testing Library, Vitest/Jest, MSW mocking, and axe accessibility assertions. Covers test boundaries between component and E2E tests.