vitest
Vitest unit testing patterns with React Testing Library. Trigger: When writing unit tests for React components, hooks, or utilities.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Vitest unit testing patterns with React Testing Library. Trigger: When writing unit tests for React components, hooks, or utilities.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Creates Prowler Attack Paths openCypher queries using the Cartography schema as the source of truth for node labels, properties, and relationships. Covers Prowler-specific additions (Internet node, ProwlerFinding, internal isolation labels), $provider_uid scoping, and list-property item nodes with typed `HAS_*` edges that run efficiently on both Neo4j and Amazon Neptune sinks. Trigger: When creating or updating Attack Paths queries.
Creates, syncs, audits and manages Prowler compliance frameworks end-to-end. Covers the two supported JSON schemas (universal multi-provider and legacy per-provider), the SDK model tree (legacy attribute classes, universal ComplianceFramework, ConfigRequirements guardrails), output formatters (legacy per-framework + universal data-driven), API/UI consumption, upstream sync workflows, and cloud-auditor check-mapping reviews. Trigger: When working with compliance frameworks (CIS, CIS Controls, NIST, PCI-DSS, SOC2, GDPR, ISO27001, ENS, MITRE ATT&CK, CCC, C5, CSA CCM, DORA, KISA ISMS-P, ASD Essential Eight, DISA STIG, CISA SCuBA, SecNumCloud, FedRAMP, HIPAA, NIS2, Prowler ThreatScore), creating a universal multi-provider framework, adding ConfigRequirements guardrails, syncing with upstream catalogs, auditing check-to-requirement mappings, adding output formatters, or fixing compliance JSON bugs (duplicate IDs, empty Version, wrong Section, stale check refs).
Make a cloud account compliant with a security or industry framework using Prowler Cloud.
Creates MCP tools for Prowler MCP Server. Covers BaseTool pattern, model design, and API client usage. Trigger: When working in mcp_server/ on tools (BaseTool), models (MinimalSerializerMixin/from_api_response), or API client patterns.
Manages changelog entries for Prowler components following keepachangelog.com format. Trigger: When creating PRs, adding changelog entries, or working with any CHANGELOG.md file in ui/, api/, mcp_server/, or prowler/.
Prowler UI-specific patterns. For generic patterns, see: typescript, react-19, nextjs-16, tailwind-4. Trigger: When working inside ui/ on Prowler-specific conventions (shadcn, folder placement, actions/adapters, shared types/hooks/lib).
| name | vitest |
| description | Vitest unit testing patterns with React Testing Library. Trigger: When writing unit tests for React components, hooks, or utilities. |
| license | Apache-2.0 |
| metadata | {"author":"prowler-cloud","version":"1.0","scope":["root","ui"],"auto_invoke":["Writing Vitest tests","Writing React component tests","Writing unit tests for UI","Testing hooks or utilities"]} |
| allowed-tools | Read, Edit, Write, Glob, Grep, Bash, Task |
For E2E tests: Use
prowler-test-uiskill (Playwright). This skill covers unit/integration tests with Vitest + React Testing Library.
Use Given/When/Then (AAA) pattern with comments:
it("should update user name when form is submitted", async () => {
// Given - Arrange
const user = userEvent.setup();
const onSubmit = vi.fn();
render(<UserForm onSubmit={onSubmit} />);
// When - Act
await user.type(screen.getByLabelText(/name/i), "John");
await user.click(screen.getByRole("button", { name: /submit/i }));
// Then - Assert
expect(onSubmit).toHaveBeenCalledWith({ name: "John" });
});
describe("ComponentName", () => {
describe("when [condition]", () => {
it("should [expected behavior]", () => {});
});
});
Group by behavior, NOT by method.
| Priority | Query | Use Case |
|---|---|---|
| 1 | getByRole | Buttons, inputs, headings |
| 2 | getByLabelText | Form fields |
| 3 | getByPlaceholderText | Inputs without label |
| 4 | getByText | Static text |
| 5 | getByTestId | Last resort only |
// ✅ GOOD
screen.getByRole("button", { name: /submit/i });
screen.getByLabelText(/email/i);
// ❌ BAD
container.querySelector(".btn-primary");
// ✅ ALWAYS use userEvent
const user = userEvent.setup();
await user.click(button);
await user.type(input, "hello");
// ❌ NEVER use fireEvent for interactions
fireEvent.click(button);
// ✅ findBy for elements that appear async
const element = await screen.findByText(/loaded/i);
// ✅ waitFor for assertions
await waitFor(() => {
expect(screen.getByText(/success/i)).toBeInTheDocument();
});
// ✅ ONE assertion per waitFor
await waitFor(() => expect(mockFn).toHaveBeenCalled());
await waitFor(() => expect(screen.getByText(/done/i)).toBeVisible());
// ❌ NEVER multiple assertions in waitFor
await waitFor(() => {
expect(mockFn).toHaveBeenCalled();
expect(screen.getByText(/done/i)).toBeVisible(); // Slower failures
});
// Basic mock
const handleClick = vi.fn();
// Mock with return value
const fetchUser = vi.fn().mockResolvedValue({ name: "John" });
// Always clean up
afterEach(() => {
vi.restoreAllMocks();
});
| Method | When to Use |
|---|---|
vi.spyOn | Observe without replacing (PREFERRED) |
vi.mock | Replace entire module (use sparingly) |
// Presence
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
// State
expect(button).toBeDisabled();
expect(input).toHaveValue("text");
expect(checkbox).toBeChecked();
// Content
expect(element).toHaveTextContent(/hello/i);
expect(element).toHaveAttribute("href", "/home");
// Functions
expect(fn).toHaveBeenCalledWith(arg1, arg2);
expect(fn).toHaveBeenCalledTimes(2);
// ❌ Internal state
expect(component.state.isLoading).toBe(true);
// ❌ Third-party libraries
expect(axios.get).toHaveBeenCalled();
// ❌ Static content (unless conditional)
expect(screen.getByText("Welcome")).toBeInTheDocument();
// ✅ User-visible behavior
expect(screen.getByRole("button")).toBeDisabled();
components/
├── Button/
│ ├── Button.tsx
│ ├── Button.test.tsx # Co-located
│ └── index.ts
pnpm test # Watch mode
pnpm test:run # Single run
pnpm test:coverage # With coverage
pnpm test Button # Filter by name