0011840: iCal 10.11: problem with recurring events
[tine20] / tests / tine20 / Calendar / Frontend / WebDAV / ContainerTest.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Calendar
6  * @license     http://www.gnu.org/licenses/agpl.html
7  * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  */
10
11 /**
12  * Test helper
13  */
14 require_once dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
15
16 /**
17  * Test class for Calendar_Frontend_WebDAV_Container
18  */
19 class Calendar_Frontend_WebDAV_ContainerTest extends PHPUnit_Framework_TestCase
20 {
21     /**
22      * @var array test objects
23      */
24     protected $objects = array();
25     
26     /**
27      * Runs the test methods of this class.
28      *
29      * @access public
30      * @static
31      */
32     public static function main()
33     {
34         $suite  = new PHPUnit_Framework_TestSuite('Tine 2.0 Calendar WebDAV Container Tests');
35         PHPUnit_TextUI_TestRunner::run($suite);
36     }
37
38     /**
39      * Sets up the fixture.
40      * This method is called before a test is executed.
41      *
42      * @access protected
43      */
44     protected function setUp()
45     {
46         Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
47         
48         $this->objects['initialContainer'] = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
49             'name'              => Tinebase_Record_Abstract::generateUID(),
50             'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
51             'backend'           => 'Sql',
52             'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(),
53         )));
54         
55         Tinebase_Container::getInstance()->addGrants($this->objects['initialContainer'], Tinebase_Acl_Rights::ACCOUNT_TYPE_GROUP, Tinebase_Core::getUser()->accountPrimaryGroup, array(Tinebase_Model_Grants::GRANT_READ));
56         
57         // must be defined for Calendar/Frontend/WebDAV/Event.php
58         $_SERVER['REQUEST_URI'] = 'foobar';
59     }
60
61     /**
62      * Tears down the fixture
63      * This method is called after a test is executed.
64      *
65      * @access protected
66      */
67     protected function tearDown()
68     {
69         Tinebase_TransactionManager::getInstance()->rollBack();
70         Calendar_Config::getInstance()->set(Calendar_Config::SKIP_DOUBLE_EVENTS, '');
71     }
72     
73     /**
74      * assert that name of folder is container name
75      */
76     public function testGetName()
77     {
78         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
79         
80         $result = $container->getName();
81         
82         $this->assertEquals($this->objects['initialContainer']->name, $result);
83     }
84     
85     public function testGetOwner()
86     {
87         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
88         
89         $result = $container->getOwner();
90         
91         $this->assertEquals('principals/users/' . Tinebase_Core::getUser()->contact_id, $result);
92     }
93     
94     public function testGetACL()
95     {
96         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
97         
98         $result = $container->getACL();
99         
100         //var_dump($result);
101         
102         $this->assertEquals(6, count($result));
103     }
104     
105     public function testGetIdAsName()
106     {
107         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer'], true);
108         
109         $result = $container->getName();
110         
111         $this->assertEquals($this->objects['initialContainer']->getId(), $result);
112     }
113     
114     /**
115      * test getProperties
116      */
117     public function testGetProperties()
118     {
119         $this->testCreateFile();
120         
121         $requestedProperties = array(
122             '{http://calendarserver.org/ns/}getctag',
123             '{DAV:}resource-id'
124         );
125         
126         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
127         
128         $result = $container->getProperties($requestedProperties);
129        
130         $this->assertTrue(! empty($result['{http://calendarserver.org/ns/}getctag']));
131         $this->assertEquals($result['{DAV:}resource-id'], 'urn:uuid:' . $this->objects['initialContainer']->getId());
132     }
133     
134     /**
135      * test updateProperties of calendar folder
136      */
137     public function testUpdateProperties()
138     {
139         $this->testCreateFile();
140         
141         $mutations = array(
142             '{http://apple.com/ns/ical/}calendar-color'      => '#123456FF',
143             '{DAV:}displayname'                              => 'testUpdateProperties',
144             '{http://calendarserver.org/ns/}invalidProperty' => null
145         );
146         
147         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
148         
149         $result = $container->updateProperties($mutations);
150         
151         $updatedContainer = Tinebase_Container::getInstance()->get($this->objects['initialContainer']);
152         
153         $this->assertEquals($result[200]["{http://apple.com/ns/ical/}calendar-color"],      null);
154         $this->assertEquals($result[200]["{DAV:}displayname"],                              null);
155         $this->assertEquals($result[403]["{http://calendarserver.org/ns/}invalidProperty"], null);
156         $this->assertEquals($updatedContainer->color, substr($mutations['{http://apple.com/ns/ical/}calendar-color'], 0, 7));
157         $this->assertEquals($updatedContainer->name,  $mutations['{DAV:}displayname']);
158     }
159     
160     /**
161      * test getCreateFile
162      * 
163      * @return Calendar_Frontend_WebDAV_Event
164      */
165     public function testCreateFile()
166     {
167         $GLOBALS['_SERVER']['HTTP_USER_AGENT'] = 'FooBar User Agent';
168         
169         $vcalendarStream = $this->_getVCalendar(dirname(__FILE__) . '/../../Import/files/lightning.ics');
170         
171         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
172         
173         $id = Tinebase_Record_Abstract::generateUID();
174         
175         $etag = $container->createFile("$id.ics", $vcalendarStream);
176         $event = new Calendar_Frontend_WebDAV_Event($this->objects['initialContainer'], "$id.ics");
177         $record = $event->getRecord();
178         
179         $this->assertTrue($event instanceof Calendar_Frontend_WebDAV_Event);
180         $this->assertEquals($id, $record->getId(), 'ID mismatch');
181         
182         return $event;
183     }
184     
185     /**
186      * test getChildren
187      * 
188      */
189     public function testGetChildren($skipAssertions = true)
190     {
191         $event = $this->testCreateFile()->getRecord();
192         
193         // reschedule to match period filter
194         $event->dtstart = Tinebase_DateTime::now();
195         $event->dtend = Tinebase_DateTime::now()->addMinute(30);
196         Calendar_Controller_MSEventFacade::getInstance()->update($event);
197         
198         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
199         
200         $children = $container->getChildren();
201         
202         if (! $skipAssertions) {
203             $this->assertEquals(1, count($children));
204             $this->assertTrue($children[$event->getId()] instanceof Calendar_Frontend_WebDAV_Event);
205         }
206         
207         return $children;
208     }
209     
210     public function testGetChildrenSkipDoubleEvents()
211     {
212         Calendar_Config::getInstance()->set(Calendar_Config::SKIP_DOUBLE_EVENTS, 'personal');
213         $children = $this->testGetChildren(true);
214         $this->assertEquals(0, count($children));
215         
216         Calendar_Config::getInstance()->set(Calendar_Config::SKIP_DOUBLE_EVENTS, 'shared');
217         $children = $this->testGetChildren(true);
218         $this->assertEquals(2, count($children));
219     }
220     
221     /**
222      * test calendarQuery with start and end time set
223      * 
224      * @param boolean $timeRangeEndSet
225      * @param boolean $removeOwnAttender
226      */
227     public function testCalendarQuery($timeRangeEndSet = true, $removeOwnAttender = false)
228     {
229         $event = $this->testCreateFile()->getRecord();
230         
231         // reschedule to match period filter
232         $event->dtstart = Tinebase_DateTime::now();
233         $event->dtend   = Tinebase_DateTime::now()->addMinute(30);
234         if ($removeOwnAttender) {
235             $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
236                 array(
237                     'user_id'   => Tinebase_User::getInstance()->getUserByLoginName('sclever')->contact_id,
238                     'user_type' => Calendar_Model_Attender::USERTYPE_USER,
239                     'role'      => Calendar_Model_Attender::ROLE_REQUIRED,
240                 )
241             ));
242         }
243         Calendar_Controller_MSEventFacade::getInstance()->update($event);
244         
245         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
246         
247         $timeRange = $timeRangeEndSet ? array(
248             'start' => Tinebase_DateTime::now()->subHour(1),
249             'end'   => Tinebase_DateTime::now()->addHour(1)
250         ) : array(
251             'start' => Tinebase_DateTime::now()->subHour(1),
252         );
253         
254         $urls = $container->calendarQuery(array(
255             'name'         => 'VCALENDAR',
256             'comp-filters' => array(
257                 array(
258                     'name'           => 'VEVENT',
259                     'comp-filters'   => array(),
260                     'prop-filters'   => array(),
261                     'is-not-defined' => false,
262                     'time-range'     => $timeRange,
263                 ),
264             ),
265             'prop-filters'   => array(),
266             'is-not-defined' => false,
267             'time-range'     => null
268         ));
269         
270         $this->assertContains($event->getId(), $urls);
271     }
272     
273     /**
274      * test calendarQuery with start time set only
275      */
276     public function testCalendarQueryNoEnd()
277     {
278         $this->testCalendarQuery(false);
279     }
280     
281     /**
282      * testCalendarQueryNotAttender
283      * 
284      * @see 0009204: "Foreign" events won't sync/show up via CalDAV.
285      */
286     public function testCalendarQueryNotAttender()
287     {
288         $this->testCalendarQuery(true, true);
289     }
290     
291     /**
292      * test calendarQuery with start and end time set
293      * 
294      * @param boolean $timeRangeEndSet
295      * @param boolean $removeOwnAttender
296      */
297     public function testCalendarQueryPropertyFilter()
298     {
299         $event1 = $this->testCreateFile()->getRecord();
300         $event2 = $this->testCreateFile()->getRecord();
301         
302         // reschedule to match period filter
303         $event1->dtstart = Tinebase_DateTime::now();
304         $event1->dtend   = Tinebase_DateTime::now()->addMinute(30);
305         Calendar_Controller_MSEventFacade::getInstance()->update($event1);
306         
307         $event2->dtstart = Tinebase_DateTime::now();
308         $event2->dtend   = Tinebase_DateTime::now()->addMinute(30);
309         Calendar_Controller_MSEventFacade::getInstance()->update($event2);
310         
311         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
312         
313         $urls = $container->calendarQuery(array(
314             'name'         => 'VCALENDAR',
315             'comp-filters' => array(
316                 array(
317                     'name'           => 'VEVENT',
318                     'prop-filters'   => array(
319                         array(
320                             'name' => 'UID',
321                             'text-match' => array(
322                                 'value' => $event1->getId()
323                             )
324                         ),
325                         array(
326                             'name' => 'UID',
327                             'text-match' => array(
328                                 'value' => $event2->getId()
329                             )
330                         )
331                     )
332                 ),
333             ),
334             'prop-filters'   => array(),
335             'is-not-defined' => false,
336             'time-range'     => null
337         ));
338         
339         $this->assertContains($event1->getId(), $urls);
340         $this->assertContains($event2->getId(), $urls);
341         $this->assertEquals(2, count($urls));
342     }
343     /**
344      * test Tinebase_WebDav_Container_Abstract::getCalendarVTimezone
345      */
346     public function testGetCalendarVTimezone()
347     {
348         $vTimezone = Tinebase_WebDav_Container_Abstract::getCalendarVTimezone('Calendar');
349         $this->assertContains('PRODID:-//tine20.org//Tine 2.0 Calendar', $vTimezone);
350         
351         $vTimezone = Tinebase_WebDav_Container_Abstract::getCalendarVTimezone(Tinebase_Application::getInstance()->getApplicationByName('Calendar'));
352         $this->assertContains('PRODID:-//tine20.org//Tine 2.0 Calendar', $vTimezone);
353     }
354     
355     /**
356      * test Calendar_Frontend_WebDAV_Container::getShares
357      */
358     public function testGetShares()
359     {
360         $container = new Calendar_Frontend_WebDAV_Container($this->objects['initialContainer']);
361         
362         $shares = $container->getShares();
363
364         $this->assertEquals(3, count($shares));
365         $this->assertEquals('urn:uuid:anyone', $shares[0]['href']);
366         $this->assertEquals('urn:uuid:' . Tinebase_Core::getUser()->contact_id, $shares[2]['href']);
367     }
368     
369     /**
370      * test Calendar_Frontend_WebDAV_Container::getShares for container user has no admin grant for
371      */
372     public function testGetSharesWithoutRights()
373     {
374         $jmcblack = array_value('jmcblack', Zend_Registry::get('personas'));
375         $jmcblacksCalId = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::DEFAULTCALENDAR, $jmcblack->getId());
376         $jmcblacksCal = Tinebase_Container::getInstance()->get($jmcblacksCalId);
377         
378         $container = new Calendar_Frontend_WebDAV_Container($jmcblacksCal);
379     
380         $shares = $container->getShares();
381     
382         $this->assertEquals(1, count($shares));
383         $this->assertTrue((bool)$shares[0]['readOnly']);
384     }
385     
386     /**
387      * return vcalendar as string and replace organizers email address with emailaddess of current user
388      * 
389      * @param string $_filename  file to open
390      * @return string
391      */
392     protected function _getVCalendar($_filename)
393     {
394         $vcalendar = file_get_contents($_filename);
395         
396         $vcalendar = preg_replace('/l.kneschke@metaway\n s.de/', Tinebase_Core::getUser()->accountEmailAddress, $vcalendar);
397         
398         return $vcalendar;
399     }
400 }