3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
28 require_once 'CiviTest/CiviUnitTestCase.php';
31 * Class CRM_Core_BAO_ActionScheduleTest
33 class CRM_Core_BAO_ActionScheduleTest
extends CiviUnitTestCase
{
40 public function setUp() {
43 require_once 'CiviTest/CiviMailUtils.php';
44 $this->mut
= new CiviMailUtils($this, TRUE);
46 $this->fixtures
['rolling_membership'] = array(
47 'membership_type_id' => array(
48 'period_type' => 'rolling',
49 'duration_unit' => 'month',
50 'duration_interval' => '3',
53 'join_date' => '20120315',
54 'start_date' => '20120315',
55 'end_date' => '20120615',
59 $this->fixtures
['rolling_membership_past'] = array(
60 'membership_type_id' => array(
61 'period_type' => 'rolling',
62 'duration_unit' => 'month',
63 'duration_interval' => '3',
66 'join_date' => '20100310',
67 'start_date' => '20100310',
68 'end_date' => '20100610',
69 'is_override' => 'NULL',
71 $this->fixtures
['participant'] = array(
75 'title' => 'Example Event',
76 'start_date' => '20120315',
77 'end_date' => '20120615',
79 'role_id' => '1', // Attendee.
80 'status_id' => '8', // No-show.
83 $this->fixtures
['phonecall'] = array(
85 'activity_type_id' => 2,
86 'activity_date_time' => '20120615100000',
87 'is_current_revision' => 1,
90 $this->fixtures
['contact'] = array(
92 'contact_type' => 'Individual',
93 'email' => 'test-member@example.com',
94 'gender_id' => 'Female',
96 $this->fixtures
['contact_birthdate'] = array(
98 'contact_type' => 'Individual',
99 'email' => 'test-bday@example.com',
100 'birth_date' => '20050707',
102 $this->fixtures
['sched_activity_1day'] = array(
103 'name' => 'One_Day_Phone_Call_Notice',
104 'title' => 'One Day Phone Call Notice',
106 'absolute_date' => NULL,
107 'body_html' => '<p>1-Day (non-repeating)</p>',
108 'body_text' => '1-Day (non-repeating)',
109 'end_action' => NULL,
111 'end_frequency_interval' => NULL,
112 'end_frequency_unit' => NULL,
113 'entity_status' => '1',
114 'entity_value' => '2',
119 'msg_template_id' => NULL,
121 'recipient_listing' => NULL,
122 'recipient_manual' => NULL,
123 'record_activity' => NULL,
124 'repetition_frequency_interval' => NULL,
125 'repetition_frequency_unit' => NULL,
126 'start_action_condition' => 'before',
127 'start_action_date' => 'activity_date_time',
128 'start_action_offset' => '1',
129 'start_action_unit' => 'day',
130 'subject' => '1-Day (non-repeating) (about {activity.activity_type})',
132 $this->fixtures
['sched_activity_1day_r'] = array(
133 'name' => 'One_Day_Phone_Call_Notice_R',
134 'title' => 'One Day Phone Call Notice R',
136 'absolute_date' => NULL,
137 'body_html' => '<p>1-Day (repeating)</p>',
138 'body_text' => '1-Day (repeating)',
139 'end_action' => 'after',
140 'end_date' => 'activity_date_time',
141 'end_frequency_interval' => '2',
142 'end_frequency_unit' => 'day',
143 'entity_status' => '1',
144 'entity_value' => '2',
149 'msg_template_id' => NULL,
151 'recipient_listing' => NULL,
152 'recipient_manual' => NULL,
153 'record_activity' => NULL,
154 'repetition_frequency_interval' => '6',
155 'repetition_frequency_unit' => 'hour',
156 'start_action_condition' => 'before',
157 'start_action_date' => 'activity_date_time',
158 'start_action_offset' => '1',
159 'start_action_unit' => 'day',
160 'subject' => '1-Day (repeating) (about {activity.activity_type})',
162 $this->fixtures
['sched_membership_join_2week'] = array(
163 'name' => 'sched_membership_join_2week',
164 'title' => 'sched_membership_join_2week',
165 'absolute_date' => '',
166 'body_html' => '<p>body sched_membership_join_2week</p>',
167 'body_text' => 'body sched_membership_join_2week',
170 'end_frequency_interval' => '',
171 'end_frequency_unit' => '',
172 'entity_status' => '',
173 'entity_value' => '',
178 'msg_template_id' => '',
180 'recipient_listing' => '',
181 'recipient_manual' => '',
182 'record_activity' => 1,
183 'repetition_frequency_interval' => '',
184 'repetition_frequency_unit' => '',
185 'start_action_condition' => 'after',
186 'start_action_date' => 'membership_join_date',
187 'start_action_offset' => '2',
188 'start_action_unit' => 'week',
189 'subject' => 'subject sched_membership_join_2week (joined {membership.join_date})',
191 $this->fixtures
['sched_membership_end_2week'] = array(
192 'name' => 'sched_membership_end_2week',
193 'title' => 'sched_membership_end_2week',
194 'absolute_date' => '',
195 'body_html' => '<p>body sched_membership_end_2week</p>',
196 'body_text' => 'body sched_membership_end_2week',
199 'end_frequency_interval' => '',
200 'end_frequency_unit' => '',
201 'entity_status' => '',
202 'entity_value' => '',
207 'msg_template_id' => '',
209 'recipient_listing' => '',
210 'recipient_manual' => '',
211 'record_activity' => 1,
212 'repetition_frequency_interval' => '',
213 'repetition_frequency_unit' => '',
214 'start_action_condition' => 'before',
215 'start_action_date' => 'membership_end_date',
216 'start_action_offset' => '2',
217 'start_action_unit' => 'week',
218 'subject' => 'subject sched_membership_end_2week',
220 $this->fixtures
['sched_on_membership_end_date'] = array(
221 'name' => 'sched_on_membership_end_date',
222 'title' => 'sched_on_membership_end_date',
223 'body_html' => '<p>Your membership expired today</p>',
224 'body_text' => 'Your membership expired today',
227 'record_activity' => 1,
228 'start_action_condition' => 'after',
229 'start_action_date' => 'membership_end_date',
230 'start_action_offset' => '0',
231 'start_action_unit' => 'hour',
232 'subject' => 'subject send reminder on membership_end_date',
234 $this->fixtures
['sched_after_1day_membership_end_date'] = array(
235 'name' => 'sched_after_1day_membership_end_date',
236 'title' => 'sched_after_1day_membership_end_date',
237 'body_html' => '<p>Your membership expired yesterday</p>',
238 'body_text' => 'Your membership expired yesterday',
241 'record_activity' => 1,
242 'start_action_condition' => 'after',
243 'start_action_date' => 'membership_end_date',
244 'start_action_offset' => '1',
245 'start_action_unit' => 'day',
246 'subject' => 'subject send reminder on membership_end_date',
249 $this->fixtures
['sched_membership_end_2month'] = array(
250 'name' => 'sched_membership_end_2month',
251 'title' => 'sched_membership_end_2month',
252 'absolute_date' => '',
253 'body_html' => '<p>body sched_membership_end_2month</p>',
254 'body_text' => 'body sched_membership_end_2month',
257 'end_frequency_interval' => '',
258 'end_frequency_unit' => '',
259 'entity_status' => '',
260 'entity_value' => '',
265 'msg_template_id' => '',
267 'recipient_listing' => '',
268 'recipient_manual' => '',
269 'record_activity' => 1,
270 'repetition_frequency_interval' => '',
271 'repetition_frequency_unit' => '',
272 'start_action_condition' => 'after',
273 'start_action_date' => 'membership_end_date',
274 'start_action_offset' => '2',
275 'start_action_unit' => 'month',
276 'subject' => 'subject sched_membership_end_2month',
279 $this->fixtures
['sched_contact_bday_yesterday'] = array(
280 'name' => 'sched_contact_bday_yesterday',
281 'title' => 'sched_contact_bday_yesterday',
282 'absolute_date' => '',
283 'body_html' => '<p>you look like you were born yesterday!</p>',
284 'body_text' => 'you look like you were born yesterday!',
287 'end_frequency_interval' => '',
288 'end_frequency_unit' => '',
289 'entity_status' => 1,
290 'entity_value' => 'birth_date',
295 'msg_template_id' => '',
297 'recipient_listing' => '',
298 'recipient_manual' => '',
299 'record_activity' => 1,
300 'repetition_frequency_interval' => '',
301 'repetition_frequency_unit' => '',
302 'start_action_condition' => 'after',
303 'start_action_date' => 'date_field',
304 'start_action_offset' => '1',
305 'start_action_unit' => 'day',
306 'subject' => 'subject sched_contact_bday_yesterday',
309 $this->fixtures
['sched_contact_bday_anniv'] = array(
310 'name' => 'sched_contact_bday_anniv',
311 'title' => 'sched_contact_bday_anniv',
312 'absolute_date' => '',
313 'body_html' => '<p>happy birthday!</p>',
314 'body_text' => 'happy birthday!',
317 'end_frequency_interval' => '',
318 'end_frequency_unit' => '',
319 'entity_status' => 2,
320 'entity_value' => 'birth_date',
325 'msg_template_id' => '',
327 'recipient_listing' => '',
328 'recipient_manual' => '',
329 'record_activity' => 1,
330 'repetition_frequency_interval' => '',
331 'repetition_frequency_unit' => '',
332 'start_action_condition' => 'before',
333 'start_action_date' => 'date_field',
334 'start_action_offset' => '1',
335 'start_action_unit' => 'day',
336 'subject' => 'subject sched_contact_bday_anniv',
339 $this->fixtures
['sched_contact_grad_tomorrow'] = array(
340 'name' => 'sched_contact_grad_tomorrow',
341 'title' => 'sched_contact_grad_tomorrow',
342 'absolute_date' => '',
343 'body_html' => '<p>congratulations on your graduation!</p>',
344 'body_text' => 'congratulations on your graduation!',
347 'end_frequency_interval' => '',
348 'end_frequency_unit' => '',
349 'entity_status' => 1,
354 'msg_template_id' => '',
356 'recipient_listing' => '',
357 'recipient_manual' => '',
358 'record_activity' => 1,
359 'repetition_frequency_interval' => '',
360 'repetition_frequency_unit' => '',
361 'start_action_condition' => 'before',
362 'start_action_date' => 'date_field',
363 'start_action_offset' => '1',
364 'start_action_unit' => 'day',
365 'subject' => 'subject sched_contact_grad_tomorrow',
368 $this->fixtures
['sched_contact_grad_anniv'] = array(
369 'name' => 'sched_contact_grad_anniv',
370 'title' => 'sched_contact_grad_anniv',
371 'absolute_date' => '',
372 'body_html' => '<p>dear alum, please send us money.</p>',
373 'body_text' => 'dear alum, please send us money.',
376 'end_frequency_interval' => '',
377 'end_frequency_unit' => '',
378 'entity_status' => 2,
383 'msg_template_id' => '',
385 'recipient_listing' => '',
386 'recipient_manual' => '',
387 'record_activity' => 1,
388 'repetition_frequency_interval' => '',
389 'repetition_frequency_unit' => '',
390 'start_action_condition' => 'after',
391 'start_action_date' => 'date_field',
392 'start_action_offset' => '1',
393 'start_action_unit' => 'week',
394 'subject' => 'subject sched_contact_grad_anniv',
397 $this->fixtures
['sched_contact_created_yesterday'] = array(
398 'name' => 'sched_contact_created_yesterday',
399 'title' => 'sched_contact_created_yesterday',
400 'absolute_date' => '',
401 'body_html' => '<p>Your contact was created yesterday</p>',
402 'body_text' => 'Your contact was created yesterday!',
405 'end_frequency_interval' => '',
406 'end_frequency_unit' => '',
407 'entity_status' => 1,
408 'entity_value' => 'created_date',
413 'msg_template_id' => '',
415 'recipient_listing' => '',
416 'recipient_manual' => '',
417 'record_activity' => 1,
418 'repetition_frequency_interval' => '',
419 'repetition_frequency_unit' => '',
420 'start_action_condition' => 'after',
421 'start_action_date' => 'date_field',
422 'start_action_offset' => '1',
423 'start_action_unit' => 'day',
424 'subject' => 'subject sched_contact_created_yesterday',
427 $this->fixtures
['sched_contact_mod_anniv'] = array(
428 'name' => 'sched_contact_mod_anniv',
429 'title' => 'sched_contact_mod_anniv',
430 'absolute_date' => '',
431 'body_html' => '<p>You last updated your data last year</p>',
432 'body_text' => 'Go update your stuff!',
435 'end_frequency_interval' => '',
436 'end_frequency_unit' => '',
437 'entity_status' => 2,
438 'entity_value' => 'modified_date',
443 'msg_template_id' => '',
445 'recipient_listing' => '',
446 'recipient_manual' => '',
447 'record_activity' => 1,
448 'repetition_frequency_interval' => '',
449 'repetition_frequency_unit' => '',
450 'start_action_condition' => 'before',
451 'start_action_date' => 'date_field',
452 'start_action_offset' => '1',
453 'start_action_unit' => 'day',
454 'subject' => 'subject sched_contact_mod_anniv',
457 $this->fixtures
['sched_eventtype_start_1week_before'] = array(
458 'name' => 'sched_eventtype_start_1week_before',
459 'title' => 'sched_eventtype_start_1week_before',
460 'absolute_date' => '',
461 'body_html' => '<p>body sched_eventtype_start_1week_before ({event.title})</p>',
462 'body_text' => 'body sched_eventtype_start_1week_before ({event.title})',
465 'end_frequency_interval' => '',
466 'end_frequency_unit' => '',
467 'entity_status' => '', // participant status id
468 'entity_value' => '', // event type id
472 'mapping_id' => 2, // event type
473 'msg_template_id' => '',
475 'recipient_listing' => '',
476 'recipient_manual' => '',
477 'record_activity' => 1,
478 'repetition_frequency_interval' => '',
479 'repetition_frequency_unit' => '',
480 'start_action_condition' => 'before',
481 'start_action_date' => 'event_start_date',
482 'start_action_offset' => '1',
483 'start_action_unit' => 'week',
484 'subject' => 'subject sched_eventtype_start_1week_before ({event.title})',
486 $this->fixtures
['sched_eventtype_end_2month_repeat_twice_2_weeks'] = array(
487 'name' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
488 'title' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
489 'absolute_date' => '',
490 'body_html' => '<p>body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}</p>',
491 'body_text' => 'body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
492 'end_action' => 'after',
493 'end_date' => 'event_end_date',
494 'end_frequency_interval' => '3',
495 'end_frequency_unit' => 'month',
496 'entity_status' => '', // participant status id
497 'entity_value' => '', // event type id
501 'mapping_id' => 2, // event type
502 'msg_template_id' => '',
504 'recipient_listing' => '',
505 'recipient_manual' => '',
506 'record_activity' => 1,
507 'repetition_frequency_interval' => '2',
508 'repetition_frequency_unit' => 'week',
509 'start_action_condition' => 'after',
510 'start_action_date' => 'event_end_date',
511 'start_action_offset' => '2',
512 'start_action_unit' => 'month',
513 'subject' => 'subject sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
516 $this->fixtures
['sched_membership_end_2month_repeat_twice_4_weeks'] = array(
517 'name' => 'sched_membership_end_2month',
518 'title' => 'sched_membership_end_2month',
519 'absolute_date' => '',
520 'body_html' => '<p>body sched_membership_end_2month</p>',
521 'body_text' => 'body sched_membership_end_2month',
523 'end_date' => 'membership_end_date',
524 'end_frequency_interval' => '4',
525 'end_frequency_unit' => 'month',
526 'entity_status' => '',
527 'entity_value' => '',
532 'msg_template_id' => '',
534 'recipient_listing' => '',
535 'recipient_manual' => '',
536 'record_activity' => 1,
537 'repetition_frequency_interval' => '4',
538 'repetition_frequency_unit' => 'week',
539 'start_action_condition' => 'after',
540 'start_action_date' => 'membership_end_date',
541 'start_action_offset' => '2',
542 'start_action_unit' => 'month',
543 'subject' => 'subject sched_membership_end_2month',
545 $this->fixtures
['sched_membership_end_limit_to_none'] = array(
546 'name' => 'limit to none',
547 'title' => 'limit to none',
548 'absolute_date' => '',
549 'body_html' => '<p>body sched_membership_end_2month</p>',
550 'body_text' => 'body sched_membership_end_2month',
553 'end_frequency_interval' => '4',
554 'end_frequency_unit' => 'month',
555 'entity_status' => '',
556 'entity_value' => '',
562 'msg_template_id' => '',
564 'recipient_listing' => '',
565 'recipient_manual' => '',
566 'record_activity' => 1,
567 'repetition_frequency_interval' => '4',
568 'repetition_frequency_unit' => 'week',
569 'start_action_condition' => 'after',
570 'start_action_date' => 'membership_end_date',
571 'start_action_offset' => '2',
572 'start_action_unit' => 'month',
573 'subject' => 'limit to none',
575 $this->fixtures
['sched_on_membership_end_date_repeat_interval'] = array(
576 'name' => 'sched_on_membership_end_date',
577 'title' => 'sched_on_membership_end_date',
578 'body_html' => '<p>Your membership expired 1 unit ago</p>',
579 'body_text' => 'Your membership expired 1 unit ago',
580 'end_frequency_interval' => 10,
581 'end_frequency_unit' => 'year',
585 'record_activity' => 1,
586 'start_action_condition' => 'after',
587 'start_action_date' => 'membership_end_date',
588 'start_action_offset' => '0',
589 'start_action_unit' => 'hour',
590 'subject' => 'subject send reminder every unit after membership_end_date',
597 * Tears down the fixture, for example, closes a network connection.
599 * This method is called after a test is executed.
601 public function tearDown() {
604 $this->mut
->clearMessages();
607 $this->quickCleanup(array(
608 'civicrm_action_schedule',
609 'civicrm_action_log',
610 'civicrm_membership',
611 'civicrm_participant',
618 public function mailerExamples() {
621 $manyTokensTmpl = implode(';;', array(
622 '{contact.display_name}', // basic contact token
623 '{contact.gender}', // funny legacy contact token
624 '{contact.gender_id}', // funny legacy contact token
625 '{domain.name}', // domain token
626 '{activity.activity_type}', // action-scheduler token
628 // Note: The behavior of domain-tokens on a scheduled reminder is undefined. All we
629 // can really do is check that it has something.
630 $manyTokensExpected = 'test-member@example.com;;Female;;Female;;[a-zA-Z0-9 ]+;;Phone Call';
632 // In this example, we use a lot of tokens cutting across multiple components..
634 // Schedule definition.
636 'subject' => "subj $manyTokensTmpl",
637 'body_html' => "html $manyTokensTmpl",
638 'body_text' => "text $manyTokensTmpl",
640 // Assertions (regex).
642 'from_name' => "/^FIXME\$/",
643 'from_email' => "/^info@EXAMPLE.ORG\$/",
644 'subject' => "/^subj $manyTokensExpected\$/",
645 'body_html' => "/^html $manyTokensExpected\$/",
646 'body_text' => "/^text $manyTokensExpected\$/",
650 // In this example, we customize the from address.
652 // Schedule definition.
654 'from_name' => 'Bob',
655 'from_email' => 'bob@example.org',
657 // Assertions (regex).
659 'from_name' => "/^Bob\$/",
660 'from_email' => "/^bob@example.org\$/",
664 // In this example, we autoconvert HTML to text
666 // Schedule definition.
668 'body_html' => '<p>Hello & stuff.</p>',
671 // Assertions (regex).
673 'body_html' => '/^' . preg_quote('<p>Hello & stuff.</p>', '/') . '/',
674 'body_text' => '/^' . preg_quote('Hello & stuff.', '/') . '/',
678 // In this example, we autoconvert HTML to text
680 // Schedule definition.
683 'body_text' => 'Hello world',
685 // Assertions (regex).
687 'body_html' => '/^--UNDEFINED--$/',
688 'body_text' => '/^Hello world$/',
696 * This generates a single mailing through the scheduled-reminder
697 * system (using an activity-reminder as a baseline) and
698 * checks that the resulting message satisfies various
699 * regular expressions.
701 * @param array $schedule
702 * Values to set/override in the schedule.
703 * Ex: array('subject' => 'Hello, {contact.first_name}!').
704 * @param array $patterns
705 * A list of regexes to compare with the actual email.
706 * Ex: array('subject' => '/^Hello, Alice!/').
707 * Keys: subject, body_text, body_html, from_name, from_email.
708 * @dataProvider mailerExamples
710 public function testMailer($schedule, $patterns) {
711 $actionSchedule = array_merge($this->fixtures
['sched_activity_1day'], $schedule);
712 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
713 $this->assertTrue(is_numeric($actionScheduleDao->id
));
715 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures
['phonecall']);
716 $this->assertTrue(is_numeric($activity->id
));
717 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures
['contact']);
720 $source['contact_id'] = $contact['id'];
721 $source['activity_id'] = $activity->id
;
722 $source['record_type_id'] = 2;
723 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
724 $activityContact->save();
726 CRM_Utils_Time
::setTime('2012-06-14 15:00:00');
727 $this->callAPISuccess('job', 'send_reminder', array());
728 $this->mut
->assertRecipients(array(array('test-member@example.com')));
729 foreach ($this->mut
->getAllMessages('ezc') as $message) {
730 /** @var ezcMail $message */
732 $messageArray = array();
733 $messageArray['subject'] = $message->subject
;
734 $messageArray['from_name'] = $message->from
->name
;
735 $messageArray['from_email'] = $message->from
->email
;
736 $messageArray['body_text'] = '--UNDEFINED--';
737 $messageArray['body_html'] = '--UNDEFINED--';
739 foreach ($message->fetchParts() as $part) {
740 /** @var ezcMailText ezcMailText */
741 if ($part instanceof ezcMailText
&& $part->subType
== 'html') {
742 $messageArray['body_html'] = $part->text
;
744 if ($part instanceof ezcMailText
&& $part->subType
== 'plain') {
745 $messageArray['body_text'] = $part->text
;
749 foreach ($patterns as $field => $pattern) {
750 $this->assertRegExp($pattern, $messageArray[$field],
751 "Check that '$field'' matches regex. " . print_r(array('expected' => $patterns, 'actual' => $messageArray), 1));
754 $this->mut
->clearMessages();
758 public function testActivityDateTimeMatchNonRepeatableSchedule() {
759 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($this->fixtures
['sched_activity_1day']);
760 $this->assertTrue(is_numeric($actionScheduleDao->id
));
762 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures
['phonecall']);
763 $this->assertTrue(is_numeric($activity->id
));
764 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures
['contact']);
767 $source['contact_id'] = $contact['id'];
768 $source['activity_id'] = $activity->id
;
769 $source['record_type_id'] = 2;
770 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
771 $activityContact->save();
773 $this->assertCronRuns(array(
775 // Before the 24-hour mark, no email
776 'time' => '2012-06-14 04:00:00',
777 'recipients' => array(),
778 'subjects' => array(),
781 // After the 24-hour mark, an email
782 'time' => '2012-06-14 15:00:00',
783 'recipients' => array(array('test-member@example.com')),
784 'subjects' => array('1-Day (non-repeating) (about Phone Call)'),
787 // Run cron again; message already sent
789 'recipients' => array(),
794 public function testActivityDateTimeMatchRepeatableSchedule() {
795 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($this->fixtures
['sched_activity_1day_r']);
796 $this->assertTrue(is_numeric($actionScheduleDao->id
));
798 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures
['phonecall']);
799 $this->assertTrue(is_numeric($activity->id
));
800 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures
['contact']);
803 $source['contact_id'] = $contact['id'];
804 $source['activity_id'] = $activity->id
;
805 $source['record_type_id'] = 2;
806 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
807 $activityContact->save();
809 $this->assertCronRuns(array(
811 // Before the 24-hour mark, no email
812 'time' => '012-06-14 04:00:00',
813 'recipients' => array(),
814 'subjects' => array(),
817 // After the 24-hour mark, an email
818 'time' => '2012-06-14 15:00:00',
819 'recipients' => array(array('test-member@example.com')),
820 'subjects' => array('1-Day (repeating) (about Phone Call)'),
823 // Run cron 4 hours later; first message already sent
824 'time' => '2012-06-14 20:00:00',
825 'recipients' => array(),
826 'subjects' => array(),
829 // Run cron 6 hours later; send second message.
830 'time' => '2012-06-14 21:00:01',
831 'recipients' => array(array('test-member@example.com')),
832 'subjects' => array('1-Day (repeating) (about Phone Call)'),
838 * For contacts/activities which don't match the schedule filter,
839 * an email should *not* be sent.
841 // TODO // function testActivityDateTime_NonMatch() { }
844 * For contacts/members which match schedule based on join date,
845 * an email should be sent.
847 public function testMembershipJoinDateMatch() {
848 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 1)));
849 $this->assertTrue(is_numeric($membership->id
));
850 $result = $this->callAPISuccess('Email', 'create', array(
851 'contact_id' => $membership->contact_id
,
852 'email' => 'test-member@example.com',
853 'location_type_id' => 1,
855 $this->assertAPISuccess($result);
857 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
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
));
863 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
864 $this->assertCronRuns(array(
866 // Before the 2-week mark, no email.
867 'time' => '2012-03-28 01:00:00',
868 'recipients' => array(),
869 'subjects' => array(),
872 // After the 2-week mark, send an email.
873 'time' => '2012-03-29 01:00:00',
874 'recipients' => array(array('test-member@example.com')),
875 'subjects' => array('subject sched_membership_join_2week (joined March 15th, 2012)'),
881 * Test end date email sent.
883 * For contacts/members which match schedule based on join date,
884 * an email should be sent.
886 public function testMembershipJoinDateNonMatch() {
887 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $this->fixtures
['rolling_membership']);
888 $this->assertTrue(is_numeric($membership->id
));
889 $result = $this->callAPISuccess('Email', 'create', array(
890 'contact_id' => $membership->contact_id
,
891 'location_type_id' => 1,
892 'email' => 'test-member@example.com',
895 // Add an alternative membership type, and only send messages for that type
896 $extraMembershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', array());
897 $this->assertTrue(is_numeric($extraMembershipType->id
));
898 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($this->fixtures
['sched_membership_join_2week']);
899 $this->assertTrue(is_numeric($actionScheduleDao->id
));
900 $actionScheduleDao->entity_value
= $extraMembershipType->id
;
901 $actionScheduleDao->save();
903 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
904 $this->assertCronRuns(array(
906 // After the 2-week mark, don't send email because we have different membership type.
907 'time' => '2012-03-29 01:00:00',
908 'recipients' => array(),
914 * Test that the first and SECOND notifications are sent out.
916 public function testMembershipEndDateRepeat() {
917 // creates membership with end_date = 20120615
918 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
919 $result = $this->callAPISuccess('Email', 'create', array(
920 'contact_id' => $membership->contact_id
,
921 'email' => 'test-member@example.com',
923 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
925 $actionSchedule = $this->fixtures
['sched_membership_end_2month_repeat_twice_4_weeks'];
926 $actionSchedule['entity_value'] = $membership->membership_type_id
;
927 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
929 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
930 $this->assertCronRuns(array(
932 // After the 2-week mark, send an email.
933 'time' => '2012-08-15 01:00:00',
934 'recipients' => array(array('test-member@example.com')),
937 // After the 2-week mark, send an email.
938 'time' => '2012-09-12 01:00:00',
939 'recipients' => array(array('test-member@example.com')),
945 * Test behaviour when date changes.
947 * Test that the first notification is sent but the second is NOT sent if the end date changes in
951 public function testMembershipEndDateRepeatChangedEndDate_CRM_15376() {
952 // creates membership with end_date = 20120615
953 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
954 $this->callAPISuccess('Email', 'create', array(
955 'contact_id' => $membership->contact_id
,
956 'email' => 'test-member@example.com',
958 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
960 $actionSchedule = $this->fixtures
['sched_membership_end_2month_repeat_twice_4_weeks'];
961 $actionSchedule['entity_value'] = $membership->membership_type_id
;
962 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
963 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
964 $this->assertCronRuns(array(
966 // After the 2-week mark, send an email.
967 'time' => '2012-08-15 01:00:00',
968 'recipients' => array(array('test-member@example.com')),
972 // Extend membership - reminder should NOT go out.
973 $this->callAPISuccess('membership', 'create', array('id' => $membership->id
, 'end_date' => '2014-01-01'));
974 $this->assertCronRuns(array(
976 // After the 2-week mark, send an email.
977 'time' => '2012-09-12 01:00:00',
978 'recipients' => array(),
984 * Test membership end date email sends.
986 * For contacts/members which match schedule based on end date,
987 * an email should be sent.
989 public function testMembershipEndDateMatch() {
990 // creates membership with end_date = 20120615
991 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
992 $this->assertTrue(is_numeric($membership->id
));
993 $this->callAPISuccess('Email', 'create', array(
994 'contact_id' => $membership->contact_id
,
995 'email' => 'test-member@example.com',
997 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
999 $actionSchedule = $this->fixtures
['sched_membership_end_2week'];
1000 $actionSchedule['entity_value'] = $membership->membership_type_id
;
1001 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1002 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1004 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1005 $this->assertCronRuns(array(
1007 // Before the 2-week mark, no email.
1008 'time' => '2012-05-31 01:00:00',
1009 // 'time' => '2012-06-01 01:00:00',
1010 // FIXME: Is this the right boundary?
1011 'recipients' => array(),
1014 // After the 2-week mark, send an email.
1015 'time' => '2012-06-01 01:00:00',
1016 'recipients' => array(array('test-member@example.com')),
1020 // Now suppose user has renewed for rolling membership after 3 months, so upcoming assertion is written
1021 // to ensure that new reminder is sent 2 week before the new end_date i.e. '2012-09-15'
1022 $membership->end_date
= '2012-09-15';
1023 $membership->save();
1025 //change the email id of chosen membership contact to assert
1026 //recipient of not the previously sent mail but the new one
1027 $result = $this->callAPISuccess('Email', 'create', array(
1029 'contact_id' => $membership->contact_id
,
1030 'email' => 'member2@example.com',
1032 $this->assertAPISuccess($result);
1034 // end_date=2012-09-15 ; schedule is 2 weeks before end_date
1035 $this->assertCronRuns(array(
1037 // Before the 2-week mark, no email
1038 'time' => '2012-08-31 01:00:00',
1039 'recipients' => array(),
1041 //array( // After the 2-week mark, send an email
1042 //'time' => '2012-09-01 01:00:00',
1043 //'recipients' => array(array('member2@example.com')),
1050 * Test membership end date email.
1052 * For contacts/members which match schedule based on end date,
1053 * an email should be sent.
1055 public function testMembershipEndDateNoMatch() {
1056 // creates membership with end_date = 20120615
1057 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 3)));
1058 $this->assertTrue(is_numeric($membership->id
));
1059 $result = $this->callAPISuccess('Email', 'create', array(
1060 'contact_id' => $membership->contact_id
,
1061 'email' => 'test-member@example.com',
1063 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
1065 $actionSchedule = $this->fixtures
['sched_membership_end_2month'];
1066 $actionSchedule['entity_value'] = $membership->membership_type_id
;
1067 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1068 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1070 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1071 $this->assertCronRuns(array(
1073 // Before the 2-week mark, no email.
1074 'time' => '2012-05-31 01:00:00',
1075 // 'time' => '2012-06-01 01:00:00',
1076 // FIXME: Is this the right boundary?
1077 'recipients' => array(),
1080 // After the 2-week mark, send an email.
1081 'time' => '2013-05-01 01:00:00',
1082 'recipients' => array(),
1087 public function testContactBirthDateNoAnniv() {
1088 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures
['contact_birthdate']);
1089 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1090 $actionSchedule = $this->fixtures
['sched_contact_bday_yesterday'];
1091 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1092 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1093 $this->assertCronRuns(array(
1095 // On the birthday, no email.
1096 'time' => '2005-07-07 01:00:00',
1097 'recipients' => array(),
1100 // The next day, send an email.
1101 'time' => '2005-07-08 20:00:00',
1102 'recipients' => array(array('test-bday@example.com')),
1107 public function testContactBirthDateAnniversary() {
1108 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures
['contact_birthdate']);
1109 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1110 $actionSchedule = $this->fixtures
['sched_contact_bday_anniv'];
1111 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1112 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1113 $this->assertCronRuns(array(
1115 // On some random day, no email.
1116 'time' => '2014-03-07 01:00:00',
1117 'recipients' => array(),
1120 // On the eve of their 9th birthday, send an email.
1121 'time' => '2014-07-06 20:00:00',
1122 'recipients' => array(array('test-bday@example.com')),
1127 public function testContactCustomDateNoAnniv() {
1129 'title' => 'Test_Group',
1130 'name' => 'test_group',
1131 'extends' => array('Individual'),
1132 'style' => 'Inline',
1133 'is_multiple' => FALSE,
1136 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
1138 'label' => 'Graduation',
1139 'data_type' => 'Date',
1140 'html_type' => 'Select Date',
1141 'custom_group_id' => $createGroup['id'],
1143 $createField = $this->callAPISuccess('custom_field', 'create', $field);
1144 $contactParams = $this->fixtures
['contact'];
1145 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
1146 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
1147 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1148 $actionSchedule = $this->fixtures
['sched_contact_grad_tomorrow'];
1149 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1150 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1151 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1152 $this->assertCronRuns(array(
1154 // On some random day, no email.
1155 'time' => '2014-03-07 01:00:00',
1156 'recipients' => array(),
1159 // On the eve of their graduation, send an email.
1160 'time' => '2013-12-15 20:00:00',
1161 'recipients' => array(array('test-member@example.com')),
1164 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
1167 public function testContactCreatedNoAnniv() {
1168 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures
['contact_birthdate']);
1169 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1170 $actionSchedule = $this->fixtures
['sched_contact_created_yesterday'];
1171 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1172 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1173 $this->assertCronRuns(array(
1175 // On the date created, no email.
1176 'time' => $contact['values'][$contact['id']]['created_date'],
1177 'recipients' => array(),
1180 // The next day, send an email.
1181 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['created_date'] . ' +1 day')),
1182 'recipients' => array(array('test-bday@example.com')),
1187 public function testContactModifiedAnniversary() {
1188 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures
['contact_birthdate']);
1189 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1190 $actionSchedule = $this->fixtures
['sched_contact_mod_anniv'];
1191 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1192 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1193 $this->assertCronRuns(array(
1195 // On some random day, no email.
1196 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['modified_date'] . ' -60 days')),
1197 'recipients' => array(),
1200 // On the eve of 3 years after they were modified, send an email.
1201 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['modified_date'] . ' +3 years -23 hours')),
1202 'recipients' => array(array('test-bday@example.com')),
1208 * Check that limit_to + an empty recipients doesn't sent to multiple contacts.
1210 public function testMembershipLimitToNone() {
1211 // creates membership with end_date = 20120615
1212 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
1214 $this->assertTrue(is_numeric($membership->id
));
1215 $result = $this->callAPISuccess('Email', 'create', array(
1216 'contact_id' => $membership->contact_id
,
1217 'email' => 'member@example.com',
1219 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
1220 $this->callAPISuccess('contact', 'create', array('email' => 'b@c.com', 'contact_type' => 'Individual'));
1222 $this->assertAPISuccess($result);
1224 $actionSchedule = $this->fixtures
['sched_membership_end_limit_to_none'];
1225 $actionSchedule['entity_value'] = $membership->membership_type_id
;
1226 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1227 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1229 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1230 $this->assertCronRuns(array(
1232 // Before the 2-week mark, no email.
1233 'time' => '2012-05-31 01:00:00',
1234 // 'time' => '2012-06-01 01:00:00', // FIXME: Is this the right boundary?
1235 'recipients' => array(),
1240 public function testMembership_referenceDate() {
1241 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
1243 $this->assertTrue(is_numeric($membership->id
));
1244 $result = $this->callAPISuccess('Email', 'create', array(
1245 'contact_id' => $membership->contact_id
,
1246 'email' => 'member@example.com',
1249 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
1250 $this->assertAPISuccess($result);
1252 $actionSchedule = $this->fixtures
['sched_membership_join_2week'];
1253 $actionSchedule['entity_value'] = $membership->membership_type_id
;
1254 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1255 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1257 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
1258 $this->assertCronRuns(array(
1260 // After the 2-week mark, send an email
1261 'time' => '2012-03-29 01:00:00',
1262 'recipients' => array(array('member@example.com')),
1265 // After the 2-week 1day mark, don't send an email
1266 'time' => '2012-03-30 01:00:00',
1267 'recipients' => array(),
1271 //check if reference date is set to membership's join date
1272 //as per the action_start_date chosen for current schedule reminder
1273 $this->assertEquals('2012-03-15',
1274 CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_ActionLog', $membership->contact_id
, 'reference_date', 'contact_id')
1277 //change current membership join date that may signifies as membership renewal activity
1278 $membership->join_date
= '2012-03-29';
1279 $membership->save();
1281 $this->assertCronRuns(array(
1283 // After the 13 days of the changed join date 2012-03-29, don't send an email
1284 'time' => '2012-04-11 01:00:00',
1285 'recipients' => array(),
1288 // After the 2-week of the changed join date 2012-03-29, send an email
1289 'time' => '2012-04-12 01:00:00',
1290 'recipients' => array(array('member@example.com')),
1295 public function testMembershipOnMultipleReminder() {
1296 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures
['rolling_membership'], array('status_id' => 2)));
1298 $this->assertTrue(is_numeric($membership->id
));
1299 $result = $this->callAPISuccess('Email', 'create', array(
1300 'contact_id' => $membership->contact_id
,
1301 'email' => 'member@example.com',
1303 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $membership->contact_id
)));
1304 $this->assertAPISuccess($result);
1306 $actionScheduleBefore = $this->fixtures
['sched_membership_end_2week']; // Send email 2 weeks before end_date
1307 $actionScheduleOn = $this->fixtures
['sched_on_membership_end_date']; // Send email on end_date/expiry date
1308 $actionScheduleAfter = $this->fixtures
['sched_after_1day_membership_end_date']; // Send email 1 day after end_date/grace period
1309 $actionScheduleBefore['entity_value'] = $actionScheduleOn['entity_value'] = $actionScheduleAfter['entity_value'] = $membership->membership_type_id
;
1310 foreach (array('actionScheduleBefore', 'actionScheduleOn', 'actionScheduleAfter') as $value) {
1311 $
$value = CRM_Core_BAO_ActionSchedule
::add($
$value);
1312 $this->assertTrue(is_numeric($
$value->id
));
1315 $this->assertCronRuns(
1318 // 1day 2weeks before membership end date(MED), don't send mail
1319 'time' => '2012-05-31 01:00:00',
1320 'recipients' => array(),
1323 // 2 weeks before MED, send an email
1324 'time' => '2012-06-01 01:00:00',
1325 'recipients' => array(array('member@example.com')),
1328 // 1day before MED, don't send mail
1329 'time' => '2012-06-14 01:00:00',
1330 'recipients' => array(),
1333 // On MED, send an email
1334 'time' => '2012-06-15 00:00:00',
1335 'recipients' => array(array('member@example.com')),
1338 // After 1day of MED, send an email
1339 'time' => '2012-06-16 01:00:00',
1340 'recipients' => array(array('member@example.com')),
1343 // After 1day 1min of MED, don't send an email
1344 'time' => '2012-06-17 00:01:00',
1345 'recipients' => array(),
1350 // Assert the timestamp as of when the emails of respective three reminders as configured
1351 // 2 weeks before, on and 1 day after MED, are sent
1352 $this->assertApproxEquals(
1353 strtotime('2012-06-01 01:00:00'),
1354 strtotime(CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleBefore->id
, 'action_date_time', 'action_schedule_id', TRUE)),
1355 3 // Variation in test execution time.
1357 $this->assertApproxEquals(
1358 strtotime('2012-06-15 00:00:00'),
1359 strtotime(CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleOn->id
, 'action_date_time', 'action_schedule_id', TRUE)),
1360 3 // Variation in test execution time.
1362 $this->assertApproxEquals(
1363 strtotime('2012-06-16 01:00:00'),
1364 strtotime(CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleAfter->id
, 'action_date_time', 'action_schedule_id', TRUE)),
1365 3 // Variation in test execution time.
1368 //extend MED to 2 weeks after the current MED (that may signifies as membership renewal activity)
1369 // and lets assert as of when the new set of reminders will be sent against their respective Schedule Reminders(SR)
1370 $membership->end_date
= '2012-06-20';
1371 $membership->save();
1373 $result = $this->callAPISuccess('Contact', 'get', array('id' => $membership->contact_id
));
1374 $this->assertCronRuns(
1377 // 1day 2weeks before membership end date(MED), don't send mail
1378 'time' => '2012-06-05 01:00:00',
1379 'recipients' => array(),
1382 // 2 weeks before MED, send an email
1383 'time' => '2012-06-06 01:00:00',
1384 'recipients' => array(array('member@example.com')),
1387 // 1day before MED, don't send mail
1388 'time' => '2012-06-19 01:00:00',
1389 'recipients' => array(),
1392 // On MED, send an email
1393 'time' => '2012-06-20 00:00:00',
1394 'recipients' => array(array('member@example.com')),
1397 // After 1day of MED, send an email
1398 'time' => '2012-06-21 01:00:00',
1399 'recipients' => array(array('member@example.com')),
1402 // After 1day 1min of MED, don't send an email
1403 'time' => '2012-07-21 00:01:00',
1404 'recipients' => array(),
1409 public function testContactCustomDate_Anniv() {
1411 'title' => 'Test_Group now',
1412 'name' => 'test_group_now',
1413 'extends' => array('Individual'),
1414 'style' => 'Inline',
1415 'is_multiple' => FALSE,
1418 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
1420 'label' => 'Graduation',
1421 'data_type' => 'Date',
1422 'html_type' => 'Select Date',
1423 'custom_group_id' => $createGroup['id'],
1425 $createField = $this->callAPISuccess('custom_field', 'create', $field);
1427 $contactParams = $this->fixtures
['contact'];
1428 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
1429 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
1430 $this->_testObjects
['CRM_Contact_DAO_Contact'][] = $contact['id'];
1431 $actionSchedule = $this->fixtures
['sched_contact_grad_anniv'];
1432 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1433 $actionScheduleDao = CRM_Core_BAO_ActionSchedule
::add($actionSchedule);
1434 $this->assertTrue(is_numeric($actionScheduleDao->id
));
1435 $this->assertCronRuns(array(
1437 // On some random day, no email.
1438 'time' => '2014-03-07 01:00:00',
1439 'recipients' => array(),
1442 // A week after their 5th anniversary of graduation, send an email.
1443 'time' => '2018-12-23 20:00:00',
1444 'recipients' => array(array('test-member@example.com')),
1447 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
1450 public function testEventTypeStartDate() {
1451 // Create event+participant with start_date = 20120315, end_date = 20120615.
1452 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures
['participant'], array('status_id' => 2)));
1453 $this->callAPISuccess('Email', 'create', array(
1454 'contact_id' => $participant->contact_id
,
1455 'email' => 'test-event@example.com',
1457 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $participant->contact_id
)));
1459 $actionSchedule = $this->fixtures
['sched_eventtype_start_1week_before'];
1460 $actionSchedule['entity_value'] = CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $participant->event_id
, 'event_type_id');
1461 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1463 //echo "CREATED\n"; ob_flush(); sleep(20);
1465 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1466 $this->assertCronRuns(array(
1469 'time' => '2012-03-02 01:00:00',
1470 'recipients' => array(),
1474 'time' => '2012-03-08 01:00:00',
1475 'recipients' => array(array('test-event@example.com')),
1478 // And then nothing else
1479 'time' => '2012-03-16 01:00:00',
1480 'recipients' => array(),
1485 public function testEventTypeEndDateRepeat() {
1486 // Create event+participant with start_date = 20120315, end_date = 20120615.
1487 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures
['participant'], array('status_id' => 2)));
1488 $this->callAPISuccess('Email', 'create', array(
1489 'contact_id' => $participant->contact_id
,
1490 'email' => 'test-event@example.com',
1492 $c = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures
['contact'], array('contact_id' => $participant->contact_id
)));
1494 $actionSchedule = $this->fixtures
['sched_eventtype_end_2month_repeat_twice_2_weeks'];
1495 $actionSchedule['entity_value'] = CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $participant->event_id
, 'event_type_id');
1496 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1498 $this->assertCronRuns(array(
1501 'time' => '2012-08-13 01:00:00',
1502 'recipients' => array(),
1505 // After the 2-month mark, send an email.
1506 'time' => '2012-08-16 01:00:00',
1507 'recipients' => array(array('test-event@example.com')),
1510 // After 2 months and 1 week, don't repeat yet.
1511 'time' => '2012-08-23 02:00:00',
1512 'recipients' => array(),
1515 // After 2 months and 2 weeks
1516 'time' => '2012-08-30 02:00:00',
1517 'recipients' => array(array('test-event@example.com')),
1520 // After 2 months and 4 week
1521 'time' => '2012-09-13 02:00:00',
1522 'recipients' => array(array('test-event@example.com')),
1525 // After 2 months and 6 weeks
1526 'time' => '2012-09-27 01:00:00',
1527 'recipients' => array(),
1532 // TODO // function testMembershipEndDate_NonMatch() { }
1533 // TODO // function testEventTypeStartDate_Match() { }
1534 // TODO // function testEventTypeEndDate_Match() { }
1535 // TODO // function testEventNameStartDate_Match() { }
1536 // TODO // function testEventNameEndDate_Match() { }
1539 * Run a series of cron jobs and make an assertion about email deliveries.
1541 * @param array $cronRuns
1542 * array specifying when to run cron and what messages to expect; each item is an array with keys:
1543 * - time: string, e.g. '2012-06-15 21:00:01'
1544 * - recipients: array(array(string)), list of email addresses which should receive messages
1546 public function assertCronRuns($cronRuns) {
1547 foreach ($cronRuns as $cronRun) {
1548 CRM_Utils_Time
::setTime($cronRun['time']);
1549 $this->callAPISuccess('job', 'send_reminder', array());
1550 $this->mut
->assertRecipients($cronRun['recipients']);
1551 if (array_key_exists('subjects', $cronRun)) {
1552 $this->mut
->assertSubjects($cronRun['subjects']);
1554 $this->mut
->clearMessages();
1559 * @var array(DAO_Name => array(int)) List of items to garbage-collect during tearDown
1561 private $_testObjects;
1564 * Sets up the fixture, for example, opens a network connection.
1566 * This method is called before a test is executed.
1568 protected function _setUp() {
1569 $this->_testObjects
= array();
1573 * Tears down the fixture, for example, closes a network connection.
1575 * This method is called after a test is executed.
1577 protected function _tearDown() {
1579 $this->deleteTestObjects();
1583 * This is a wrapper for CRM_Core_DAO::createTestObject which tracks
1584 * created entities and provides for brainless cleanup.
1586 * @see CRM_Core_DAO::createTestObject
1589 * @param array $params
1590 * @param int $numObjects
1591 * @param bool $createOnly
1593 * @return array|NULL|object
1595 public function createTestObject($daoName, $params = array(), $numObjects = 1, $createOnly = FALSE) {
1596 $objects = CRM_Core_DAO
::createTestObject($daoName, $params, $numObjects, $createOnly);
1597 if (is_array($objects)) {
1598 $this->registerTestObjects($objects);
1601 $this->registerTestObjects(array($objects));
1607 * @param array $objects
1608 * DAO or BAO objects.
1610 public function registerTestObjects($objects) {
1611 //if (is_object($objects)) {
1612 // $objects = array($objects);
1614 foreach ($objects as $object) {
1615 $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object));
1616 $this->_testObjects
[$daoName][] = $object->id
;
1620 public function deleteTestObjects() {
1621 // Note: You might argue that the FK relations between test
1622 // objects could make this problematic; however, it should
1623 // behave intuitively as long as we mentally split our
1624 // test-objects between the "manual/primary records"
1625 // and the "automatic/secondary records"
1626 foreach ($this->_testObjects
as $daoName => $daoIds) {
1627 foreach ($daoIds as $daoId) {
1628 CRM_Core_DAO
::deleteTestObjects($daoName, array('id' => $daoId));
1631 $this->_testObjects
= array();
1635 * Test that the various repetition units work correctly.
1638 public function testRepetitionFrequencyUnit() {
1639 $membershipTypeParams = array(
1640 'duration_interval' => '1',
1641 'duration_unit' => 'year',
1643 'period_type' => 'rolling',
1645 $membershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipTypeParams);
1646 $interval_units = array('hour', 'day', 'week', 'month', 'year');
1647 foreach ($interval_units as $interval_unit) {
1648 $membershipEndDate = DateTime
::createFromFormat('Y-m-d H:i:s', "2013-03-15 00:00:00");
1649 $contactParams = array(
1650 'contact_type' => 'Individual',
1651 'first_name' => 'Test',
1652 'last_name' => "Interval $interval_unit",
1655 $contact = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
1656 $this->assertTrue(is_numeric($contact->id
));
1657 $emailParams = array(
1658 'contact_id' => $contact->id
,
1659 'email' => "test-member-{$interval_unit}@example.com",
1660 'location_type_id' => 1,
1662 $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
1663 $this->assertTrue(is_numeric($email->id
));
1664 $membershipParams = array(
1665 'membership_type_id' => $membershipType->id
,
1666 'contact_id' => $contact->id
,
1667 'join_date' => '20120315',
1668 'start_date' => '20120315',
1669 'end_date' => '20130315',
1673 $membershipParams['status-id'] = 1;
1674 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
1675 $actionScheduleParams = $this->fixtures
['sched_on_membership_end_date_repeat_interval'];
1676 $actionScheduleParams['entity_value'] = $membershipType->id
;
1677 $actionScheduleParams['repetition_frequency_unit'] = $interval_unit;
1678 $actionScheduleParams['repetition_frequency_interval'] = 2;
1679 $actionSchedule = CRM_Core_BAO_ActionSchedule
::add($actionScheduleParams);
1680 $this->assertTrue(is_numeric($actionSchedule->id
));
1681 $beforeEndDate = $this->createModifiedDateTime($membershipEndDate, '-1 day');
1682 $beforeFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+1 $interval_unit");
1683 $afterFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+2 $interval_unit");
1686 'time' => $beforeEndDate->format('Y-m-d H:i:s'),
1687 'recipients' => array(),
1690 'time' => $membershipEndDate->format('Y-m-d H:i:s'),
1691 'recipients' => array(array("test-member-{$interval_unit}@example.com")),
1694 'time' => $beforeFirstUnit->format('Y-m-d H:i:s'),
1695 'recipients' => array(),
1698 'time' => $afterFirstUnit->format('Y-m-d H:i:s'),
1699 'recipients' => array(array("test-member-{$interval_unit}@example.com")),
1702 $this->assertCronRuns($cronRuns);
1703 $actionSchedule->delete();
1704 $membership->delete();
1708 public function createModifiedDateTime($origDateTime, $modifyRule) {
1709 $newDateTime = clone($origDateTime);
1710 $newDateTime->modify($modifyRule);
1711 return $newDateTime;