additional comments
[civicrm-core.git] / tests / phpunit / CRM / Core / BAO / ActionScheduleTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06a1bc01 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28
29require_once 'CiviTest/CiviUnitTestCase.php';
e9479dcf
EM
30
31/**
32 * Class CRM_Core_BAO_ActionScheduleTest
33 */
6a488035 34class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
63e9c3fd 35
6a488035
TO
36 /**
37 * @var object see CiviTest/CiviMailUtils
38 */
567b2076 39 public $mut;
cee19268 40
00be9182 41 public function setUp() {
6a488035
TO
42 parent::setUp();
43
44 require_once 'CiviTest/CiviMailUtils.php';
6c6e6187 45 $this->mut = new CiviMailUtils($this, TRUE);
6a488035 46
57507ae6 47 $this->fixtures['rolling_membership'] = array(
6a488035
TO
48 'membership_type_id' => array(
49 'period_type' => 'rolling',
50 'duration_unit' => 'month',
51 'duration_interval' => '3',
52 'is_active' => 1,
53 ),
54 'join_date' => '20120315',
55 'start_date' => '20120315',
56 'end_date' => '20120615',
b29be8c2 57 'is_override' => 0,
6a488035 58 );
4b1efa1d 59
63e9c3fd 60 $this->fixtures['rolling_membership_past'] = array(
4b1efa1d 61 'membership_type_id' => array(
62 'period_type' => 'rolling',
63 'duration_unit' => 'month',
64 'duration_interval' => '3',
65 'is_active' => 1,
66 ),
67 'join_date' => '20100310',
68 'start_date' => '20100310',
69 'end_date' => '20100610',
70 'is_override' => 'NULL',
71 );
fe265b4e 72
db7de9c1 73 $this->fixtures['phonecall'] = array(
6a488035
TO
74 'status_id' => 1,
75 'activity_type_id' => 2,
76 'activity_date_time' => '20120615100000',
77 'is_current_revision' => 1,
78 'is_deleted' => 0,
79 );
db7de9c1 80 $this->fixtures['contact'] = array(
b29be8c2 81 'is_deceased' => 0,
6a488035
TO
82 'contact_type' => 'Individual',
83 'email' => 'test-member@example.com',
84 );
db7de9c1 85 $this->fixtures['contact_birthdate'] = array(
43030baf
AH
86 'is_deceased' => 0,
87 'contact_type' => 'Individual',
88 'email' => 'test-bday@example.com',
89 'birth_date' => '20050707',
90 );
db7de9c1 91 $this->fixtures['sched_activity_1day'] = array(
6a488035
TO
92 'name' => 'One_Day_Phone_Call_Notice',
93 'title' => 'One Day Phone Call Notice',
84a3e359 94 'limit_to' => '1',
6a488035
TO
95 'absolute_date' => NULL,
96 'body_html' => '<p>1-Day (non-repeating)</p>',
97 'body_text' => '1-Day (non-repeating)',
98 'end_action' => NULL,
99 'end_date' => NULL,
100 'end_frequency_interval' => NULL,
101 'end_frequency_unit' => NULL,
102 'entity_status' => '1',
103 'entity_value' => '2',
104 'group_id' => NULL,
105 'is_active' => '1',
106 'is_repeat' => '0',
107 'mapping_id' => '1',
108 'msg_template_id' => NULL,
109 'recipient' => '2',
110 'recipient_listing' => NULL,
111 'recipient_manual' => NULL,
112 'record_activity' => NULL,
113 'repetition_frequency_interval' => NULL,
114 'repetition_frequency_unit' => NULL,
115 'start_action_condition' => 'before',
116 'start_action_date' => 'activity_date_time',
117 'start_action_offset' => '1',
118 'start_action_unit' => 'day',
119 'subject' => '1-Day (non-repeating)',
120 );
121 $this->fixtures['sched_activity_1day_r'] = array(
122 'name' => 'One_Day_Phone_Call_Notice_R',
123 'title' => 'One Day Phone Call Notice R',
84a3e359 124 'limit_to' => 1,
6a488035
TO
125 'absolute_date' => NULL,
126 'body_html' => '<p>1-Day (repeating)</p>',
127 'body_text' => '1-Day (repeating)',
128 'end_action' => 'after',
129 'end_date' => 'activity_date_time',
130 'end_frequency_interval' => '2',
131 'end_frequency_unit' => 'day',
132 'entity_status' => '1',
133 'entity_value' => '2',
134 'group_id' => NULL,
135 'is_active' => '1',
136 'is_repeat' => '1',
137 'mapping_id' => '1',
138 'msg_template_id' => NULL,
139 'recipient' => '2',
140 'recipient_listing' => NULL,
141 'recipient_manual' => NULL,
142 'record_activity' => NULL,
143 'repetition_frequency_interval' => '6',
144 'repetition_frequency_unit' => 'hour',
145 'start_action_condition' => 'before',
146 'start_action_date' => 'activity_date_time',
147 'start_action_offset' => '1',
148 'start_action_unit' => 'day',
149 'subject' => '1-Day (repeating)',
150 );
567b2076 151 $this->fixtures['sched_membership_join_2week'] = array(
6a488035
TO
152 'name' => 'sched_membership_join_2week',
153 'title' => 'sched_membership_join_2week',
154 'absolute_date' => '',
155 'body_html' => '<p>body sched_membership_join_2week</p>',
156 'body_text' => 'body sched_membership_join_2week',
157 'end_action' => '',
158 'end_date' => '',
159 'end_frequency_interval' => '',
160 'end_frequency_unit' => '',
161 'entity_status' => '',
162 'entity_value' => '',
163 'group_id' => '',
164 'is_active' => 1,
165 'is_repeat' => '0',
166 'mapping_id' => 4,
167 'msg_template_id' => '',
168 'recipient' => '',
169 'recipient_listing' => '',
170 'recipient_manual' => '',
171 'record_activity' => 1,
172 'repetition_frequency_interval' => '',
173 'repetition_frequency_unit' => '',
174 'start_action_condition' => 'after',
175 'start_action_date' => 'membership_join_date',
176 'start_action_offset' => '2',
177 'start_action_unit' => 'week',
178 'subject' => 'subject sched_membership_join_2week',
179 );
567b2076 180 $this->fixtures['sched_membership_end_2week'] = array(
6a488035
TO
181 'name' => 'sched_membership_end_2week',
182 'title' => 'sched_membership_end_2week',
183 'absolute_date' => '',
184 'body_html' => '<p>body sched_membership_end_2week</p>',
185 'body_text' => 'body sched_membership_end_2week',
186 'end_action' => '',
187 'end_date' => '',
188 'end_frequency_interval' => '',
189 'end_frequency_unit' => '',
190 'entity_status' => '',
191 'entity_value' => '',
192 'group_id' => '',
193 'is_active' => 1,
194 'is_repeat' => '0',
195 'mapping_id' => 4,
196 'msg_template_id' => '',
197 'recipient' => '',
198 'recipient_listing' => '',
199 'recipient_manual' => '',
200 'record_activity' => 1,
201 'repetition_frequency_interval' => '',
202 'repetition_frequency_unit' => '',
203 'start_action_condition' => 'before',
204 'start_action_date' => 'membership_end_date',
205 'start_action_offset' => '2',
206 'start_action_unit' => 'week',
207 'subject' => 'subject sched_membership_end_2week',
208 );
4b1efa1d 209
567b2076 210 $this->fixtures['sched_membership_end_2month'] = array(
4b1efa1d 211 'name' => 'sched_membership_end_2month',
212 'title' => 'sched_membership_end_2month',
213 'absolute_date' => '',
214 'body_html' => '<p>body sched_membership_end_2month</p>',
215 'body_text' => 'body sched_membership_end_2month',
216 'end_action' => '',
217 'end_date' => '',
218 'end_frequency_interval' => '',
219 'end_frequency_unit' => '',
220 'entity_status' => '',
221 'entity_value' => '',
222 'group_id' => '',
223 'is_active' => 1,
224 'is_repeat' => '0',
225 'mapping_id' => 4,
226 'msg_template_id' => '',
227 'recipient' => '',
228 'recipient_listing' => '',
229 'recipient_manual' => '',
230 'record_activity' => 1,
231 'repetition_frequency_interval' => '',
232 'repetition_frequency_unit' => '',
233 'start_action_condition' => 'after',
234 'start_action_date' => 'membership_end_date',
235 'start_action_offset' => '2',
236 'start_action_unit' => 'month',
237 'subject' => 'subject sched_membership_end_2month',
238 );
239
567b2076 240 $this->fixtures['sched_contact_bday_yesterday'] = array(
43030baf
AH
241 'name' => 'sched_contact_bday_yesterday',
242 'title' => 'sched_contact_bday_yesterday',
243 'absolute_date' => '',
244 'body_html' => '<p>you look like you were born yesterday!</p>',
245 'body_text' => 'you look like you were born yesterday!',
246 'end_action' => '',
247 'end_date' => '',
248 'end_frequency_interval' => '',
249 'end_frequency_unit' => '',
250 'entity_status' => 1,
251 'entity_value' => 'birth_date',
252 'group_id' => '',
253 'is_active' => 1,
254 'is_repeat' => '0',
255 'mapping_id' => 6,
256 'msg_template_id' => '',
257 'recipient' => '',
258 'recipient_listing' => '',
259 'recipient_manual' => '',
260 'record_activity' => 1,
261 'repetition_frequency_interval' => '',
262 'repetition_frequency_unit' => '',
263 'start_action_condition' => 'after',
264 'start_action_date' => 'date_field',
265 'start_action_offset' => '1',
266 'start_action_unit' => 'day',
267 'subject' => 'subject sched_contact_bday_yesterday',
268 );
269
567b2076 270 $this->fixtures['sched_contact_bday_anniv'] = array(
43030baf
AH
271 'name' => 'sched_contact_bday_anniv',
272 'title' => 'sched_contact_bday_anniv',
273 'absolute_date' => '',
274 'body_html' => '<p>happy birthday!</p>',
275 'body_text' => 'happy birthday!',
276 'end_action' => '',
277 'end_date' => '',
278 'end_frequency_interval' => '',
279 'end_frequency_unit' => '',
280 'entity_status' => 2,
281 'entity_value' => 'birth_date',
282 'group_id' => '',
283 'is_active' => 1,
284 'is_repeat' => '0',
285 'mapping_id' => 6,
286 'msg_template_id' => '',
287 'recipient' => '',
288 'recipient_listing' => '',
289 'recipient_manual' => '',
290 'record_activity' => 1,
291 'repetition_frequency_interval' => '',
292 'repetition_frequency_unit' => '',
293 'start_action_condition' => 'before',
294 'start_action_date' => 'date_field',
295 'start_action_offset' => '1',
296 'start_action_unit' => 'day',
297 'subject' => 'subject sched_contact_bday_anniv',
298 );
299
567b2076 300 $this->fixtures['sched_contact_grad_tomorrow'] = array(
43030baf
AH
301 'name' => 'sched_contact_grad_tomorrow',
302 'title' => 'sched_contact_grad_tomorrow',
303 'absolute_date' => '',
304 'body_html' => '<p>congratulations on your graduation!</p>',
305 'body_text' => 'congratulations on your graduation!',
306 'end_action' => '',
307 'end_date' => '',
308 'end_frequency_interval' => '',
309 'end_frequency_unit' => '',
310 'entity_status' => 1,
311 'group_id' => '',
312 'is_active' => 1,
313 'is_repeat' => '0',
314 'mapping_id' => 6,
315 'msg_template_id' => '',
316 'recipient' => '',
317 'recipient_listing' => '',
318 'recipient_manual' => '',
319 'record_activity' => 1,
320 'repetition_frequency_interval' => '',
321 'repetition_frequency_unit' => '',
322 'start_action_condition' => 'before',
323 'start_action_date' => 'date_field',
324 'start_action_offset' => '1',
325 'start_action_unit' => 'day',
326 'subject' => 'subject sched_contact_grad_tomorrow',
327 );
328
567b2076 329 $this->fixtures['sched_contact_grad_anniv'] = array(
43030baf
AH
330 'name' => 'sched_contact_grad_anniv',
331 'title' => 'sched_contact_grad_anniv',
332 'absolute_date' => '',
333 'body_html' => '<p>dear alum, please send us money.</p>',
334 'body_text' => 'dear alum, please send us money.',
335 'end_action' => '',
336 'end_date' => '',
337 'end_frequency_interval' => '',
338 'end_frequency_unit' => '',
339 'entity_status' => 2,
340 'group_id' => '',
341 'is_active' => 1,
342 'is_repeat' => '0',
343 'mapping_id' => 6,
344 'msg_template_id' => '',
345 'recipient' => '',
346 'recipient_listing' => '',
347 'recipient_manual' => '',
348 'record_activity' => 1,
349 'repetition_frequency_interval' => '',
350 'repetition_frequency_unit' => '',
351 'start_action_condition' => 'after',
352 'start_action_date' => 'date_field',
353 'start_action_offset' => '1',
354 'start_action_unit' => 'week',
355 'subject' => 'subject sched_contact_grad_anniv',
356 );
567b2076 357 $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'] = array(
861d11c4
DG
358 'name' => 'sched_membership_end_2month',
359 'title' => 'sched_membership_end_2month',
360 'absolute_date' => '',
361 'body_html' => '<p>body sched_membership_end_2month</p>',
362 'body_text' => 'body sched_membership_end_2month',
363 'end_action' => '',
5c4d6559 364 'end_date' => 'membership_end_date',
861d11c4
DG
365 'end_frequency_interval' => '4',
366 'end_frequency_unit' => 'month',
367 'entity_status' => '',
368 'entity_value' => '',
369 'group_id' => '',
370 'is_active' => 1,
371 'is_repeat' => '1',
372 'mapping_id' => 4,
373 'msg_template_id' => '',
374 'recipient' => '',
375 'recipient_listing' => '',
376 'recipient_manual' => '',
377 'record_activity' => 1,
378 'repetition_frequency_interval' => '4',
379 'repetition_frequency_unit' => 'week',
380 'start_action_condition' => 'after',
381 'start_action_date' => 'membership_end_date',
382 'start_action_offset' => '2',
383 'start_action_unit' => 'month',
384 'subject' => 'subject sched_membership_end_2month',
385 );
567b2076 386 $this->fixtures['sched_membership_end_limit_to_none'] = array(
baa85770
EM
387 'name' => 'limit to none',
388 'title' => 'limit to none',
389 'absolute_date' => '',
390 'body_html' => '<p>body sched_membership_end_2month</p>',
391 'body_text' => 'body sched_membership_end_2month',
392 'end_action' => '',
393 'end_date' => '',
394 'end_frequency_interval' => '4',
395 'end_frequency_unit' => 'month',
396 'entity_status' => '',
397 'entity_value' => '',
398 'limit_to' => 0,
399 'group_id' => '',
400 'is_active' => 1,
401 'is_repeat' => '1',
402 'mapping_id' => 4,
403 'msg_template_id' => '',
404 'recipient' => '',
405 'recipient_listing' => '',
406 'recipient_manual' => '',
407 'record_activity' => 1,
408 'repetition_frequency_interval' => '4',
409 'repetition_frequency_unit' => 'week',
410 'start_action_condition' => 'after',
411 'start_action_date' => 'membership_end_date',
412 'start_action_offset' => '2',
413 'start_action_unit' => 'month',
414 'subject' => 'limit to none',
415 );
6a488035 416 $this->_setUp();
6a488035
TO
417 }
418
419 /**
420 * Tears down the fixture, for example, closes a network connection.
92c99a4a 421 *
6a488035 422 * This method is called after a test is executed.
6a488035 423 */
00be9182 424 public function tearDown() {
6a488035
TO
425 parent::tearDown();
426
427 $this->mut->clearMessages();
428 $this->mut->stop();
429 unset($this->mut);
92c99a4a
EM
430 $this->quickCleanup(array(
431 'civicrm_action_schedule',
432 'civicrm_action_log',
433 'civicrm_membership',
434 'civicrm_email',
435 ));
6a488035
TO
436 $this->_tearDown();
437 }
438
92c99a4a 439 public function testActivityDateTimeMatchNonRepeatableSchedule() {
cee19268 440 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day']);
6a488035
TO
441 $this->assertTrue(is_numeric($actionScheduleDao->id));
442
443 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
6a488035 444 $this->assertTrue(is_numeric($activity->id));
6c6e6187 445 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
6a488035
TO
446 $activity->save();
447
4f20f356 448 $source['contact_id'] = $contact['id'];
449 $source['activity_id'] = $activity->id;
450 $source['record_type_id'] = 2;
451 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
452 $activityContact->save();
453
6a488035 454 $this->assertCronRuns(array(
567b2076
EM
455 array(
456 // Before the 24-hour mark, no email
6a488035
TO
457 'time' => '2012-06-14 04:00:00',
458 'recipients' => array(),
459 ),
567b2076
EM
460 array(
461 // After the 24-hour mark, an email
6a488035
TO
462 'time' => '2012-06-14 15:00:00',
463 'recipients' => array(array('test-member@example.com')),
464 ),
567b2076
EM
465 array(
466 // Run cron again; message already sent
6a488035
TO
467 'time' => '',
468 'recipients' => array(),
469 ),
470 ));
471 }
472
92c99a4a 473 public function testActivityDateTimeMatchRepeatableSchedule() {
cee19268 474 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day_r']);
6a488035
TO
475 $this->assertTrue(is_numeric($actionScheduleDao->id));
476
477 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
478 $this->assertTrue(is_numeric($activity->id));
6c6e6187 479 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
6a488035
TO
480 $activity->save();
481
4f20f356 482 $source['contact_id'] = $contact['id'];
483 $source['activity_id'] = $activity->id;
6c6e6187 484 $source['record_type_id'] = 2;
4f20f356 485 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
486 $activityContact->save();
487
6a488035 488 $this->assertCronRuns(array(
567b2076
EM
489 array(
490 // Before the 24-hour mark, no email
6a488035
TO
491 'time' => '012-06-14 04:00:00',
492 'recipients' => array(),
493 ),
567b2076
EM
494 array(
495 // After the 24-hour mark, an email
6a488035
TO
496 'time' => '2012-06-14 15:00:00',
497 'recipients' => array(array('test-member@example.com')),
498 ),
567b2076
EM
499 array(
500 // Run cron 4 hours later; first message already sent
6a488035
TO
501 'time' => '2012-06-14 20:00:00',
502 'recipients' => array(),
503 ),
567b2076
EM
504 array(
505 // Run cron 6 hours later; send second message.
6a488035
TO
506 'time' => '2012-06-14 21:00:01',
507 'recipients' => array(array('test-member@example.com')),
508 ),
509 ));
510 }
511
512 /**
513 * For contacts/activities which don't match the schedule filter,
514 * an email should *not* be sent.
515 */
516 // TODO // function testActivityDateTime_NonMatch() { }
517
518 /**
519 * For contacts/members which match schedule based on join date,
520 * an email should be sent.
521 */
92c99a4a 522 public function testMembershipJoinDateMatch() {
b29be8c2 523 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 1)));
6a488035 524 $this->assertTrue(is_numeric($membership->id));
bf308d29 525 $result = $this->callAPISuccess('Email', 'create', array(
6a488035
TO
526 'contact_id' => $membership->contact_id,
527 'email' => 'test-member@example.com',
528 'location_type_id' => 1,
92915c55 529 ));
6a488035
TO
530 $this->assertAPISuccess($result);
531
bf308d29 532 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
6a488035
TO
533 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
534 $actionSchedule['entity_value'] = $membership->membership_type_id;
cee19268 535 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
6a488035
TO
536 $this->assertTrue(is_numeric($actionScheduleDao->id));
537
538 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
539 $this->assertCronRuns(array(
567b2076
EM
540 array(
541 // Before the 2-week mark, no email.
6a488035
TO
542 'time' => '2012-03-28 01:00:00',
543 'recipients' => array(),
544 ),
567b2076
EM
545 array(
546 // After the 2-week mark, send an email.
6a488035
TO
547 'time' => '2012-03-29 01:00:00',
548 'recipients' => array(array('test-member@example.com')),
549 ),
550 ));
551 }
552
553 /**
442cf836
EM
554 * Test end date email sent.
555 *
6a488035
TO
556 * For contacts/members which match schedule based on join date,
557 * an email should be sent.
558 */
92c99a4a 559 public function testMembershipJoinDateNonMatch() {
6a488035
TO
560 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $this->fixtures['rolling_membership']);
561 $this->assertTrue(is_numeric($membership->id));
bf308d29 562 $result = $this->callAPISuccess('Email', 'create', array(
6a488035
TO
563 'contact_id' => $membership->contact_id,
564 'location_type_id' => 1,
565 'email' => 'test-member@example.com',
6a488035 566 ));
fe265b4e 567
6a488035
TO
568 // Add an alternative membership type, and only send messages for that type
569 $extraMembershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', array());
570 $this->assertTrue(is_numeric($extraMembershipType->id));
cee19268 571 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_membership_join_2week']);
6a488035
TO
572 $this->assertTrue(is_numeric($actionScheduleDao->id));
573 $actionScheduleDao->entity_value = $extraMembershipType->id;
574 $actionScheduleDao->save();
575
576 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
577 $this->assertCronRuns(array(
567b2076
EM
578 array(
579 // After the 2-week mark, don't send email because we have different membership type.
6a488035
TO
580 'time' => '2012-03-29 01:00:00',
581 'recipients' => array(),
582 ),
583 ));
584 }
585
861d11c4 586 /**
442cf836 587 * Test that the first and SECOND notifications are sent out.
861d11c4 588 */
92c99a4a 589 public function testMembershipEndDateRepeat() {
861d11c4
DG
590 // creates membership with end_date = 20120615
591 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
592 $result = $this->callAPISuccess('Email', 'create', array(
593 'contact_id' => $membership->contact_id,
594 'email' => 'test-member@example.com',
595 ));
596 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
597
598 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
599 $actionSchedule['entity_value'] = $membership->membership_type_id;
600 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
601
602 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
603 $this->assertCronRuns(array(
567b2076
EM
604 array(
605 // After the 2-week mark, send an email.
861d11c4
DG
606 'time' => '2012-08-15 01:00:00',
607 'recipients' => array(array('test-member@example.com')),
608 ),
567b2076
EM
609 array(
610 // After the 2-week mark, send an email.
861d11c4
DG
611 'time' => '2012-09-12 01:00:00',
612 'recipients' => array(array('test-member@example.com')),
613 ),
614 ));
615 }
616
617 /**
442cf836
EM
618 * Test behaviour when date changes.
619 *
861d11c4
DG
620 * Test that the first notification is sent but the second is NOT sent if the end date changes in
621 * between
622 * see CRM-15376
623 */
92c99a4a 624 public function testMembershipEndDateRepeatChangedEndDate_CRM_15376() {
861d11c4
DG
625 // creates membership with end_date = 20120615
626 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
627 $this->callAPISuccess('Email', 'create', array(
628 'contact_id' => $membership->contact_id,
629 'email' => 'test-member@example.com',
630 ));
631 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
632
633 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
634 $actionSchedule['entity_value'] = $membership->membership_type_id;
635 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
636 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
637 $this->assertCronRuns(array(
567b2076
EM
638 array(
639 // After the 2-week mark, send an email.
861d11c4
DG
640 'time' => '2012-08-15 01:00:00',
641 'recipients' => array(array('test-member@example.com')),
642 ),
643 ));
644
442cf836 645 // Extend membership - reminder should NOT go out.
861d11c4
DG
646 $this->callAPISuccess('membership', 'create', array('id' => $membership->id, 'end_date' => '2014-01-01'));
647 $this->assertCronRuns(array(
442cf836
EM
648 array(
649 // After the 2-week mark, send an email.
861d11c4
DG
650 'time' => '2012-09-12 01:00:00',
651 'recipients' => array(),
652 ),
653 ));
654 }
655
6a488035 656 /**
442cf836
EM
657 * Test membership end date email sends.
658 *
6a488035
TO
659 * For contacts/members which match schedule based on end date,
660 * an email should be sent.
661 */
92c99a4a 662 public function testMembershipEndDateMatch() {
6a488035 663 // creates membership with end_date = 20120615
b29be8c2 664 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
6a488035 665 $this->assertTrue(is_numeric($membership->id));
bf308d29 666 $this->callAPISuccess('Email', 'create', array(
6a488035
TO
667 'contact_id' => $membership->contact_id,
668 'email' => 'test-member@example.com',
92915c55 669 ));
bf308d29 670 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
6a488035
TO
671
672 $actionSchedule = $this->fixtures['sched_membership_end_2week'];
673 $actionSchedule['entity_value'] = $membership->membership_type_id;
cee19268 674 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
6a488035
TO
675 $this->assertTrue(is_numeric($actionScheduleDao->id));
676
677 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
678 $this->assertCronRuns(array(
442cf836
EM
679 array(
680 // Before the 2-week mark, no email.
6a488035 681 'time' => '2012-05-31 01:00:00',
442cf836
EM
682 // 'time' => '2012-06-01 01:00:00',
683 // FIXME: Is this the right boundary?
6a488035
TO
684 'recipients' => array(),
685 ),
442cf836
EM
686 array(
687 // After the 2-week mark, send an email.
6a488035
TO
688 'time' => '2012-06-01 01:00:00',
689 'recipients' => array(array('test-member@example.com')),
690 ),
691 ));
692 }
693
4b1efa1d 694
695 /**
442cf836
EM
696 * Test membership end date email.
697 *
6c6e6187
TO
698 * For contacts/members which match schedule based on end date,
699 * an email should be sent.
700 */
92c99a4a 701 public function testMembershipEndDateNoMatch() {
4b1efa1d 702 // creates membership with end_date = 20120615
5c4d6559 703 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 3)));
4b1efa1d 704 $this->assertTrue(is_numeric($membership->id));
6c6e6187 705 $result = $this->callAPISuccess('Email', 'create', array(
4b1efa1d 706 'contact_id' => $membership->contact_id,
707 'email' => 'test-member@example.com',
4b1efa1d 708 ));
bf308d29 709 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
4b1efa1d 710
711 $actionSchedule = $this->fixtures['sched_membership_end_2month'];
712 $actionSchedule['entity_value'] = $membership->membership_type_id;
cee19268 713 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
4b1efa1d 714 $this->assertTrue(is_numeric($actionScheduleDao->id));
715
716 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
717 $this->assertCronRuns(array(
442cf836
EM
718 array(
719 // Before the 2-week mark, no email.
4b1efa1d 720 'time' => '2012-05-31 01:00:00',
442cf836
EM
721 // 'time' => '2012-06-01 01:00:00',
722 // FIXME: Is this the right boundary?
4b1efa1d 723 'recipients' => array(),
724 ),
442cf836
EM
725 array(
726 // After the 2-week mark, send an email.
4b1efa1d 727 'time' => '2013-05-01 01:00:00',
728 'recipients' => array(),
729 ),
730 ));
731 }
732
92c99a4a 733 public function testContactBirthDateNoAnniv() {
bf308d29 734 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
43030baf
AH
735 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
736 $actionSchedule = $this->fixtures['sched_contact_bday_yesterday'];
737 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
738 $this->assertTrue(is_numeric($actionScheduleDao->id));
739 $this->assertCronRuns(array(
442cf836
EM
740 array(
741 // On the birthday, no email.
43030baf
AH
742 'time' => '2005-07-07 01:00:00',
743 'recipients' => array(),
744 ),
442cf836
EM
745 array(
746 // The next day, send an email.
43030baf
AH
747 'time' => '2005-07-08 20:00:00',
748 'recipients' => array(array('test-bday@example.com')),
749 ),
750 ));
751 }
752
92c99a4a 753 public function testContactBirthDateAnniversary() {
6c6e6187 754 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
43030baf
AH
755 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
756 $actionSchedule = $this->fixtures['sched_contact_bday_anniv'];
757 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
758 $this->assertTrue(is_numeric($actionScheduleDao->id));
759 $this->assertCronRuns(array(
92c99a4a
EM
760 array(
761 // On some random day, no email.
43030baf
AH
762 'time' => '2014-03-07 01:00:00',
763 'recipients' => array(),
764 ),
92c99a4a
EM
765 array(
766 // On the eve of their 9th birthday, send an email.
43030baf
AH
767 'time' => '2014-07-06 20:00:00',
768 'recipients' => array(array('test-bday@example.com')),
769 ),
770 ));
771 }
4b1efa1d 772
92c99a4a 773 public function testContactCustomDateNoAnniv() {
43030baf
AH
774 $group = array(
775 'title' => 'Test_Group',
776 'name' => 'test_group',
777 'extends' => array('Individual'),
778 'style' => 'Inline',
6c6e6187 779 'is_multiple' => FALSE,
43030baf 780 'is_active' => 1,
43030baf 781 );
bf308d29 782 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
43030baf 783 $field = array(
43030baf
AH
784 'label' => 'Graduation',
785 'data_type' => 'Date',
786 'html_type' => 'Select Date',
787 'custom_group_id' => $createGroup['id'],
788 );
bf308d29 789 $createField = $this->callAPISuccess('custom_field', 'create', $field);
43030baf
AH
790 $contactParams = $this->fixtures['contact'];
791 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
bf308d29 792 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
43030baf
AH
793 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
794 $actionSchedule = $this->fixtures['sched_contact_grad_tomorrow'];
795 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
796 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
797 $this->assertTrue(is_numeric($actionScheduleDao->id));
798 $this->assertCronRuns(array(
92c99a4a
EM
799 array(
800 // On some random day, no email.
43030baf
AH
801 'time' => '2014-03-07 01:00:00',
802 'recipients' => array(),
803 ),
92c99a4a
EM
804 array(
805 // On the eve of their graduation, send an email.
43030baf
AH
806 'time' => '2013-12-15 20:00:00',
807 'recipients' => array(array('test-member@example.com')),
808 ),
809 ));
6c6e6187 810 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
43030baf 811 }
92915c55 812
baa85770 813 /**
92c99a4a 814 * Check that limit_to + an empty recipients doesn't sent to multiple contacts.
baa85770 815 */
00be9182 816 public function testMembershipLimitToNone() {
baa85770
EM
817 // creates membership with end_date = 20120615
818 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
819
820 $this->assertTrue(is_numeric($membership->id));
821 $result = $this->callAPISuccess('Email', 'create', array(
822 'contact_id' => $membership->contact_id,
823 'email' => 'member@example.com',
824 ));
825 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
826 $this->callAPISuccess('contact', 'create', array('email' => 'b@c.com', 'contact_type' => 'Individual'));
827
828 $this->assertAPISuccess($result);
829
830 $actionSchedule = $this->fixtures['sched_membership_end_limit_to_none'];
831 $actionSchedule['entity_value'] = $membership->membership_type_id;
832 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
833 $this->assertTrue(is_numeric($actionScheduleDao->id));
834
835 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
836 $this->assertCronRuns(array(
92c99a4a
EM
837 array(
838 // Before the 2-week mark, no email.
baa85770
EM
839 'time' => '2012-05-31 01:00:00',
840 // 'time' => '2012-06-01 01:00:00', // FIXME: Is this the right boundary?
841 'recipients' => array(),
842 ),
843 ));
844 }
845
5c4d6559 846 function testMembership_referenceDate() {
847 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
848
849 $this->assertTrue(is_numeric($membership->id));
850 $result = $this->callAPISuccess('Email', 'create', array(
851 'contact_id' => $membership->contact_id,
852 'email' => 'member@example.com',
853 ));
854
855 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
856 $this->assertAPISuccess($result);
857
858 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
859 $actionSchedule['entity_value'] = $membership->membership_type_id;
860 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
861 $this->assertTrue(is_numeric($actionScheduleDao->id));
862
863 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
864 $this->assertCronRuns(array(
865 array( // After the 2-week mark, send an email
866 'time' => '2012-03-29 01:00:00',
867 'recipients' => array(array('member@example.com')),
868 )
869 ));
870
871 //check if reference date is set to membership's join date
872 //as per the action_start_date chosen for current schedule reminder
873 $this->assertEquals('2012-03-15',
874 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $membership->contact_id, 'reference_date', 'contact_id')
875 );
876
877 //change current membership join date that may signifies as memberhip renewal activity
878 $membership->join_date = '2012-03-29';
879 $membership->save();
880
881 //change the email id of chosen membership contact to assert
882 //recipient of not the previously sent mail but the new one
883 $result = $this->callAPISuccess('Email', 'create', array(
884 'is_primary' => 1,
885 'contact_id' => $membership->contact_id,
886 'email' => 'member2@example.com'
887 ));
888 $this->assertAPISuccess($result);
889
890 $this->assertCronRuns(array(
891 array( // After the 2-week of the changed join date 2012-03-29, send an email
892 'time' => '2012-04-12 01:00:00',
893 'recipients' => array(array('member2@example.com')
894),
895 ),
896 ));
897
898 //To check whether the reference date is being changed to new join_date
899 $this->assertEquals('2012-03-29',
900 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $membership->contact_id, 'reference_date', 'contact_id', TRUE)
901 );
902 }
baa85770 903
92c99a4a 904 public function testContactCustomDateAnniv() {
43030baf
AH
905 $group = array(
906 'title' => 'Test_Group now',
907 'name' => 'test_group_now',
908 'extends' => array('Individual'),
909 'style' => 'Inline',
6c6e6187 910 'is_multiple' => FALSE,
43030baf 911 'is_active' => 1,
43030baf 912 );
bf308d29 913 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
43030baf 914 $field = array(
43030baf
AH
915 'label' => 'Graduation',
916 'data_type' => 'Date',
917 'html_type' => 'Select Date',
918 'custom_group_id' => $createGroup['id'],
919 );
bf308d29
EM
920 $createField = $this->callAPISuccess('custom_field', 'create', $field);
921
43030baf
AH
922 $contactParams = $this->fixtures['contact'];
923 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
bf308d29 924 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
43030baf
AH
925 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
926 $actionSchedule = $this->fixtures['sched_contact_grad_anniv'];
927 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
928 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
929 $this->assertTrue(is_numeric($actionScheduleDao->id));
930 $this->assertCronRuns(array(
92c99a4a
EM
931 array(
932 // On some random day, no email.
43030baf
AH
933 'time' => '2014-03-07 01:00:00',
934 'recipients' => array(),
935 ),
92c99a4a
EM
936 array(
937 // A week after their 5th anniversary of graduation, send an email.
43030baf
AH
938 'time' => '2018-12-23 20:00:00',
939 'recipients' => array(array('test-member@example.com')),
940 ),
941 ));
6c6e6187 942 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
43030baf 943 }
4b1efa1d 944
6a488035
TO
945 // TODO // function testMembershipEndDate_NonMatch() { }
946 // TODO // function testEventTypeStartDate_Match() { }
947 // TODO // function testEventTypeEndDate_Match() { }
948 // TODO // function testEventNameStartDate_Match() { }
949 // TODO // function testEventNameEndDate_Match() { }
950
951 /**
92c99a4a 952 * Run a series of cron jobs and make an assertion about email deliveries.
6a488035 953 *
16b10e64
CW
954 * @param array $cronRuns
955 * array specifying when to run cron and what messages to expect; each item is an array with keys:
956 * - time: string, e.g. '2012-06-15 21:00:01'
957 * - recipients: array(array(string)), list of email addresses which should receive messages
6a488035 958 */
00be9182 959 public function assertCronRuns($cronRuns) {
6a488035
TO
960 foreach ($cronRuns as $cronRun) {
961 CRM_Utils_Time::setTime($cronRun['time']);
bf308d29 962 $this->callAPISuccess('job', 'send_reminder', array());
6a488035
TO
963 $this->mut->assertRecipients($cronRun['recipients']);
964 $this->mut->clearMessages();
965 }
966 }
967
6a488035
TO
968 /**
969 * @var array(DAO_Name => array(int)) List of items to garbage-collect during tearDown
970 */
971 private $_testObjects;
972
973 /**
974 * Sets up the fixture, for example, opens a network connection.
92c99a4a 975 *
6a488035 976 * This method is called before a test is executed.
6a488035
TO
977 */
978 protected function _setUp() {
979 $this->_testObjects = array();
980 }
981
982 /**
983 * Tears down the fixture, for example, closes a network connection.
92c99a4a 984 *
6a488035 985 * This method is called after a test is executed.
6a488035
TO
986 */
987 protected function _tearDown() {
988 parent::tearDown();
989 $this->deleteTestObjects();
990 }
991
992 /**
993 * This is a wrapper for CRM_Core_DAO::createTestObject which tracks
92c99a4a 994 * created entities and provides for brainless cleanup.
6a488035
TO
995 *
996 * @see CRM_Core_DAO::createTestObject
92c99a4a 997 *
1e1fdcf6
EM
998 * @param $daoName
999 * @param array $params
1000 * @param int $numObjects
1001 * @param bool $createOnly
92c99a4a
EM
1002 *
1003 * @return array|NULL|object
6a488035 1004 */
2da40d21 1005 public function createTestObject($daoName, $params = array(), $numObjects = 1, $createOnly = FALSE) {
6a488035
TO
1006 $objects = CRM_Core_DAO::createTestObject($daoName, $params, $numObjects, $createOnly);
1007 if (is_array($objects)) {
1008 $this->registerTestObjects($objects);
0db6c3e1
TO
1009 }
1010 else {
6a488035
TO
1011 $this->registerTestObjects(array($objects));
1012 }
1013 return $objects;
1014 }
1015
1016 /**
5a4f6742
CW
1017 * @param array $objects
1018 * DAO or BAO objects.
6a488035 1019 */
00be9182 1020 public function registerTestObjects($objects) {
6a488035
TO
1021 //if (is_object($objects)) {
1022 // $objects = array($objects);
1023 //}
1024 foreach ($objects as $object) {
1025 $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object));
1026 $this->_testObjects[$daoName][] = $object->id;
1027 }
1028 }
1029
00be9182 1030 public function deleteTestObjects() {
6a488035
TO
1031 // Note: You might argue that the FK relations between test
1032 // objects could make this problematic; however, it should
1033 // behave intuitively as long as we mentally split our
1034 // test-objects between the "manual/primary records"
1035 // and the "automatic/secondary records"
1036 foreach ($this->_testObjects as $daoName => $daoIds) {
1037 foreach ($daoIds as $daoId) {
1038 CRM_Core_DAO::deleteTestObjects($daoName, array('id' => $daoId));
1039 }
1040 }
1041 $this->_testObjects = array();
1042 }
1043
1044}