Testy (Vitest / React Testing Library)
Frontend ZEUS testujemy Vitest-em (szybki, zgodny z Vite/ESM) i React Testing Library (RTL). Filozofia RTL: testuj to, co widzi użytkownik, nie szczegóły implementacji.
Vitest — testy logiki
Czystą logikę z lib/ testujemy jak zwykłe funkcje.
import { describe, it, expect } from "vitest";
import { formatForest } from "@/lib/format";
describe("formatForest", () => {
it("przycina i obniża wielkość liter", () => {
expect(formatForest(" CORP.LOCAL ")).toBe("corp.local");
});
});
Standard ProfessNet: pliki testów leżą obok kodu jako
*.test.ts/*.test.tsx. Nazwait(...)opisuje zachowanie po polsku albo po angielsku — byle jednolicie w obrębie projektu.
React Testing Library — testy komponentów
Testujemy zachowanie z perspektywy użytkownika: co jest na ekranie, co się dzieje po kliknięciu. Selektory wybieramy po roli i tekście, nie po klasach CSS.
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ProbeTable } from "@/app/(dashboard)/probes/probe-table";
const probes = [
{ id: "1", host: "dc01.corp", forest: "corp" },
{ id: "2", host: "dc02.dmz", forest: "dmz" },
];
it("filtruje probe'y po wpisaniu w pole", async () => {
render(<ProbeTable probes={probes} />);
await userEvent.type(screen.getByRole("textbox"), "dmz");
expect(screen.getByText("dc02.dmz")).toBeInTheDocument();
expect(screen.queryByText("dc01.corp")).not.toBeInTheDocument();
});
Standard ProfessNet: priorytet selektorów to
getByRole→getByLabelText→getByText.getByTestIdużywamy ostatecznie. Nie testujemy stanu wewnętrznego komponentu ani nazw klas.
Mockowanie fetch i modułów
Żądania sieciowe mockujemy, żeby testy były szybkie i deterministyczne.
import { vi, beforeEach, it, expect } from "vitest";
import { getProbe } from "@/lib/probes";
beforeEach(() => {
vi.restoreAllMocks();
});
it("zwraca sparsowany obiekt probe", async () => {
vi.spyOn(globalThis, "fetch").mockResolvedValue(
new Response(JSON.stringify({ id: "1", host: "dc01", forest: "corp" })),
);
const probe = await getProbe("1");
expect(probe.host).toBe("dc01");
});
Konfiguracja
// vitest.config.ts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
environment: "jsdom",
setupFiles: ["./vitest.setup.ts"],
globals: true,
},
});
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest"
}
}
| Rodzaj testu | Narzędzie | Co sprawdza |
|---|---|---|
logika lib/ | Vitest | wejście → wyjście funkcji |
| komponent | Vitest + RTL | render i interakcja jak u usera |
| hook | RTL renderHook | zwracany stan i efekty |
Wskazówka: jeśli test ciągle się psuje przy refaktorze, choć aplikacja działa — prawdopodobnie testujesz implementację, nie zachowanie. Przepisz go w stylu RTL.
Vitest do logiki, RTL do komponentów, testuj zachowanie a nie wnętrzności. Taki zestaw testów przeżywa refaktory i daje pewność przy każdym PR-ze.