package test import ( "encoding/json" "net/http" "os" "testing" ) type inviteEmailCase struct { Email string `json:"email"` Valid bool `json:"valid"` } func loadInviteEmailCases(t *testing.T) []inviteEmailCase { t.Helper() raw, err := os.ReadFile("testdata/invite_emails.json") if err != nil { t.Fatalf("read fixture: %v", err) } var cases []inviteEmailCase if err := json.Unmarshal(raw, &cases); err != nil { t.Fatalf("decode fixture: %v", err) } return cases } func TestInviteEmailValidationHttp(t *testing.T) { t.Run("The same address gets the same verdict on both sides", func(t *testing.T) { for _, tc := range loadInviteEmailCases(t) { t.Run("["+tc.Email+"]", func(t *testing.T) { f := newInviteFixture(t, 100) body, _ := json.Marshal(map[string]string{"email": tc.Email}) rec := f.post(t, string(body)) if tc.Valid && rec.Code != http.StatusCreated { t.Errorf("expected 201, got %d: %s", rec.Code, rec.Body.String()) } if !tc.Valid && rec.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d: %s", rec.Code, rec.Body.String()) } }) } }) t.Run("A rejected address stores nothing and sends nothing", func(t *testing.T) { f := newInviteFixture(t, 100) rec := f.post(t, `{"email": "user@localhost"}`) if rec.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d", rec.Code) } if len(f.invites.invites) != 0 || len(f.mail.SentEmails) != 0 { t.Errorf("nothing may be stored or sent, got %d invites and %d emails", len(f.invites.invites), len(f.mail.SentEmails)) } }) }