Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ npm run dev # start utviklingsserver på http://localhost:5173
| `npm run build` | Kjører typekontroll og bygger til `dist/` |
| `npm run preview` | Viser det bygde resultatet lokalt |
| `npm run typecheck` | Kjører TypeScript med streng typekontroll |
| `npm test` | Kjører alle testene én gang |
| `npm run test:watch` | Kjører testene ved hver endring |
| `npm run lint` | Kjører ESLint på hele prosjektet |
| `npm run format` | Formaterer alle filer med Prettier |
| `npm run format:check` | Sjekker formatering uten å endre filer |
Expand All @@ -101,6 +103,9 @@ ESLint finner feil i koden, mens Prettier bestemmer formateringen.
ESLint-regler som ellers ville kollidert med Prettier. Byggfiler,
avhengigheter og `package-lock.json` formateres ikke.

Testene bruker Vitest og React Testing Library. Hva som testes, og hvilke
kontroller som er gjort i nettleser, står i [docs/testing.md](docs/testing.md).

## Mappestruktur

```
Expand All @@ -114,6 +119,7 @@ src/
pages/ Én mappe per side
hooks/ Små felles hooks, for eksempel usePageTitle
design/ Designreferanse, bare under utvikling
test/ Felles oppsett for testene
```

Komponenter i `components/` får data gjennom props og importerer ikke
Expand Down
117 changes: 117 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Testing

Oversikt over automatiske tester og kontroller av brukeropplevelsen for første
innlevering. Dokumentet oppdateres når nye tester eller kontroller kommer til.

## Kjøre testene

```bash
npm test # kjører alle testene én gang og avslutter
npm run test:watch # kjører testene på nytt ved hver endring
```

Testene bruker [Vitest](https://vitest.dev/) med
[React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)
og jsdom, så de trenger ingen nettleser. Vitest bruker samme oppsett som Vite,
så CSS-moduler, SVG-importer og TypeScript virker likt i test og app.
Oppsettet ligger i `vite.config.ts` og `src/test/setup.ts`.

Testfilene ligger ved siden av koden de tester og heter `*.test.ts` eller
`*.test.tsx`.

## Prinsipper

- **Test oppførsel, ikke implementasjon.** Testene finner elementer slik en
bruker eller skjermleser gjør, med rolle og tilgjengelig navn, for eksempel
`getByRole('button', { name: 'Send forespørsel (demo)' })`. CSS-klasser og
intern tilstand testes ikke.
- **Bruk `userEvent` for interaksjon**, slik at klikk og tastetrykk oppfører
seg som i en nettleser. Datofelt endres med `fireEvent.change`, fordi
jsdom ikke har nettleserens datovelger.
- **Sjekk `aria-invalid`, ikke `toBeInvalid()`, på påkrevde felt.**
`toBeInvalid()` bruker også nettleserens egen validering, og et tomt
`required`-felt er da alltid ugyldig. Testen ville bestått selv om skjemaet
ikke viste noen feil.
- **Lås datoen når testen avhenger av «i dag».** Testene for leieforespørsel
bruker `vi.useFakeTimers({ toFake: ['Date'] })`, så bare `Date` forfalskes
og `userEvent` virker som vanlig.

## Hva som testes

| Fil | Hva som testes |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `src/App.test.tsx` | Navigasjon via meny, annonsekort og tilbakelenke, aktiv side, fanetittel, fokus ved sidebytte, hopp-lenke, 404-sider, katalogsøk |
| `utils/listingFormat.test.ts` | Døgnpris, gratis utlån og norsk tusenskille |
| `utils/listingFilters.test.ts` | Søk uten å skille store og små bokstaver, tomt søk, kombinerte filtre, filtre i URL-en |
| `utils/listingSort.test.ts` | Sortering på pris, stabil rekkefølge ved lik pris, sortering i URL-en |
| `utils/rentalPeriod.test.ts` | Antall døgn, samme dag, overgang fra sommertid, datovalidering |
| `utils/listingForm.test.ts` | Validering av alle feltene, pris 0, ugyldige priser som «12,5» og «1e3» |
| `components/PriceTag/` | Gratismerking og døgnpris vises som tekst |
| `components/TextField/` | Tilgjengelig navn, beskrivelse og feilmelding for `TextField`, `SelectField` og `TextAreaField` |
| `components/Button/` | Sender ikke inn skjema ved et uhell, tastatur og deaktivert knapp |
| `components/RentalRequestForm/` | Feil ved tomme og ugyldige datoer, samlet pris, gratis utlån, demomelding |
| `components/ListingForm/` | Etiketter, feil og fokus på første ugyldige felt, prisforhåndsvisning, demomelding |

Status 1. oktober 2026: 11 testfiler og 79 tester, alle grønne.

## Kontroller før innlevering

Disse kommandoene skal gå uten feil før en pull request merges:

```bash
npm run typecheck
npm run lint
npm run format:check
npm test
npm run build
```

### Ren installasjon

Kontrollert 1. oktober 2026 med en ny klone av repoet, Node 24.21 og npm
11.19, ved å følge README: `npm ci`, deretter alle kommandoene over og
`npm run dev`. Alt gikk uten feil, og utviklingsserveren svarte på
`http://localhost:5173`.

npm skriver en advarsel om at `fsevents` har installasjonsskript. Pakken
brukes bare på macOS av filovervåkingen, og advarselen kan ignoreres.

### Mobil og desktop

Kontrollert i Chromium med Playwright i breddene 320, 375, 768 og 1280 px.
Sidene som ble sjekket:

- katalogen uten filtre, med filtre og sortering, og uten treff
- detaljvisning med lang tittel, uten bilde og med gratis utlån
- utleieskjemaet med feilmeldinger synlige
- «Fant ikke siden» og «Fant ikke annonsen»

Resultat: ingen sider gir horisontal scrolling i noen av breddene. Minste
tekststørrelse er 14 px. Lange titler brytes over flere linjer.

### Tastatur og synlig fokus

Kontrollert ved å tabulere gjennom katalogen, detaljvisningen og
utleieskjemaet.

- Rekkefølgen følger visningen: hopp-lenke, logo, meny, filtre, sortering og
annonsekort.
- Alle elementer som får fokus, har synlig fokusring. På annonsekortene
tegnes ringen rundt hele kortet.
- Hopp-lenken flytter fokus til hovedinnholdet.
- Annonsekort åpnes med Enter.
- Etter en innsending med feil havner fokus på første ugyldige felt.

## Begrensninger

- **Nettleserkontrollene er automatiserte.** Mobil, desktop og tastatur er
kontrollert med Playwright i Chromium, ikke på en ekte telefon, i Firefox
eller Safari, eller med skjermleser. Dette bør kontrolleres for hånd før
senere innleveringer.
- **Datofelt i Chromium** har ett tabulatorstopp for dag, måned og år. Det er
nettleserens egen oppførsel.
- **Ingen ende-til-ende-tester eller API-tester ennå.** De kommer når
backenden finnes. Testene for appen rendrer hele `App` i en `MemoryRouter`,
men kjører i jsdom og sjekker ikke layout.
- **`favicon.ico` mangler**, så nettleseren logger en 404 i konsollen. Det
påvirker ikke appen.
Loading