Files
vikunja/pkg/caldavtests/xml_helpers.go
kolaente ef85a22f99 fix(caldav): resolve lint issues in caldavtests package
- Remove unused helper functions (findResponse, assertMultistatusHasResponses, caldavRequestAsUser)
- Fix gofmt formatting
- Convert WriteString(fmt.Sprintf(...)) to fmt.Fprintf
- Fix unused parameter warnings
- Fix testifylint suggestions (assert.NotEmpty, assert.Positive)
- Add nolint:unparam for assertResponseStatus
2026-04-02 11:34:55 +00:00

140 lines
4.7 KiB
Go

// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package caldavtests
import (
"encoding/xml"
"net/http/httptest"
"strings"
"testing"
ics "github.com/arran4/golang-ical"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Multistatus represents a WebDAV multistatus response (RFC 4918 §13)
type Multistatus struct {
XMLName xml.Name `xml:"DAV: multistatus"`
Responses []Response `xml:"response"`
}
// Response represents a single response within a multistatus
type Response struct {
Href string `xml:"href"`
Propstat []Propstat `xml:"propstat"`
}
// Propstat groups a set of properties with a status
type Propstat struct {
Prop Prop `xml:"prop"`
Status string `xml:"status"`
}
// Prop holds the actual property values returned by PROPFIND/REPORT.
type Prop struct {
// Standard DAV properties
DisplayName string `xml:"displayname,omitempty"`
ResourceType RawXML `xml:"resourcetype,omitempty"`
GetETag string `xml:"getetag,omitempty"`
GetCTag string `xml:"http://calendarserver.org/ns/ getctag,omitempty"`
// CalDAV properties
CalendarData string `xml:"urn:ietf:params:xml:ns:caldav calendar-data,omitempty"`
CalendarHomeSet RawXML `xml:"urn:ietf:params:xml:ns:caldav calendar-home-set,omitempty"`
SupportedComponents RawXML `xml:"urn:ietf:params:xml:ns:caldav supported-calendar-component-set,omitempty"`
CalendarDescription string `xml:"urn:ietf:params:xml:ns:caldav calendar-description,omitempty"`
// Principal properties
CurrentUserPrincipal RawXML `xml:"current-user-principal,omitempty"`
// ACL properties
CurrentUserPrivilegeSet RawXML `xml:"current-user-privilege-set,omitempty"`
// Catch-all for unexpected properties
InnerXML string `xml:",innerxml"`
}
// RawXML captures raw XML content for properties we want to inspect flexibly
type RawXML struct {
InnerXML string `xml:",innerxml"`
}
// parseMultistatus parses a WebDAV multistatus XML response body.
func parseMultistatus(t *testing.T, rec *httptest.ResponseRecorder) Multistatus {
t.Helper()
var ms Multistatus
err := xml.Unmarshal(rec.Body.Bytes(), &ms)
require.NoError(t, err, "Failed to parse multistatus XML. Body:\n%s", rec.Body.String())
return ms
}
// getSuccessfulProp returns the Prop from the first propstat with a 200 status.
func getSuccessfulProp(t *testing.T, r Response) Prop {
t.Helper()
for _, ps := range r.Propstat {
if strings.Contains(ps.Status, "200") {
return ps.Prop
}
}
t.Fatalf("No successful (200) propstat found in response for href %s", r.Href)
return Prop{} // unreachable
}
// parseICalFromResponse parses iCalendar data from a response body.
func parseICalFromResponse(t *testing.T, rec *httptest.ResponseRecorder) *ics.Calendar {
t.Helper()
cal, err := ics.ParseCalendar(strings.NewReader(rec.Body.String()))
require.NoError(t, err, "Failed to parse iCalendar. Body:\n%s", rec.Body.String())
return cal
}
// parseICalFromString parses iCalendar data from a string (e.g., calendar-data property).
func parseICalFromString(t *testing.T, data string) *ics.Calendar {
t.Helper()
cal, err := ics.ParseCalendar(strings.NewReader(data))
require.NoError(t, err, "Failed to parse iCalendar data:\n%s", data)
return cal
}
// getVTodo extracts the first VTODO component from a calendar.
func getVTodo(t *testing.T, cal *ics.Calendar) *ics.VTodo {
t.Helper()
for _, comp := range cal.Components {
if vtodo, ok := comp.(*ics.VTodo); ok {
return vtodo
}
}
t.Fatal("No VTODO component found in calendar")
return nil // unreachable
}
// getVTodoProperty extracts a property value from a VTODO.
func getVTodoProperty(vtodo *ics.VTodo, prop ics.ComponentProperty) string {
p := vtodo.GetProperty(prop)
if p == nil {
return ""
}
return p.Value
}
// assertResponseStatus asserts the HTTP status code.
func assertResponseStatus(t *testing.T, rec *httptest.ResponseRecorder, expectedStatus int) { //nolint:unparam
t.Helper()
assert.Equal(t, expectedStatus, rec.Code, "Response body:\n%s", rec.Body.String())
}