package calendar import ( "strings" "testing" "github.com/google/uuid" ) const propfindHead = ` ` func TestParsePropfindTrenntUnsereEigenschaftenAb(t *testing.T) { body := []byte(propfindHead + ``) want, rewritten := parsePropfind(body) if !want.ctag || !want.color { t.Fatalf("beide Eigenschaften sollten erkannt werden, bekam %+v", want) } out := string(rewritten) if !strings.Contains(out, "") { t.Errorf("die übrigen Eigenschaften müssen erhalten bleiben: %s", out) } // Der Kern: go-webdav darf sie nicht zu sehen bekommen, sonst meldet es // sie als 404 und dieselbe Eigenschaft stünde zweimal in der Antwort. if strings.Contains(out, "getctag") || strings.Contains(out, "calendar-color") { t.Errorf("unsere Eigenschaften müssen entfernt sein: %s", out) } } func TestParsePropfindLaesstFremdeAnfragenInRuhe(t *testing.T) { body := []byte(propfindHead + ``) want, rewritten := parsePropfind(body) if want.any() { t.Errorf("nichts von uns gefragt, trotzdem %+v", want) } if string(rewritten) != string(body) { t.Errorf("Rumpf muss unverändert durchgereicht werden") } } func TestParsePropfindNurUnsereEigenschaftHinterlaesstKeinLeeresProp(t *testing.T) { // Ein leeres weist go-webdav ab – dann käme auf eine gültige // Anfrage ein Fehler statt einer Antwort. body := []byte(propfindHead + ``) _, rewritten := parsePropfind(body) if !strings.Contains(string(rewritten), "") { t.Errorf("Platzhalter fehlt: %s", rewritten) } } func TestParsePropfindAllpropUndLeererRumpf(t *testing.T) { for _, tc := range []struct { name string body []byte }{ {"allprop", []byte(propfindHead + ``)}, {"leerer Rumpf", nil}, // RFC 4918, 9.1: leer bedeutet allprop } { want, rewritten := parsePropfind(tc.body) if !want.ctag || !want.color { t.Errorf("%s: sollte alles liefern, bekam %+v", tc.name, want) } if string(rewritten) != string(tc.body) { t.Errorf("%s: Rumpf darf nicht umgebaut werden", tc.name) } } } func TestCalendarOfResponseTrifftNurKalender(t *testing.T) { id := uuid.New() cal := &Calendar{ID: id, Color: "#a142f4", CTag: 7} // Ein Kalender unter seiner UUID, einer unter einer vom Client // gewählten Adresse – beide müssen gefunden werden. eigen := &Calendar{ID: uuid.New(), PathSegment: "arbeit", Color: "#34a853"} byRef := map[string]*Calendar{id.String(): cal, "arbeit": eigen} tests := []struct { name string href string will *Calendar }{ {"Kalender", "/caldav/calendars/max/" + id.String() + "/", cal}, {"Home-Set", "/caldav/calendars/max/", nil}, {"Principal", "/caldav/principals-max/", nil}, {"einzelner Termin", "/caldav/calendars/max/" + id.String() + "/abc.ics", nil}, {"fremder Kalender", "/caldav/calendars/max/" + uuid.New().String() + "/", nil}, {"selbst gewählte Adresse", "/caldav/calendars/max/arbeit/", eigen}, {"Termin darin", "/caldav/calendars/max/arbeit/abc.ics", nil}, } for _, tc := range tests { part := `` + tc.href + `` if got := calendarOfResponse(part, byRef); got != tc.will { t.Errorf("%s: bekam %v, erwartet %v", tc.name, got, tc.will) } } } func TestExtrasPropstat(t *testing.T) { cal := &Calendar{Color: "#a142f4", CTag: 12} got := extrasPropstat(cal, wantedExtras{ctag: true, color: true}) if !strings.Contains(got, ">12") { t.Errorf("ctag fehlt: %s", got) } // Apple-Clients und DAVx5 erwarten den Alpha-Anteil. if !strings.Contains(got, ">#A142F4FF") { t.Errorf("Farbe nicht in Apple-Schreibweise: %s", got) } if !strings.Contains(got, "HTTP/1.1 200 OK") { t.Errorf("Status fehlt: %s", got) } // Ohne Farbe bleibt die Eigenschaft weg – lieber gar nicht melden als // leer, sonst färbt der Client den Kalender schwarz. if got := extrasPropstat(&Calendar{CTag: 1}, wantedExtras{color: true}); got != "" { t.Errorf("ohne Farbe sollte nichts entstehen, bekam %s", got) } }