package dav import ( "context" "net/http" "net/http/httptest" "strings" "testing" ) func TestProbeOptions_parsesHeaders(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodOptions { t.Fatalf("expected OPTIONS, got %s", r.Method) } w.Header().Set("DAV", "1, 2, calendar-access, calendar-schedule") w.Header().Set("Allow", "OPTIONS, PROPFIND, REPORT, PUT") w.Header().Set("Server", "TestSrv/1.0") w.Header().Add("WWW-Authenticate", `Basic realm="test"`) w.Header().Add("WWW-Authenticate", `Digest realm="test", nonce="abc"`) w.WriteHeader(http.StatusOK) })) t.Cleanup(srv.Close) res, err := ProbeOptions(context.Background(), srv.Client(), srv.URL) if err != nil { t.Fatalf("ProbeOptions: %v", err) } if !res.HasCapability("calendar-access") { t.Errorf("expected calendar-access in %v", res.DAVClasses) } if !res.HasCapability("CALENDAR-SCHEDULE") { t.Errorf("case-insensitive match failed for calendar-schedule") } if !res.AllowsMethod("REPORT") || !res.AllowsMethod("PROPFIND") { t.Errorf("expected REPORT and PROPFIND in %v", res.AllowMethods) } if len(res.AuthSchemes) != 2 { t.Errorf("expected 2 auth schemes, got %v", res.AuthSchemes) } if res.Server != "TestSrv/1.0" { t.Errorf("Server header: %q", res.Server) } } func TestProbeOptions_missingDAVHeader(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) t.Cleanup(srv.Close) res, err := ProbeOptions(context.Background(), srv.Client(), srv.URL) if err != nil { t.Fatalf("unexpected transport error: %v", err) } if res.HasCapability("calendar-access") { t.Error("expected capability absent") } if len(res.DAVClasses) != 0 { t.Errorf("expected empty DAV classes, got %v", res.DAVClasses) } } func TestProbeOptions_errorStatus(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusServiceUnavailable) })) t.Cleanup(srv.Close) res, err := ProbeOptions(context.Background(), srv.Client(), srv.URL) if err != nil { t.Fatalf("transport err: %v", err) } if res.StatusCode != 503 { t.Errorf("status: %d", res.StatusCode) } if res.Error == "" { t.Error("expected Error to be set for 503") } } func TestParseCSVHeader_mergeAndTrim(t *testing.T) { got := parseCSVHeader([]string{"1, 2 ,calendar-access", " calendar-schedule"}) want := []string{"1", "2", "calendar-access", "calendar-schedule"} if !equalSlices(got, want) { t.Errorf("got %v want %v", got, want) } } func TestAuthScheme(t *testing.T) { cases := map[string]string{ `Basic realm="x"`: "Basic", "Bearer": "Bearer", `Digest realm="r", nonce="n"`: "Digest", "": "", " ": "", } for in, want := range cases { if got := authScheme(in); got != want { t.Errorf("authScheme(%q) = %q, want %q", in, got, want) } } } func equalSlices(a, b []string) bool { if len(a) != len(b) { return false } for i := range a { if !strings.EqualFold(a[i], b[i]) { return false } } return true }