Add 125 new test functions across 10 new test files, covering: - CSRF middleware (8 tests): double-submit cookie validation - Auth middleware (12 tests): SessionLoader, RequireAdmin, context helpers - API handlers (28 tests): auth, faves CRUD, tags, users, export/import - Web handlers (41 tests): signup, login, password reset, fave CRUD, admin panel, feeds, import/export, profiles, settings - Config (8 tests): env parsing, defaults, trusted proxies, normalization - Database (6 tests): migrations, PRAGMAs, idempotency, seeding - Image processing (10 tests): JPEG/PNG, resize, EXIF strip, path traversal - Render (6 tests): page/error/partial rendering, template functions - Settings store (3 tests): CRUD operations - Regression tests for display name fallback and CSP-safe autocomplete Also adds CSRF middleware to testServer chain for end-to-end CSRF verification, TESTPLAN.md documenting coverage, and PLANS-v1.1.md with implementation plans for notes+OG, PWA, editing UX, and admin. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
388 lines
17 KiB
Markdown
388 lines
17 KiB
Markdown
# Testplan — Favoritter
|
|
|
|
## Dekning (oppdatert 2026-04-03)
|
|
|
|
| Lag | Pakke | Testfiler | Testfunksjoner | Dekning |
|
|
|-----|-------|-----------|----------------|---------|
|
|
| Data | `internal/store` | 6 | 24 | 70.8 % |
|
|
| HTTP (web) | `internal/handler` | 2 | 55 | 56.1 % |
|
|
| HTTP (API) | `internal/handler/api` | 1 | 28 | 75.8 % |
|
|
| Mellomvare | `internal/middleware` | 3 | 29 | 83.1 % |
|
|
| Konfig | `internal/config` | 1 | 8 | 81.1 % |
|
|
| Bilde | `internal/image` | 1 | 10 | 85.7 % |
|
|
| Database | `internal/database` | 1 | 6 | 66.0 % |
|
|
| Rendering | `internal/render` | 1 | 6 | 72.7 % |
|
|
| Modell | `internal/model` | 0 | 0 | 0.0 % (kun datatyper) |
|
|
|
|
**Totalt**: 16 testfiler, 167 testfunksjoner, alle grønne.
|
|
|
|
---
|
|
|
|
## Prioriteter
|
|
|
|
- **P0 — Kritisk**: Sikkerhet, autentisering, autorisasjon
|
|
- **P1 — Høy**: Forretningslogikk, dataintegritet, API-kontrakter
|
|
- **P2 — Middels**: Konfigurasjon, feilhåndtering, kanttilfeller
|
|
- **P3 — Lav**: Rendering, logging, hjelpefunksjoner
|
|
|
|
---
|
|
|
|
## P0 — Sikkerhet og tilgangskontroll
|
|
|
|
### CSRF-beskyttelse (`internal/middleware/csrf.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestCSRFTokenSetInCookie` | POST uten eksisterende cookie → ny `csrf_token`-cookie settes |
|
|
| 2 | `TestCSRFValidTokenAccepted` | POST med matchende cookie + form-felt → 200 |
|
|
| 3 | `TestCSRFMismatchRejected` | POST med feil token i form-felt → 403 |
|
|
| 4 | `TestCSRFMissingTokenRejected` | POST uten token i form-felt/header → 403 |
|
|
| 5 | `TestCSRFHeaderFallback` | POST med token i `X-CSRF-Token`-header → 200 |
|
|
| 6 | `TestCSRFSkippedForAPI` | POST til `/api/`-ruter → CSRF sjekkes ikke |
|
|
| 7 | `TestCSRFSafeMethodsPassThrough` | GET/HEAD/OPTIONS → ingen validering |
|
|
|
|
### Auth-mellomvare (`internal/middleware/auth.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestSessionLoaderValidToken` | Gyldig session-cookie → bruker satt i context |
|
|
| 2 | `TestSessionLoaderInvalidToken` | Ugyldig cookie → context uten bruker, ingen feil |
|
|
| 3 | `TestSessionLoaderNoCookie` | Ingen cookie → context uten bruker |
|
|
| 4 | `TestRequireLoginRedirectsToLogin` | Uautentisert → 302 til `/login` |
|
|
| 5 | `TestRequireLoginAllowsAuthenticated` | Autentisert → neste handler kjøres |
|
|
| 6 | `TestRequireAdminRejectsNonAdmin` | Vanlig bruker → 403 |
|
|
| 7 | `TestRequireAdminAllowsAdmin` | Admin-bruker → neste handler kjøres |
|
|
|
|
### API-autentisering (`internal/handler/api/`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAPILoginSuccess` | Korrekt brukernavn/passord → token + brukerinfo |
|
|
| 2 | `TestAPILoginWrongPassword` | Feil passord → 401 |
|
|
| 3 | `TestAPILoginInvalidBody` | Ugyldig JSON → 400 |
|
|
| 4 | `TestAPILogout` | Gyldig session → session slettet, cookie fjernet |
|
|
| 5 | `TestAPIRequiresAuth` | Beskyttede endepunkter uten session → 401/redirect |
|
|
|
|
### Autorisasjon (eierskap)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestCannotEditOtherUsersFave` | PUT `/api/v1/faves/{id}` med annen bruker → 403 |
|
|
| 2 | `TestCannotDeleteOtherUsersFave` | DELETE `/api/v1/faves/{id}` med annen bruker → 403 |
|
|
| 3 | `TestPrivateFaveHiddenFromAPI` | GET `/api/v1/faves/{id}` privat fave, annen bruker → 404 |
|
|
| 4 | `TestPrivateFaveVisibleToOwnerAPI` | GET `/api/v1/faves/{id}` privat fave, eier → 200 |
|
|
| 5 | `TestAdminEndpointsRequireAdminRole` | Ikke-admin → 403 på alle admin-ruter |
|
|
|
|
---
|
|
|
|
## P1 — Forretningslogikk og API-kontrakter
|
|
|
|
### Store: Innstillinger (`internal/store/settings.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestSettingsGetDefault` | Hent standardinnstillinger etter migrasjon |
|
|
| 2 | `TestSettingsUpdate` | Oppdater site_name, description, signup_mode → endringer leses tilbake |
|
|
| 3 | `TestSettingsUpdatePartial` | Oppdater kun ett felt → andre felter beholdes |
|
|
|
|
### API: Favoritter CRUD (`internal/handler/api/`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAPICreateFave` | POST med beskrivelse, URL, privacy, tags → 201 + komplett JSON |
|
|
| 2 | `TestAPICreateFaveMinimal` | POST med kun beskrivelse → 201, standardverdier |
|
|
| 3 | `TestAPICreateFaveMissingDescription` | POST uten beskrivelse → 400 |
|
|
| 4 | `TestAPIGetFave` | GET `/api/v1/faves/{id}` → komplett JSON med tagger |
|
|
| 5 | `TestAPIGetFaveNotFound` | GET med ugyldig ID → 404 |
|
|
| 6 | `TestAPIUpdateFave` | PUT med endringer → oppdatert JSON |
|
|
| 7 | `TestAPIUpdateFavePartial` | PUT med kun tags → andre felter uendret |
|
|
| 8 | `TestAPIDeleteFave` | DELETE → 204 No Content |
|
|
| 9 | `TestAPIDeleteFaveNotFound` | DELETE med ugyldig ID → 404 |
|
|
| 10 | `TestAPIListFaves` | GET `/api/v1/faves` → paginert resultat med total |
|
|
| 11 | `TestAPIListFavesPagination` | Sjekk page/limit-parametre og grense (limit ≤ 100) |
|
|
|
|
### API: Brukere og offentlige favoritter
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAPIGetUser` | GET `/api/v1/users/{username}` → brukerinfo |
|
|
| 2 | `TestAPIGetUserNotFound` | Ukjent brukernavn → 404 |
|
|
| 3 | `TestAPIGetDisabledUser` | Deaktivert bruker → 404 |
|
|
| 4 | `TestAPIGetUserFaves` | GET `/api/v1/users/{username}/faves` → kun offentlige |
|
|
| 5 | `TestAPIGetUserFavesEmpty` | Bruker uten favoritter → tom liste |
|
|
|
|
### API: Tagger
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAPISearchTags` | GET `/api/v1/tags?q=prefix` → matchende tagger |
|
|
| 2 | `TestAPISearchTagsEmpty` | Søk uten treff → tom liste |
|
|
| 3 | `TestAPISearchTagsLimit` | `limit`-parameter respekteres, maks 100 |
|
|
|
|
### API: Eksport/import
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAPIExport` | GET `/api/v1/export/json` → alle brukerens favoritter |
|
|
| 2 | `TestAPIImportValid` | POST med JSON-array → imported/total-svar |
|
|
| 3 | `TestAPIImportSkipsEmpty` | Oppføringer uten beskrivelse → hoppes over |
|
|
| 4 | `TestAPIImportInvalidJSON` | Ugyldig JSON → 400 |
|
|
| 5 | `TestAPIImportBodyLimit` | Stor body → avvist (MaxUploadSize) |
|
|
|
|
### Handler: Registrering og pålogging (`internal/handler/auth.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestSignupPageRendering` | GET `/signup` → skjema med CSRF-token |
|
|
| 2 | `TestSignupSuccess` | POST med gyldig data → registreringsforespørsel opprettet |
|
|
| 3 | `TestSignupDuplicate` | Duplisert brukernavn → feilmelding |
|
|
| 4 | `TestSignupDisabled` | `signup_mode=closed` → 403 eller redirect |
|
|
| 5 | `TestPasswordResetFlow` | Bruker med must_reset → tvinges til å endre passord |
|
|
| 6 | `TestPasswordChangeSuccess` | POST med korrekt gammelt + nytt passord → oppdatert |
|
|
| 7 | `TestPasswordChangeMismatch` | Nytt passord ≠ bekreftelse → feilmelding |
|
|
| 8 | `TestLogout` | POST `/logout` → session slettet, redirect til login |
|
|
|
|
### Handler: Favoritter CRUD (web) (`internal/handler/fave.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestCreateFavePage` | GET `/faves/new` → skjema rendres |
|
|
| 2 | `TestCreateFaveSubmit` | POST med gyldig data → redirect til favoritt |
|
|
| 3 | `TestCreateFaveWithImage` | POST med multipart/bilde → bilde lagret |
|
|
| 4 | `TestEditFavePage` | GET `/faves/{id}/edit` → skjema med eksisterende data |
|
|
| 5 | `TestEditFaveSubmit` | POST med endringer → oppdatert |
|
|
| 6 | `TestEditFaveNotOwner` | Annen bruker → 403 |
|
|
| 7 | `TestDeleteFave` | POST `/faves/{id}/delete` → slettet, redirect |
|
|
| 8 | `TestDeleteFaveNotOwner` | Annen bruker → 403 |
|
|
| 9 | `TestFaveListPagination` | Navigasjon med page-parameter |
|
|
|
|
### Handler: Administrasjon (`internal/handler/admin.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestAdminDashboard` | GET `/admin` → statistikk rendres |
|
|
| 2 | `TestAdminUserList` | GET `/admin/users` → alle brukere vises |
|
|
| 3 | `TestAdminDisableUser` | POST → bruker deaktiveres |
|
|
| 4 | `TestAdminEnableUser` | POST → bruker reaktiveres |
|
|
| 5 | `TestAdminApproveSignup` | POST → bruker opprettes, forespørsel fjernes |
|
|
| 6 | `TestAdminRejectSignup` | POST → forespørsel fjernes, bruker opprettes ikke |
|
|
| 7 | `TestAdminUpdateSettings` | POST → innstillinger oppdateres |
|
|
|
|
### Handler: Profil (`internal/handler/profile.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestPublicProfileVisible` | Offentlig profil → bio, visningsnavn vist |
|
|
| 2 | `TestLimitedProfileHidesBio` | Begrenset profil → bio skjult, merknad vist |
|
|
| 3 | `TestProfileEditPage` | GET `/profile/edit` → skjema med gjeldende verdier |
|
|
| 4 | `TestProfileUpdateDisplayName` | POST → visningsnavn oppdatert |
|
|
| 5 | `TestProfileUpdateVisibility` | POST → synlighet endret |
|
|
| 6 | `TestProfileAvatarUpload` | POST med bilde → avatar lagret |
|
|
|
|
### Handler: Feed (`internal/handler/feed.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestGlobalFeedAtom` | GET `/feed` → gyldig Atom XML |
|
|
| 2 | `TestUserFeedAtom` | GET `/{username}/feed` → kun brukerens offentlige |
|
|
| 3 | `TestFeedExcludesPrivate` | Private favoritter utelates |
|
|
| 4 | `TestFeedLinksUseExternalURL` | Lenker bruker `EXTERNAL_URL`, ikke localhost |
|
|
|
|
### Handler: Import/Eksport (web) (`internal/handler/import_export.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestExportPageRendering` | GET `/export` → eksportvalg vist |
|
|
| 2 | `TestExportJSON` | GET `/export/json` → JSON-array med alle faves |
|
|
| 3 | `TestExportCSV` | GET `/export/csv` → gyldig CSV med header |
|
|
| 4 | `TestImportJSON` | POST med JSON-fil → favoritter importert |
|
|
| 5 | `TestImportCSV` | POST med CSV-fil → favoritter importert |
|
|
| 6 | `TestImportDuplicateHandling` | Duplikater → håndteres uten feil |
|
|
|
|
---
|
|
|
|
## P2 — Konfigurasjon, bilde, database
|
|
|
|
### Konfigurasjon (`internal/config/config.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestLoadDefaults` | Ingen env-variabler → fornuftige standardverdier |
|
|
| 2 | `TestLoadFromEnv` | Alle env-variabler satt → config inneholder riktige verdier |
|
|
| 3 | `TestTrustedProxiesParsing` | `TRUSTED_PROXIES=10.0.0.0/8,192.168.0.0/16` → korrekte IPNet |
|
|
| 4 | `TestTrustedProxiesInvalid` | Ugyldig CIDR → logges, hoppes over |
|
|
| 5 | `TestBasePathNormalization` | Trailing slash fjernes, tom streng beholdes |
|
|
| 6 | `TestSessionLifetimeParsing` | `SESSION_LIFETIME=48h` → korrekt Duration |
|
|
| 7 | `TestDevModeFlag` | `FAVORITTER_DEV_MODE=true` → DevMode = true |
|
|
| 8 | `TestMaxUploadSizeParsing` | `MAX_UPLOAD_SIZE=10485760` → korrekt int64 |
|
|
|
|
### Bildebehandling (`internal/image/image.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestProcessJPEG` | Gyldig JPEG → UUID-filnavn, lagret i uploadDir |
|
|
| 2 | `TestProcessPNG` | Gyldig PNG → re-encoded, EXIF strippet |
|
|
| 3 | `TestProcessResizeWideImage` | Bilde > 1920px bredt → nedskalert til MaxWidth |
|
|
| 4 | `TestProcessSmallImageNotResized` | Bilde < 1920px → beholdes som det er |
|
|
| 5 | `TestProcessInvalidMIME` | `text/plain`-fil → feil returneres |
|
|
| 6 | `TestProcessCorruptImage` | Korrupt bildedata → feil returneres |
|
|
| 7 | `TestProcessUUIDFilename` | Filnavn bruker UUID, aldri brukerens opprinnelige filnavn |
|
|
| 8 | `TestAllowedTypes` | Sjekk at JPEG, PNG, GIF, WebP er tillatt |
|
|
|
|
### Databasemigrasjoner (`internal/database/database.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestOpenInMemory` | `:memory:` → fungerende tilkobling |
|
|
| 2 | `TestMigrateCreatesAllTables` | Migrasjon → alle forventede tabeller finnes |
|
|
| 3 | `TestMigrateIdempotent` | Kjør Migrate to ganger → ingen feil |
|
|
| 4 | `TestPRAGMAs` | WAL-modus, foreign_keys, journal_size_limit satt |
|
|
| 5 | `TestSingleConnection` | MaxOpenConns = 1 verifisert |
|
|
|
|
### Mellomvare: Context-hjelpere (`internal/middleware/context.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestUserFromContextPresent` | Bruker i context → returneres |
|
|
| 2 | `TestUserFromContextAbsent` | Ingen bruker → nil |
|
|
| 3 | `TestCSRFTokenFromContext` | Token i context → returneres |
|
|
| 4 | `TestFlashFromContext` | Flash-melding i context → returneres |
|
|
|
|
### Mellomvare: Logger (`internal/middleware/logger.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestLoggerRecordsStatusCode` | Response status kodes logges |
|
|
| 2 | `TestLoggerRecordsDuration` | Forespørselstid logges |
|
|
| 3 | `TestLoggerIncludesPath` | URL-path inkluderes i loggoppføring |
|
|
|
|
---
|
|
|
|
## P3 — Rendering og hjelpefunksjoner
|
|
|
|
### Template-rendering (`internal/render/render.go`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestRenderPage` | Rendrer side med layout → komplett HTML |
|
|
| 2 | `TestRenderPageWithData` | PageData (Title, brukerinfo) → interpolert i template |
|
|
| 3 | `TestRenderPartial` | Rendrer partial uten layout |
|
|
| 4 | `TestRenderMissingTemplate` | Ukjent template-navn → feilhåndtering |
|
|
| 5 | `TestCSRFTokenInTemplate` | CSRF-token tilgjengelig i template-context |
|
|
|
|
### API JSON-hjelpere (`internal/handler/api/`)
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestJsonOKFormat` | Content-Type: application/json, gyldig JSON |
|
|
| 2 | `TestJsonErrorFormat` | Feil → `{"error": "melding"}` + riktig statuskode |
|
|
| 3 | `TestUserJSONPublicProfile` | Offentlig profil → bio og avatar inkludert |
|
|
| 4 | `TestUserJSONLimitedProfile` | Begrenset profil → bio og avatar utelatt |
|
|
| 5 | `TestFaveJSONComplete` | Alle felter mappet korrekt |
|
|
| 6 | `TestQueryIntFallback` | Ugyldig/manglende parameter → standardverdi |
|
|
| 7 | `TestQueryIntNegative` | Negativ verdi → standardverdi |
|
|
|
|
---
|
|
|
|
## Integrasjonstester (tverrgående)
|
|
|
|
Disse testene verifiserer hele flyten fra HTTP-forespørsel gjennom mellomvare, handler, store og tilbake.
|
|
|
|
| # | Test | Verifiserer |
|
|
|---|------|-------------|
|
|
| 1 | `TestFullLoginFlow` | GET login → POST credentials → session cookie → GET /faves → 200 |
|
|
| 2 | `TestFullSignupApprovalFlow` | Registrering → admin godkjenner → bruker logger inn → endrer passord |
|
|
| 3 | `TestFullFaveCRUDFlow` | Opprett → les → rediger → slett favoritt via web |
|
|
| 4 | `TestFullAPIFaveCRUDFlow` | Login → opprett → hent → oppdater → slett via JSON API |
|
|
| 5 | `TestImportExportRoundtrip` | Eksporter → importer til ny bruker → verifiser likhet |
|
|
| 6 | `TestFeedReflectsNewFaves` | Opprett favoritt → feed oppdateres |
|
|
| 7 | `TestRateLimitOnLogin` | Mange mislykkede pålogginger → 429 |
|
|
| 8 | `TestCSRFProtectionEndToEnd` | Hent side → ekstraher token → POST med token → suksess |
|
|
| 9 | `TestBasePathPropagation` | Alle lenker og redirects respekterer base path |
|
|
| 10 | `TestMultiUserPrivacy` | Bruker A ser ikke bruker Bs private favoritter i noen visning |
|
|
|
|
---
|
|
|
|
## Testinfrastruktur
|
|
|
|
### Eksisterende hjelpere (gjenbruk)
|
|
|
|
- `testDB(t)` — in-memory SQLite med migrasjoner (`store/*_test.go`)
|
|
- `testServer(t)` — komplett handler-stack med mellomvare (`handler/handler_test.go`)
|
|
- `loginUser(t, h, username, password, role)` — oppretter bruker og returnerer session-cookie
|
|
- `extractCookie(rr, name)` — henter cookie fra response
|
|
|
|
### Nye hjelpere som trengs
|
|
|
|
| Hjelper | Bruksområde |
|
|
|---------|-------------|
|
|
| `testAPIServer(t)` | Setup for API-handler med in-memory DB |
|
|
| `apiLogin(t, server, username, password)` | Hent session-token for API-tester |
|
|
| `testImage(t, width, height, mime)` | Generer test-bilde med gitte dimensjoner |
|
|
| `setEnv(t, key, value)` | Sett env-variabel med automatisk cleanup |
|
|
|
|
### Konvensjoner
|
|
|
|
- Bruk `:memory:` SQLite for alle tester
|
|
- Sett raske Argon2-parametre (`Memory=1024, Time=1`) i alle passord-tester
|
|
- Bruk `t.Helper()` på alle hjelpefunksjoner
|
|
- Bruk `t.Cleanup()` for opprydding, aldri manuell defer i hjelpere
|
|
- Bruk `httptest.NewRecorder()` og `httptest.NewRequest()` for HTTP-tester
|
|
- Bruk `t.TempDir()` for bildebehandlingstester
|
|
- Tabell-drevne tester der det er naturlig (f.eks. config-parsing, feilkoder)
|
|
- Norske testbeskrivelser i kommentarer, engelske funksjons-/variabelnavn
|
|
|
|
---
|
|
|
|
## Implementeringsrekkefølge
|
|
|
|
```
|
|
Fase 1 (P0): Sikkerhet
|
|
├── middleware/csrf_test.go (~7 tester)
|
|
├── middleware/auth_test.go (~7 tester) ← utvid eksisterende fil
|
|
└── handler/api/api_test.go (~5 auth-tester)
|
|
|
|
Fase 2 (P1a): Store + API-kontrakter
|
|
├── store/settings_test.go (~3 tester)
|
|
└── handler/api/api_test.go (~25 tester, utvid)
|
|
|
|
Fase 3 (P1b): Web-handlere
|
|
├── handler/handler_test.go (~30 tester, utvid eksisterende)
|
|
└── handler/auth_test.go (~8 tester)
|
|
|
|
Fase 4 (P2): Konfig, bilde, database
|
|
├── config/config_test.go (~8 tester)
|
|
├── image/image_test.go (~8 tester)
|
|
├── database/database_test.go (~5 tester)
|
|
└── middleware/context_test.go (~4 tester)
|
|
|
|
Fase 5 (P3): Rendering og hjelpere
|
|
├── render/render_test.go (~5 tester)
|
|
└── handler/api/helpers_test.go (~7 tester)
|
|
|
|
Fase 6: Integrasjonstester
|
|
└── integration_test.go (~10 tester, build tag)
|
|
```
|
|
|
|
**Totalt**: ~132 nye tester → fra 44 til ~176 testfunksjoner.
|
|
|
|
---
|
|
|
|
## Kjøring
|
|
|
|
```bash
|
|
# Alle tester
|
|
go test ./...
|
|
|
|
# Én pakke
|
|
go test ./internal/store/...
|
|
|
|
# Med dekning
|
|
go test -cover ./...
|
|
|
|
# Detaljert dekningsrapport
|
|
go test -coverprofile=coverage.out ./... && go tool cover -html=coverage.out
|
|
|
|
# Kun integrasjonstester (om build tag brukes)
|
|
go test -tags=integration ./...
|
|
```
|