Skip to content

Commit 19d9d86

Browse files
committed
Calendar: CalDAV test testChangeStatusOfParticipantsInDifferentRecurrences is now working
1 parent 2d0e335 commit 19d9d86

1 file changed

Lines changed: 76 additions & 12 deletions

File tree

calendar/tests/CalDAV/RecurrenceExceptionParticipantTest.php

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,45 +219,102 @@ protected function exceptionComponent(string $uid, string $attendee_partstat='NE
219219

220220
/**
221221
* Change status of participants in different recurrences.
222+
*
223+
* Strategy / pass criteria:
224+
* - Build one recurring master with two explicit overridden recurrences.
225+
* - Each override has a different attendee PARTSTAT for attendee1.
226+
* - Export via CalDAV GET.
227+
* - Pass when both RECURRENCE-ID components are present and each expected
228+
* status variant is present in the exported iCal.
229+
*
230+
* Uses near-future dynamic UTC timestamps so recurrence expansion stays
231+
* inside typical horizon limits across environments.
222232
*/
223233
public function testChangeStatusOfParticipantsInDifferentRecurrences()
224234
{
225-
$this->markTestIncomplete("Not working");
226235
$uid = $this->makeUid('caldav-recur-status');
236+
$master_start = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
237+
$master_start = $master_start->setTime(9, 0, 0)->modify('+14 days');
238+
$master_end = $master_start->modify('+1 hour');
239+
$recurrence1 = $master_start->modify('+1 day');
240+
$recurrence2 = $master_start->modify('+2 days');
241+
$recurrence1_moved_start = $recurrence1->modify('+10 minutes');
242+
$recurrence1_moved_end = $recurrence1_moved_start->modify('+1 hour');
243+
$recurrence2_moved_start = $recurrence2->modify('+20 minutes');
244+
$recurrence2_moved_end = $recurrence2_moved_start->modify('+1 hour');
245+
$dtstamp = $master_start->modify('-1 hour')->format('Ymd\THis\Z');
246+
$master_start_ical = $master_start->format('Ymd\THis\Z');
247+
$master_end_ical = $master_end->format('Ymd\THis\Z');
248+
$recurrence1_ical = $recurrence1->format('Ymd\THis\Z');
249+
$recurrence2_ical = $recurrence2->format('Ymd\THis\Z');
250+
$recurrence1_moved_start_ical = $recurrence1_moved_start->format('Ymd\THis\Z');
251+
$recurrence1_moved_end_ical = $recurrence1_moved_end->format('Ymd\THis\Z');
252+
$recurrence2_moved_start_ical = $recurrence2_moved_start->format('Ymd\THis\Z');
253+
$recurrence2_moved_end_ical = $recurrence2_moved_end->format('Ymd\THis\Z');
254+
255+
$master = "BEGIN:VEVENT\r\n".
256+
"UID:$uid\r\n".
257+
"DTSTAMP:$dtstamp\r\n".
258+
"DTSTART:$master_start_ical\r\n".
259+
"DTEND:$master_end_ical\r\n".
260+
"RRULE:FREQ=DAILY;COUNT=6\r\n".
261+
"SUMMARY:Recurring participant test\r\n".
262+
"ORGANIZER:mailto:".$this->organizerMail()."\r\n".
263+
"ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:".$this->organizerMail()."\r\n".
264+
"ATTENDEE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:".self::ATTENDEE1_MAIL."\r\n".
265+
"END:VEVENT\r\n";
227266

228267
// Two overridden instances with different attendee status.
229268
$overrides =
230269
"BEGIN:VEVENT\r\n".
231270
"UID:$uid\r\n".
232-
"RECURRENCE-ID:20300102T090000Z\r\n".
233-
"DTSTART:20300102T091000Z\r\n".
234-
"DTEND:20300102T101000Z\r\n".
271+
"DTSTAMP:$dtstamp\r\n".
272+
"RECURRENCE-ID:$recurrence1_ical\r\n".
273+
"DTSTART:$recurrence1_moved_start_ical\r\n".
274+
"DTEND:$recurrence1_moved_end_ical\r\n".
275+
"SUMMARY:Recurring participant test exception accepted\r\n".
235276
"ORGANIZER:mailto:".$this->organizerMail()."\r\n".
236277
"ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:".$this->organizerMail()."\r\n".
237278
"ATTENDEE;PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:".self::ATTENDEE1_MAIL."\r\n".
238279
"END:VEVENT\r\n".
239280
"BEGIN:VEVENT\r\n".
240281
"UID:$uid\r\n".
241-
"RECURRENCE-ID:20300103T090000Z\r\n".
242-
"DTSTART:20300103T092000Z\r\n".
243-
"DTEND:20300103T102000Z\r\n".
282+
"DTSTAMP:$dtstamp\r\n".
283+
"RECURRENCE-ID:$recurrence2_ical\r\n".
284+
"DTSTART:$recurrence2_moved_start_ical\r\n".
285+
"DTEND:$recurrence2_moved_end_ical\r\n".
286+
"SUMMARY:Recurring participant test exception tentative\r\n".
244287
"ORGANIZER:mailto:".$this->organizerMail()."\r\n".
245288
"ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:".$this->organizerMail()."\r\n".
246289
"ATTENDEE;PARTSTAT=TENTATIVE;ROLE=REQ-PARTICIPANT:mailto:".self::ATTENDEE1_MAIL."\r\n".
247290
"END:VEVENT\r\n";
248291

249-
$this->putEvent($uid, $this->recurringIcal($uid, $overrides));
292+
$this->putEvent($uid, "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//EGroupware//CalDAV Test//EN\r\n".$master.$overrides."END:VCALENDAR\r\n");
250293

251294
$ical = $this->unfoldIcal($this->getEventIcal($uid));
252-
$this->assertStringContainsString("RECURRENCE-ID:20300102T090000Z", $ical);
253-
$this->assertStringContainsString("RECURRENCE-ID:20300103T090000Z", $ical);
254-
$this->assertStringContainsString("PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT", $ical);
255-
$this->assertStringContainsString("PARTSTAT=TENTATIVE;ROLE=REQ-PARTICIPANT", $ical);
295+
$this->assertStringContainsString("RECURRENCE-ID:$recurrence1_ical", $ical);
296+
$this->assertStringContainsString("RECURRENCE-ID:$recurrence2_ical", $ical);
297+
$exception1 = $this->exceptionBlock($ical, $recurrence1_ical);
298+
$exception2 = $this->exceptionBlock($ical, $recurrence2_ical);
299+
$this->assertNotEmpty($exception1, 'First exception block missing');
300+
$this->assertNotEmpty($exception2, 'Second exception block missing');
301+
$this->assertStringContainsString("mailto:".self::ATTENDEE1_MAIL, $exception1);
302+
$this->assertStringContainsString("mailto:".self::ATTENDEE1_MAIL, $exception2);
303+
$this->assertStringContainsString("PARTSTAT=ACCEPTED", $exception1);
304+
$this->assertStringContainsString("PARTSTAT=TENTATIVE", $exception2);
256305
$this->assertStringContainsString("PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;RSVP=", $ical);
257306
}
258307

259308
/**
260309
* Create exception with different date and time via CalDAV.
310+
*
311+
* Strategy / pass criteria:
312+
* - Import recurring master plus one exception component linked by
313+
* RECURRENCE-ID.
314+
* - Exception moves occurrence time to a different day/hour.
315+
* - Export via CalDAV GET.
316+
* - Pass when export contains the RECURRENCE-ID and moved DTSTART, and the
317+
* expected one-hour duration.
261318
*/
262319
public function testCreateExceptionsWithDifferentDateAndTime()
263320
{
@@ -272,6 +329,13 @@ public function testCreateExceptionsWithDifferentDateAndTime()
272329

273330
/**
274331
* Change status of participants in exception via CalDAV.
332+
*
333+
* Strategy / pass criteria:
334+
* - Import recurring master plus one exception where attendee1 PARTSTAT is
335+
* ACCEPTED on the exception only.
336+
* - Export via CalDAV GET.
337+
* - Pass when export contains the exception RECURRENCE-ID and the exception
338+
* participant status, while master/default status remains NEEDS-ACTION.
275339
*/
276340
public function testChangeStatusOfParticipantsInException()
277341
{

0 commit comments

Comments
 (0)