44 "context"
55 "fmt"
66 "io"
7- "io/ioutil "
7+ "net/http "
88 "net/http/httptest"
99 "strings"
1010 "testing"
@@ -33,12 +33,12 @@ func TestPropFindSupportedCalendarComponent(t *testing.T) {
3333 req .Body = io .NopCloser (strings .NewReader (propFindSupportedCalendarComponentRequest ))
3434 req .Header .Set ("Content-Type" , "application/xml" )
3535 w := httptest .NewRecorder ()
36- handler := Handler {Backend : testBackend {calendars : []Calendar {* calendar }}}
36+ handler := Handler {Backend : & testBackend {calendars : []Calendar {* calendar }}}
3737 handler .ServeHTTP (w , req )
3838
3939 res := w .Result ()
4040 defer res .Body .Close ()
41- data , err := ioutil .ReadAll (res .Body )
41+ data , err := io .ReadAll (res .Body )
4242 if err != nil {
4343 t .Error (err )
4444 }
@@ -68,12 +68,12 @@ func TestPropFindRoot(t *testing.T) {
6868 req .Header .Set ("Content-Type" , "application/xml" )
6969 w := httptest .NewRecorder ()
7070 calendar := & Calendar {}
71- handler := Handler {Backend : testBackend {calendars : []Calendar {* calendar }}}
71+ handler := Handler {Backend : & testBackend {calendars : []Calendar {* calendar }}}
7272 handler .ServeHTTP (w , req )
7373
7474 res := w .Result ()
7575 defer res .Body .Close ()
76- data , err := ioutil .ReadAll (res .Body )
76+ data , err := io .ReadAll (res .Body )
7777 if err != nil {
7878 t .Error (err )
7979 }
@@ -83,6 +83,108 @@ func TestPropFindRoot(t *testing.T) {
8383 }
8484}
8585
86+ const TestMkCalendarReq = `
87+ <?xml version="1.0" encoding="UTF-8"?>
88+ <B:mkcalendar xmlns:B="urn:ietf:params:xml:ns:caldav">
89+ <A:set xmlns:A="DAV:">
90+ <A:prop>
91+ <B:calendar-timezone>BEGIN:VCALENDAR
92+ VERSION:2.0
93+ PRODID:-//Apple Inc.//iPhone OS 18.1.1//EN
94+ CALSCALE:GREGORIAN
95+ BEGIN:VTIMEZONE
96+ TZID:Europe/Paris
97+ BEGIN:DAYLIGHT
98+ TZOFFSETFROM:+0100
99+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
100+ DTSTART:19810329T020000
101+ TZNAME:UTC+2
102+ TZOFFSETTO:+0200
103+ END:DAYLIGHT
104+ BEGIN:STANDARD
105+ TZOFFSETFROM:+0200
106+ RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
107+ DTSTART:19961027T030000
108+ TZNAME:UTC+1
109+ TZOFFSETTO:+0100
110+ END:STANDARD
111+ END:VTIMEZONE
112+ END:VCALENDAR
113+ </B:calendar-timezone>
114+ <D:calendar-order xmlns:D="http://apple.com/ns/ical/">2</D:calendar-order>
115+ <B:supported-calendar-component-set>
116+ <B:comp name="VEVENT"/>
117+ </B:supported-calendar-component-set>
118+ <D:calendar-color xmlns:D="http://apple.com/ns/ical/" symbolic-color="red">#FF2968</D:calendar-color>
119+ <A:displayname>test calendar</A:displayname>
120+ <B:calendar-free-busy-set>
121+ <NO/>
122+ </B:calendar-free-busy-set>
123+ </A:prop>
124+ </A:set>
125+ </B:mkcalendar>
126+ `
127+
128+ const propFindTest2 = `
129+ <d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
130+ <d:prop>
131+ <d:resourcetype/>
132+ <c:supported-calendar-component-set/>
133+ <d:displayname/>
134+ <c:max-resource-size/>
135+ <c:calendar-description/>
136+ </d:prop>
137+ </d:propfind>
138+ `
139+
140+ func TestMkCalendar (t * testing.T ) {
141+ handler := Handler {Backend : & testBackend {
142+ calendars : []Calendar {},
143+ objectMap : map [string ][]CalendarObject {},
144+ }}
145+
146+ req := httptest .NewRequest ("MKCALENDAR" , "/user/calendars/default/" , strings .NewReader (TestMkCalendarReq ))
147+ req .Header .Set ("Content-Type" , "application/xml" )
148+ w := httptest .NewRecorder ()
149+ handler .ServeHTTP (w , req )
150+
151+ res := w .Result ()
152+ if e := res .Body .Close (); e != nil {
153+ t .Fatal (e )
154+ } else if loc := res .Header .Get ("Location" ); loc != "/user/calendars/default/" {
155+ t .Fatalf ("unexpected location: %s" , loc )
156+ } else if sc := res .StatusCode ; sc != http .StatusCreated {
157+ t .Fatalf ("unexpected status code: %d" , sc )
158+ }
159+
160+ req = httptest .NewRequest ("PROPFIND" , "/user/calendars/default/" , strings .NewReader (propFindTest2 ))
161+ req .Header .Set ("Content-Type" , "application/xml" )
162+ req .Header .Set ("Depth" , "0" )
163+ w = httptest .NewRecorder ()
164+ handler .ServeHTTP (w , req )
165+
166+ res = w .Result ()
167+ defer res .Body .Close ()
168+ data , err := io .ReadAll (res .Body )
169+ if err != nil {
170+ t .Fatal (err )
171+ }
172+ resp := string (data )
173+ if ! strings .Contains (resp , fmt .Sprintf ("<href>%s</href>" , "/user/calendars/default/" )) {
174+ t .Fatalf ("want calendar href in response" )
175+ } else if ! strings .Contains (resp , "<resourcetype xmlns=\" DAV:\" >" ) {
176+ t .Fatalf ("want resource type in response" )
177+ } else if ! strings .Contains (resp , "<collection xmlns=\" DAV:\" ></collection>" ) {
178+ t .Fatalf ("want collection resource type in response" )
179+ } else if ! strings .Contains (resp , "<calendar xmlns=\" urn:ietf:params:xml:ns:caldav\" ></calendar>" ) {
180+ t .Fatalf ("want calendar resource type in response" )
181+ } else if ! strings .Contains (resp , "<displayname xmlns=\" DAV:\" >test calendar</displayname>" ) {
182+ t .Fatalf ("want display name in response" )
183+ } else if ! strings .Contains (resp , "<supported-calendar-component-set xmlns=\" urn:ietf:params:xml:ns:caldav\" ><comp xmlns=\" urn:ietf:params:xml:ns:caldav\" name=\" VEVENT\" ></comp></supported-calendar-component-set>" ) {
184+ t .Fatalf ("want supported-calendar-component-set in response" )
185+ }
186+ }
187+
86188var reportCalendarData = `
87189<?xml version="1.0" encoding="UTF-8"?>
88190<B:calendar-multiget xmlns:A="DAV:" xmlns:B="urn:ietf:params:xml:ns:caldav">
@@ -118,7 +220,7 @@ func TestMultiCalendarBackend(t *testing.T) {
118220 req := httptest .NewRequest ("PROPFIND" , "/user/calendars/" , strings .NewReader (propFindUserPrincipal ))
119221 req .Header .Set ("Content-Type" , "application/xml" )
120222 w := httptest .NewRecorder ()
121- handler := Handler {Backend : testBackend {
223+ handler := Handler {Backend : & testBackend {
122224 calendars : calendars ,
123225 objectMap : map [string ][]CalendarObject {
124226 calendarB .Path : []CalendarObject {object },
@@ -128,7 +230,7 @@ func TestMultiCalendarBackend(t *testing.T) {
128230
129231 res := w .Result ()
130232 defer res .Body .Close ()
131- data , err := ioutil .ReadAll (res .Body )
233+ data , err := io .ReadAll (res .Body )
132234 if err != nil {
133235 t .Error (err )
134236 }
@@ -147,7 +249,7 @@ func TestMultiCalendarBackend(t *testing.T) {
147249
148250 res = w .Result ()
149251 defer res .Body .Close ()
150- data , err = ioutil .ReadAll (res .Body )
252+ data , err = io .ReadAll (res .Body )
151253 if err != nil {
152254 t .Error (err )
153255 }
@@ -167,7 +269,7 @@ func TestMultiCalendarBackend(t *testing.T) {
167269
168270 res = w .Result ()
169271 defer res .Body .Close ()
170- data , err = ioutil .ReadAll (res .Body )
272+ data , err = io .ReadAll (res .Body )
171273 if err != nil {
172274 t .Error (err )
173275 }
@@ -182,8 +284,15 @@ type testBackend struct {
182284 objectMap map [string ][]CalendarObject
183285}
184286
185- func (t testBackend ) CreateCalendar (ctx context.Context , calendar * Calendar ) error {
186- return nil
287+ func (t * testBackend ) CreateCalendar (ctx context.Context , calendar * Calendar ) error {
288+ if v , e := t .CalendarHomeSetPath (ctx ); e != nil {
289+ return e
290+ } else if ! strings .HasPrefix (calendar .Path , v ) || len (calendar .Path ) == len (v ) {
291+ return fmt .Errorf ("cannot create calendar at location %s" , calendar .Path )
292+ } else {
293+ t .calendars = append (t .calendars , * calendar )
294+ return nil
295+ }
187296}
188297
189298func (t testBackend ) ListCalendars (ctx context.Context ) ([]Calendar , error ) {
@@ -207,7 +316,7 @@ func (t testBackend) CurrentUserPrincipal(ctx context.Context) (string, error) {
207316 return "/user/" , nil
208317}
209318
210- func (t testBackend ) DeleteCalendarObject (ctx context.Context , path string ) error {
319+ func (t * testBackend ) DeleteCalendarObject (ctx context.Context , path string ) error {
211320 return nil
212321}
213322
@@ -222,7 +331,7 @@ func (t testBackend) GetCalendarObject(ctx context.Context, path string, req *Ca
222331 return nil , fmt .Errorf ("Couldn't find calendar object at: %s" , path )
223332}
224333
225- func (t testBackend ) PutCalendarObject (ctx context.Context , path string , calendar * ical.Calendar , opts * PutCalendarObjectOptions ) (* CalendarObject , error ) {
334+ func (t * testBackend ) PutCalendarObject (ctx context.Context , path string , calendar * ical.Calendar , opts * PutCalendarObjectOptions ) (* CalendarObject , error ) {
226335 return nil , nil
227336}
228337
0 commit comments