Tilbake til alle innlegg

Testing av komponenter med React Testing Library

Strategi og praksis for å teste Jøkul-komponenter og egne komposisjoner på en måte som speiler faktisk bruk.

Kategori
Utvikling
Publisert
05.03.2026
Lesetid
2 min.

Vi hadde en komponent som alltid var grønn i CI. Hundre prosent testdekning. Stolt av den var vi. Så gikk det i produksjon og én bruker klarte ikke å sende inn skjemaet sitt fordi feilmeldingene aldri ble synlige for skjermlesere. Testene hadde sjekket at komponentene rendret riktig HTML — men ingen hadde sjekket det brukeren faktisk opplever. Det var lekkepunktet i filosofien vår.

Jøkul-teamet bruker Vitest og React Testing Library internt. Jest fungerer like bra — API-ene er identiske.

Spørringsprioritet — følg rekkefølgen

RTL er bygget rundt én filosofi: test det brukeren ser og opplever. Det betyr at du skal bruke spørringer som speiler hvordan skjermlesere og faktiske brukere navigerer siden. Prioritetsrekkefølgen er ikke valgfri:

getByRole
Alltid første valg. Speiler skjermlesernavigasjon. getByRole("button", { name: "Send inn" })
getByLabelText
For skjemafelter. Tvinger deg til å ha labels — god tilgjengelighetspraksis som bieffekt.
getByText
For ikke-interaktive elementer. Avsnitt, overskrifter, listeinnhold.
getByTestId
Siste utvei. Krev begrunnelse i code review. Tyder på at noe er feil med HTML-semantikken.

userEvent er ikke det samme som fireEvent

Jeg brukte fireEvent.click() i lang tid. Det er ikke feil — men det er ikke hva brukeren gjør. En bruker klikker ikke bare ett DOM-event; de hovrer, fokuserer, klikker og blurrer. userEvent simulerer hele sekvensen:

TypeScript
// Unngå
fireEvent.click(button);

// Foretrekk — simulerer hele interaksjonssekvensen
await userEvent.click(button);

// For tekstinntasting
await userEvent.type(input, "Ola Nordmann");

jest-axe — tilgjengelighet i CI

  1. Installer: npm install --save-dev jest-axe
  2. Importer og utvid: import "jest-axe/extend-expect"
  3. Legg til axe(container) i kritiske komponent-tester
  4. Kjør i CI — tilgjengelighetsregresjoner fanges automatisk

Hva du IKKE skal teste

Testeksempel som faktisk fanget en ekte bug

Her er et komprimert eksempel fra kodebasen vår. Testen fanger akkurat feilen vi hadde i produksjon — at feilmeldinger ikke ble kunngjort til skjermlesere:

TSX
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { axe, toHaveNoViolations } from "jest-axe";
expect.extend(toHaveNoViolations);

describe("Kontaktskjema", () => {
  it("viser og kunngjør feilmelding ved tomt navn", async () => {
    render(<Kontaktskjema />);

    await userEvent.click(
      screen.getByRole("button", { name: "Send inn" })
    );

    // Sjekker at feilmeldingen er synlig OG tilgjengelig
    const error = screen.getByRole("alert");
    expect(error).toHaveTextContent("Navn er påkrevd");
  });

  it("har ingen tilgjengelighetsfeil", async () => {
    const { container } = render(<Kontaktskjema />);
    expect(await axe(container)).toHaveNoViolations();
  });
});

Legg merke til getByRole("alert") — det tester at meldingen faktisk bruker riktig ARIA-rolle, ikke bare at den er i DOM-en. Det er forskjellen.

Hundre prosent testdekning er ikke et mål — det er et tall. Målet er at testene dine fanger de feilene som faktisk skader brukere. Tenk på hvem som bruker løsningen din og skriv tester som verifiserer at de faktisk kan bruke den.