favoritter/TESTPLAN.md
Ole-Morten Duesund a8f3aa6f7e test: add comprehensive test suite (44 → 169 tests) and v1.1 plan
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>
2026-04-04 00:18:01 +02:00

17 KiB

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

# 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 ./...