hsa-app/internal/web/web_test.go

129 lines
3.4 KiB
Go
Raw Permalink Normal View History

package web
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"maisym.com/hsa/internal/auth"
"maisym.com/hsa/internal/config"
)
func testServer() *Server {
var key [32]byte
copy(key[:], "web-test-key-32-bytes-padded!!!!")
return &Server{cfg: config.Config{
SessionKey: key,
RequiredGroup: "hsa-users",
SecureCookies: false,
}}
}
func TestStaticCSS(t *testing.T) {
s := testServer()
req := httptest.NewRequest(http.MethodGet, "/static/style.css", nil)
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
if !strings.Contains(rec.Body.String(), "font-family") {
t.Errorf("CSS not served: %q", rec.Body.String())
}
}
func TestHealthz(t *testing.T) {
s := testServer()
req := httptest.NewRequest(http.MethodGet, "/healthz", nil)
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
if !strings.Contains(rec.Body.String(), "ok") {
t.Errorf("body = %q, want to contain ok", rec.Body.String())
}
}
func TestHome_NoSession_RedirectsToLogin(t *testing.T) {
s := testServer()
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusFound {
t.Fatalf("status = %d, want 302", rec.Code)
}
if loc := rec.Header().Get("Location"); loc != "/login" {
t.Errorf("Location = %q, want /login", loc)
}
}
func TestHome_ValidSession_ShowsUploadForm(t *testing.T) {
s := testServerWithStore(t)
sess := auth.Session{Subject: "jm@example.com", Groups: []string{"hsa-users"}}
cookie, err := auth.EncodeSession(sess, s.cfg.SessionKey)
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest(http.MethodGet, "/", nil)
req.AddCookie(&http.Cookie{Name: sessionCookie, Value: cookie})
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
body := rec.Body.String()
if !strings.Contains(body, "jm@example.com") {
t.Errorf("body missing subject: %q", body)
}
if !strings.Contains(body, "Add receipt") {
t.Errorf("body missing upload form: %q", body)
}
}
func TestHome_TamperedSession_RedirectsToLogin(t *testing.T) {
s := testServer()
sess := auth.Session{Subject: "jm@example.com", Groups: []string{"hsa-users"}}
cookie, _ := auth.EncodeSession(sess, s.cfg.SessionKey)
tampered := cookie[:len(cookie)-3] + "AAA"
req := httptest.NewRequest(http.MethodGet, "/", nil)
req.AddCookie(&http.Cookie{Name: sessionCookie, Value: tampered})
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusFound {
t.Fatalf("status = %d, want 302", rec.Code)
}
if loc := rec.Header().Get("Location"); loc != "/login" {
t.Errorf("Location = %q, want /login", loc)
}
}
func TestLogout_ClearsCookieAndRedirects(t *testing.T) {
s := testServer()
req := httptest.NewRequest(http.MethodGet, "/logout", nil)
rec := httptest.NewRecorder()
s.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusFound {
t.Fatalf("status = %d, want 302", rec.Code)
}
// The session cookie should be expired (MaxAge < 0).
var cleared bool
for _, c := range rec.Result().Cookies() {
if c.Name == sessionCookie && c.MaxAge < 0 {
cleared = true
}
}
if !cleared {
t.Error("logout did not clear the session cookie")
}
}