package mailu import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "strings" "testing" ) func TestConfigured(t *testing.T) { if New(Config{BaseURL: "http://x"}).Configured() { t.Fatal("no token should be unconfigured") } if !New(Config{BaseURL: "http://x", Token: "tok"}).Configured() { t.Fatal("token should be configured") } var nilc *Client if nilc.Configured() { t.Fatal("nil client must be unconfigured") } } func TestEnsureUserCreatesWhenMissing(t *testing.T) { var created map[string]any var sawToken string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sawToken = r.Header.Get("Authorization") switch { case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/v1/user/"): w.WriteHeader(http.StatusNotFound) case r.Method == http.MethodPost && r.URL.Path == "/api/v1/user": b, _ := io.ReadAll(r.Body) _ = json.Unmarshal(b, &created) w.WriteHeader(http.StatusOK) default: t.Errorf("unexpected %s %s", r.Method, r.URL.Path) } })) defer srv.Close() c := New(Config{BaseURL: srv.URL, Token: "secret-tok"}) if err := c.EnsureUser(context.Background(), "alice", "bbs.profullstack.com"); err != nil { t.Fatal(err) } if sawToken != "secret-tok" { t.Fatalf("token header = %q", sawToken) } if created["email"] != "alice@bbs.profullstack.com" { t.Fatalf("created email = %v", created["email"]) } if created["raw_password"] == nil || created["raw_password"] == "" { t.Fatal("expected a generated password") } } func TestEnsureUserIdempotentWhenExists(t *testing.T) { posted := false srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { w.WriteHeader(http.StatusOK) return } posted = true w.WriteHeader(http.StatusOK) })) defer srv.Close() c := New(Config{BaseURL: srv.URL, Token: "t"}) if err := c.EnsureUser(context.Background(), "bob", "bbs.profullstack.com"); err != nil { t.Fatal(err) } if posted { t.Fatal("should not POST when the mailbox already exists") } } func TestEnsureUserConflictIsSuccess(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { w.WriteHeader(http.StatusNotFound) return } w.WriteHeader(http.StatusConflict) _, _ = io.WriteString(w, `{"message":"already exists"}`) })) defer srv.Close() c := New(Config{BaseURL: srv.URL, Token: "t"}) if err := c.EnsureUser(context.Background(), "carol", "bbs.profullstack.com"); err != nil { t.Fatalf("conflict should be treated as success, got %v", err) } } func TestEnsureUserUnconfigured(t *testing.T) { if err := New(Config{}).EnsureUser(context.Background(), "x", "y"); err == nil { t.Fatal("expected error when unconfigured") } } func TestSetPassword(t *testing.T) { var method, path string var body map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { method, path = r.Method, r.URL.Path b, _ := io.ReadAll(r.Body) _ = json.Unmarshal(b, &body) w.WriteHeader(http.StatusOK) })) defer srv.Close() c := New(Config{BaseURL: srv.URL, Token: "t"}) if err := c.SetPassword(context.Background(), "alice", "bbs.profullstack.com", "hunter2"); err != nil { t.Fatal(err) } if method != http.MethodPatch || path != "/api/v1/user/alice@bbs.profullstack.com" { t.Fatalf("got %s %s", method, path) } if body["raw_password"] != "hunter2" { t.Fatalf("raw_password = %v", body["raw_password"]) } }