package main import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" ) func testServer(t *testing.T) *server { t.Helper() return &server{ accountsPath: "testdata/accounts.cf", quotaPath: "testdata/quotas.cf", maildirRoot: "testdata/mail", basePath: "/admin", user: "bot", pass: "s3cret", } } func doAuth(t *testing.T, h http.Handler, path, user, pass string) *httptest.ResponseRecorder { t.Helper() req := httptest.NewRequest(http.MethodGet, path, nil) if user != "" { req.SetBasicAuth(user, pass) } rec := httptest.NewRecorder() h.ServeHTTP(rec, req) return rec } func TestBasicAuth(t *testing.T) { h := testServer(t).handler() if rec := doAuth(t, h, "/admin/", "", ""); rec.Code != http.StatusUnauthorized { t.Errorf("no creds: code = %d, want 401", rec.Code) } if rec := doAuth(t, h, "/admin/", "bot", "wrong"); rec.Code != http.StatusUnauthorized { t.Errorf("wrong pass: code = %d, want 401", rec.Code) } if rec := doAuth(t, h, "/admin/", "bot", "s3cret"); rec.Code != http.StatusOK { t.Errorf("right creds: code = %d, want 200", rec.Code) } } func TestBasePathRedirect(t *testing.T) { h := testServer(t).handler() rec := doAuth(t, h, "/", "bot", "s3cret") if rec.Code != http.StatusFound { t.Fatalf("code = %d, want 302", rec.Code) } if loc := rec.Header().Get("Location"); loc != "/admin/" { t.Errorf("Location = %q, want /admin/", loc) } } func TestNotFoundOutsideBasePath(t *testing.T) { h := testServer(t).handler() rec := doAuth(t, h, "/other", "bot", "s3cret") if rec.Code != http.StatusNotFound { t.Errorf("code = %d, want 404", rec.Code) } } func TestAPIAccounts(t *testing.T) { h := testServer(t).handler() rec := doAuth(t, h, "/admin/api/accounts", "bot", "s3cret") if rec.Code != http.StatusOK { t.Fatalf("code = %d, want 200: %s", rec.Code, rec.Body.String()) } var resp accountsResponse if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { t.Fatal(err) } if len(resp.Accounts) != 5 { t.Fatalf("got %d accounts, want 5", len(resp.Accounts)) } byEmail := map[string]viewAccount{} for _, a := range resp.Accounts { byEmail[a.Email] = a } info, ok := byEmail["info@produktor.io"] if !ok { t.Fatal("info@produktor.io missing") } if info.Messages != 3 { t.Errorf("info Messages = %d, want 3 (fixture)", info.Messages) } if info.Total != 4 { t.Errorf("info Total = %d, want 4 (incl. .Sent)", info.Total) } if info.Quota != "500M" { t.Errorf("info Quota = %q, want 500M", info.Quota) } if byEmail["postman@produktor.io"].Messages != 0 { t.Errorf("postman Messages = %d, want 0", byEmail["postman@produktor.io"].Messages) } if byEmail["andriy.oblivantsev@produktor.io"].Messages != 0 { t.Errorf("andriy Messages = %d, want 0 (no maildir)", byEmail["andriy.oblivantsev@produktor.io"].Messages) } if byEmail["postmaster@produktor.io"].Messages != 1 { t.Errorf("postmaster Messages = %d, want 1", byEmail["postmaster@produktor.io"].Messages) } } func TestIndexPageRenders(t *testing.T) { h := testServer(t).handler() rec := doAuth(t, h, "/admin/", "bot", "s3cret") body := rec.Body.String() if !strings.Contains(body, "info@produktor.io") { t.Error("page does not list info@produktor.io") } if !strings.Contains(body, "Mail accounts") { t.Error("page title missing") } }