Commit | Line | Data |
---|---|---|
a7a84903 AN |
1 | <?php |
2 | // This file is part of Moodle - http://moodle.org/ | |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * The forum module mail generation tests. | |
19 | * | |
20 | * @package mod_forum | |
21 | * @category external | |
22 | * @copyright 2013 Andrew Nicols | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
27 | ||
28 | global $CFG; | |
29 | ||
30 | class mod_forum_mail_testcase extends advanced_testcase { | |
31 | ||
32 | protected $helper; | |
33 | ||
34 | public function setUp() { | |
59075a43 AN |
35 | // We must clear the subscription caches. This has to be done both before each test, and after in case of other |
36 | // tests using these functions. | |
37 | \mod_forum\subscriptions::reset_forum_cache(); | |
a54702b2 | 38 | \mod_forum\subscriptions::reset_discussion_cache(); |
59075a43 | 39 | |
a7a84903 AN |
40 | global $CFG; |
41 | require_once($CFG->dirroot . '/mod/forum/lib.php'); | |
42 | ||
43 | $helper = new stdClass(); | |
44 | ||
45 | // Messaging is not compatible with transactions... | |
46 | $this->preventResetByRollback(); | |
47 | ||
48 | // Catch all messages. | |
49 | $helper->messagesink = $this->redirectMessages(); | |
50 | $helper->mailsink = $this->redirectEmails(); | |
51 | ||
52 | // Confirm that we have an empty message sink so far. | |
53 | $messages = $helper->messagesink->get_messages(); | |
54 | $this->assertEquals(0, count($messages)); | |
55 | ||
56 | $messages = $helper->mailsink->get_messages(); | |
57 | $this->assertEquals(0, count($messages)); | |
58 | ||
555837c5 AN |
59 | // Forcibly reduce the maxeditingtime to a second in the past to |
60 | // ensure that messages are sent out. | |
61 | $CFG->maxeditingtime = -1; | |
a7a84903 | 62 | |
a7a84903 AN |
63 | $this->helper = $helper; |
64 | } | |
65 | ||
66 | public function tearDown() { | |
59075a43 AN |
67 | // We must clear the subscription caches. This has to be done both before each test, and after in case of other |
68 | // tests using these functions. | |
69 | \mod_forum\subscriptions::reset_forum_cache(); | |
70 | ||
a7a84903 AN |
71 | $this->helper->messagesink->clear(); |
72 | $this->helper->messagesink->close(); | |
73 | ||
74 | $this->helper->mailsink->clear(); | |
75 | $this->helper->mailsink->close(); | |
76 | } | |
77 | ||
e7f0b4d3 AN |
78 | /** |
79 | * Perform message inbound setup for the mod_forum reply handler. | |
80 | */ | |
81 | protected function helper_spoof_message_inbound_setup() { | |
82 | global $CFG, $DB; | |
83 | // Setup the default Inbound Message mailbox settings. | |
84 | $CFG->messageinbound_domain = 'example.com'; | |
85 | $CFG->messageinbound_enabled = true; | |
86 | ||
87 | // Must be no longer than 15 characters. | |
88 | $CFG->messageinbound_mailbox = 'moodlemoodle123'; | |
89 | ||
90 | $record = $DB->get_record('messageinbound_handlers', array('classname' => '\mod_forum\message\inbound\reply_handler')); | |
91 | $record->enabled = true; | |
92 | $record->id = $DB->update_record('messageinbound_handlers', $record); | |
93 | } | |
94 | ||
a7a84903 AN |
95 | /** |
96 | * Helper to create the required number of users in the specified | |
97 | * course. | |
98 | * Users are enrolled as students. | |
99 | * | |
100 | * @param stdClass $course The course object | |
101 | * @param integer $count The number of users to create | |
102 | * @return array The users created | |
103 | */ | |
104 | protected function helper_create_users($course, $count) { | |
105 | $users = array(); | |
106 | ||
107 | for ($i = 0; $i < $count; $i++) { | |
108 | $user = $this->getDataGenerator()->create_user(); | |
109 | $this->getDataGenerator()->enrol_user($user->id, $course->id); | |
110 | $users[] = $user; | |
111 | } | |
112 | ||
113 | return $users; | |
114 | } | |
115 | ||
116 | /** | |
117 | * Create a new discussion and post within the specified forum, as the | |
118 | * specified author. | |
119 | * | |
120 | * @param stdClass $forum The forum to post in | |
121 | * @param stdClass $author The author to post as | |
28c0c4af | 122 | * @param array $fields any other fields in discussion (name, message, messageformat, ...) |
a7a84903 AN |
123 | * @param array An array containing the discussion object, and the post object |
124 | */ | |
28c0c4af | 125 | protected function helper_post_to_forum($forum, $author, $fields = array()) { |
555837c5 | 126 | global $DB; |
a7a84903 AN |
127 | $generator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); |
128 | ||
129 | // Create a discussion in the forum, and then add a post to that discussion. | |
28c0c4af | 130 | $record = (object)$fields; |
a7a84903 AN |
131 | $record->course = $forum->course; |
132 | $record->userid = $author->id; | |
133 | $record->forum = $forum->id; | |
134 | $discussion = $generator->create_discussion($record); | |
135 | ||
555837c5 AN |
136 | // Retrieve the post which was created by create_discussion. |
137 | $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id)); | |
a7a84903 AN |
138 | |
139 | return array($discussion, $post); | |
140 | } | |
141 | ||
7122e154 AN |
142 | /** |
143 | * Update the post time for the specified post by $factor. | |
144 | * | |
145 | * @param stdClass $post The post to update | |
146 | * @param int $factor The amount to update by | |
147 | */ | |
148 | protected function helper_update_post_time($post, $factor) { | |
149 | global $DB; | |
150 | ||
151 | // Update the post to have a created in the past. | |
152 | $DB->set_field('forum_posts', 'created', $post->created + $factor, array('id' => $post->id)); | |
153 | } | |
154 | ||
155 | /** | |
156 | * Update the subscription time for the specified user/discussion by $factor. | |
157 | * | |
158 | * @param stdClass $user The user to update | |
159 | * @param stdClass $discussion The discussion to update for this user | |
160 | * @param int $factor The amount to update by | |
161 | */ | |
162 | protected function helper_update_subscription_time($user, $discussion, $factor) { | |
163 | global $DB; | |
164 | ||
165 | $sub = $DB->get_record('forum_discussion_subs', array('userid' => $user->id, 'discussion' => $discussion->id)); | |
166 | ||
167 | // Update the subscription to have a preference in the past. | |
168 | $DB->set_field('forum_discussion_subs', 'preference', $sub->preference + $factor, array('id' => $sub->id)); | |
169 | } | |
170 | ||
171 | /** | |
172 | * Create a new post within an existing discussion, as the specified author. | |
173 | * | |
174 | * @param stdClass $forum The forum to post in | |
175 | * @param stdClass $discussion The discussion to post in | |
176 | * @param stdClass $author The author to post as | |
177 | * @return stdClass The forum post | |
178 | */ | |
179 | protected function helper_post_to_discussion($forum, $discussion, $author) { | |
180 | global $DB; | |
181 | ||
182 | $generator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); | |
183 | ||
184 | // Add a post to the discussion. | |
185 | $record = new stdClass(); | |
186 | $record->course = $forum->course; | |
187 | $record->userid = $author->id; | |
188 | $record->forum = $forum->id; | |
189 | $record->discussion = $discussion->id; | |
190 | $record->mailnow = 1; | |
191 | ||
192 | $post = $generator->create_post($record); | |
193 | ||
194 | return $post; | |
195 | } | |
196 | ||
a7a84903 AN |
197 | /** |
198 | * Run the forum cron, and check that the specified post was sent the | |
199 | * specified number of times. | |
200 | * | |
201 | * @param stdClass $post The forum post object | |
202 | * @param integer $expected The number of times that the post should have been sent | |
203 | * @return array An array of the messages caught by the message sink | |
204 | */ | |
205 | protected function helper_run_cron_check_count($post, $expected) { | |
eb451c79 | 206 | |
a7a84903 AN |
207 | // Clear the sinks before running cron. |
208 | $this->helper->messagesink->clear(); | |
209 | $this->helper->mailsink->clear(); | |
210 | ||
211 | // Cron daily uses mtrace, turn on buffering to silence output. | |
212 | $this->expectOutputRegex("/{$expected} users were sent post {$post->id}, '{$post->subject}'/"); | |
213 | forum_cron(); | |
214 | ||
215 | // Now check the results in the message sink. | |
216 | $messages = $this->helper->messagesink->get_messages(); | |
217 | ||
218 | // There should be the expected number of messages. | |
219 | $this->assertEquals($expected, count($messages)); | |
220 | ||
221 | return $messages; | |
222 | } | |
223 | ||
eb451c79 AN |
224 | /** |
225 | * Run the forum cron, and check that the specified posts were sent the | |
226 | * specified number of times. | |
227 | * | |
228 | * @param stdClass $post The forum post object | |
229 | * @param integer $expected The number of times that the post should have been sent | |
230 | * @return array An array of the messages caught by the message sink | |
231 | */ | |
232 | protected function helper_run_cron_check_counts($posts, $expected) { | |
233 | ||
234 | // Clear the sinks before running cron. | |
235 | $this->helper->messagesink->clear(); | |
236 | $this->helper->mailsink->clear(); | |
237 | ||
238 | // Cron daily uses mtrace, turn on buffering to silence output. | |
239 | foreach ($posts as $post) { | |
240 | $this->expectOutputRegex("/{$post['count']} users were sent post {$post['id']}, '{$post['subject']}'/"); | |
241 | } | |
242 | forum_cron(); | |
243 | ||
244 | // Now check the results in the message sink. | |
245 | $messages = $this->helper->messagesink->get_messages(); | |
246 | ||
247 | // There should be the expected number of messages. | |
248 | $this->assertEquals($expected, count($messages)); | |
249 | ||
250 | return $messages; | |
251 | } | |
252 | ||
a7a84903 AN |
253 | public function test_forced_subscription() { |
254 | $this->resetAfterTest(true); | |
255 | ||
256 | // Create a course, with a forum. | |
257 | $course = $this->getDataGenerator()->create_course(); | |
258 | ||
259 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); | |
260 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
261 | ||
262 | // Create two users enrolled in the course as students. | |
263 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
264 | ||
265 | // Post a discussion to the forum. | |
266 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
267 | ||
268 | // We expect both users to receive this post. | |
269 | $expected = 2; | |
270 | ||
271 | // Run cron and check that the expected number of users received the notification. | |
272 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
273 | ||
274 | $seenauthor = false; | |
275 | $seenrecipient = false; | |
276 | foreach ($messages as $message) { | |
277 | // They should both be from our user. | |
278 | $this->assertEquals($author->id, $message->useridfrom); | |
279 | ||
280 | if ($message->useridto == $author->id) { | |
281 | $seenauthor = true; | |
282 | } else if ($message->useridto = $recipient->id) { | |
283 | $seenrecipient = true; | |
284 | } | |
285 | } | |
286 | ||
287 | // Check we saw messages for both users. | |
288 | $this->assertTrue($seenauthor); | |
289 | $this->assertTrue($seenrecipient); | |
290 | } | |
291 | ||
292 | public function test_subscription_disabled() { | |
293 | global $DB; | |
294 | ||
295 | $this->resetAfterTest(true); | |
296 | ||
297 | // Create a course, with a forum. | |
298 | $course = $this->getDataGenerator()->create_course(); | |
299 | ||
300 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_DISALLOWSUBSCRIBE); | |
301 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
302 | ||
303 | // Create two users enrolled in the course as students. | |
304 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
305 | ||
306 | // Post a discussion to the forum. | |
307 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
308 | ||
309 | // We expect both users to receive this post. | |
310 | $expected = 0; | |
311 | ||
312 | // Run cron and check that the expected number of users received the notification. | |
313 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
314 | ||
315 | // A user with the manageactivities capability within the course can subscribe. | |
316 | $expected = 1; | |
317 | $roleids = $DB->get_records_menu('role', null, '', 'shortname, id'); | |
318 | assign_capability('moodle/course:manageactivities', CAP_ALLOW, $roleids['student'], context_course::instance($course->id)); | |
7122e154 | 319 | \mod_forum\subscriptions::subscribe_user($recipient->id, $forum); |
a7a84903 AN |
320 | |
321 | $this->assertEquals($expected, $DB->count_records('forum_subscriptions', array( | |
7122e154 | 322 | 'userid' => $recipient->id, |
a7a84903 AN |
323 | 'forum' => $forum->id, |
324 | ))); | |
325 | ||
326 | // Run cron and check that the expected number of users received the notification. | |
7122e154 | 327 | list($discussion, $post) = $this->helper_post_to_forum($forum, $recipient); |
a7a84903 AN |
328 | $messages = $this->helper_run_cron_check_count($post, $expected); |
329 | ||
330 | // Unsubscribe the user again. | |
7122e154 | 331 | \mod_forum\subscriptions::unsubscribe_user($recipient->id, $forum); |
a7a84903 AN |
332 | |
333 | $expected = 0; | |
334 | $this->assertEquals($expected, $DB->count_records('forum_subscriptions', array( | |
7122e154 | 335 | 'userid' => $recipient->id, |
a7a84903 AN |
336 | 'forum' => $forum->id, |
337 | ))); | |
338 | ||
339 | // Run cron and check that the expected number of users received the notification. | |
340 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
341 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
342 | ||
7122e154 AN |
343 | // Subscribe the user to the discussion. |
344 | \mod_forum\subscriptions::subscribe_user_to_discussion($recipient->id, $discussion); | |
345 | $this->helper_update_subscription_time($recipient, $discussion, -60); | |
346 | ||
347 | $reply = $this->helper_post_to_discussion($forum, $discussion, $author); | |
348 | $this->helper_update_post_time($reply, -30); | |
349 | ||
350 | $messages = $this->helper_run_cron_check_count($reply, $expected); | |
a7a84903 AN |
351 | } |
352 | ||
353 | public function test_automatic() { | |
354 | $this->resetAfterTest(true); | |
355 | ||
356 | // Create a course, with a forum. | |
357 | $course = $this->getDataGenerator()->create_course(); | |
358 | ||
359 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE); | |
360 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
361 | ||
362 | // Create two users enrolled in the course as students. | |
363 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
364 | ||
365 | // Post a discussion to the forum. | |
366 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
367 | ||
368 | // We expect both users to receive this post. | |
369 | $expected = 2; | |
370 | ||
371 | // Run cron and check that the expected number of users received the notification. | |
372 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
373 | ||
374 | $seenauthor = false; | |
375 | $seenrecipient = false; | |
376 | foreach ($messages as $message) { | |
377 | // They should both be from our user. | |
378 | $this->assertEquals($author->id, $message->useridfrom); | |
379 | ||
380 | if ($message->useridto == $author->id) { | |
381 | $seenauthor = true; | |
382 | } else if ($message->useridto = $recipient->id) { | |
383 | $seenrecipient = true; | |
384 | } | |
385 | } | |
386 | ||
387 | // Check we saw messages for both users. | |
388 | $this->assertTrue($seenauthor); | |
389 | $this->assertTrue($seenrecipient); | |
390 | } | |
391 | ||
392 | public function test_optional() { | |
393 | $this->resetAfterTest(true); | |
394 | ||
395 | // Create a course, with a forum. | |
396 | $course = $this->getDataGenerator()->create_course(); | |
397 | ||
398 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); | |
399 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
400 | ||
401 | // Create two users enrolled in the course as students. | |
402 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
403 | ||
404 | // Post a discussion to the forum. | |
405 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
406 | ||
407 | // We expect both users to receive this post. | |
408 | $expected = 0; | |
409 | ||
410 | // Run cron and check that the expected number of users received the notification. | |
411 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
412 | } | |
413 | ||
414 | public function test_automatic_with_unsubscribed_user() { | |
415 | $this->resetAfterTest(true); | |
416 | ||
417 | // Create a course, with a forum. | |
418 | $course = $this->getDataGenerator()->create_course(); | |
419 | ||
420 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE); | |
421 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
422 | ||
423 | // Create two users enrolled in the course as students. | |
424 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
425 | ||
426 | // Unsubscribe the 'author' user from the forum. | |
59075a43 | 427 | \mod_forum\subscriptions::unsubscribe_user($author->id, $forum); |
a7a84903 AN |
428 | |
429 | // Post a discussion to the forum. | |
430 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
431 | ||
432 | // We expect only one user to receive this post. | |
433 | $expected = 1; | |
434 | ||
435 | // Run cron and check that the expected number of users received the notification. | |
436 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
437 | ||
438 | $seenauthor = false; | |
439 | $seenrecipient = false; | |
440 | foreach ($messages as $message) { | |
441 | // They should both be from our user. | |
442 | $this->assertEquals($author->id, $message->useridfrom); | |
443 | ||
444 | if ($message->useridto == $author->id) { | |
445 | $seenauthor = true; | |
446 | } else if ($message->useridto = $recipient->id) { | |
447 | $seenrecipient = true; | |
448 | } | |
449 | } | |
450 | ||
451 | // Check we only saw one user. | |
452 | $this->assertFalse($seenauthor); | |
453 | $this->assertTrue($seenrecipient); | |
454 | } | |
455 | ||
456 | public function test_optional_with_subscribed_user() { | |
457 | $this->resetAfterTest(true); | |
458 | ||
459 | // Create a course, with a forum. | |
460 | $course = $this->getDataGenerator()->create_course(); | |
461 | ||
462 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); | |
463 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
464 | ||
465 | // Create two users enrolled in the course as students. | |
466 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
467 | ||
468 | // Subscribe the 'recipient' user from the forum. | |
59075a43 | 469 | \mod_forum\subscriptions::subscribe_user($recipient->id, $forum); |
a7a84903 AN |
470 | |
471 | // Post a discussion to the forum. | |
472 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
473 | ||
474 | // We expect only one user to receive this post. | |
475 | $expected = 1; | |
476 | ||
477 | // Run cron and check that the expected number of users received the notification. | |
478 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
479 | ||
480 | $seenauthor = false; | |
481 | $seenrecipient = false; | |
482 | foreach ($messages as $message) { | |
483 | // They should both be from our user. | |
484 | $this->assertEquals($author->id, $message->useridfrom); | |
485 | ||
486 | if ($message->useridto == $author->id) { | |
487 | $seenauthor = true; | |
488 | } else if ($message->useridto = $recipient->id) { | |
489 | $seenrecipient = true; | |
490 | } | |
491 | } | |
492 | ||
493 | // Check we only saw one user. | |
494 | $this->assertFalse($seenauthor); | |
495 | $this->assertTrue($seenrecipient); | |
496 | } | |
497 | ||
49566c8a AN |
498 | public function test_automatic_with_unsubscribed_discussion() { |
499 | $this->resetAfterTest(true); | |
500 | ||
501 | // Create a course, with a forum. | |
502 | $course = $this->getDataGenerator()->create_course(); | |
503 | ||
504 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE); | |
505 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
506 | ||
507 | // Create two users enrolled in the course as students. | |
508 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
509 | ||
510 | // Post a discussion to the forum. | |
511 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
512 | ||
513 | // Unsubscribe the 'author' user from the discussion. | |
514 | \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion); | |
515 | ||
eb451c79 AN |
516 | $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id)); |
517 | $this->assertTrue(\mod_forum\subscriptions::is_subscribed($recipient->id, $forum, $discussion->id)); | |
518 | ||
49566c8a AN |
519 | // We expect only one user to receive this post. |
520 | $expected = 1; | |
521 | ||
522 | // Run cron and check that the expected number of users received the notification. | |
523 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
524 | ||
525 | $seenauthor = false; | |
526 | $seenrecipient = false; | |
527 | foreach ($messages as $message) { | |
528 | // They should both be from our user. | |
529 | $this->assertEquals($author->id, $message->useridfrom); | |
530 | ||
531 | if ($message->useridto == $author->id) { | |
532 | $seenauthor = true; | |
533 | } else if ($message->useridto = $recipient->id) { | |
534 | $seenrecipient = true; | |
535 | } | |
536 | } | |
537 | ||
538 | // Check we only saw one user. | |
539 | $this->assertFalse($seenauthor); | |
540 | $this->assertTrue($seenrecipient); | |
541 | } | |
542 | ||
543 | public function test_optional_with_subscribed_discussion() { | |
544 | $this->resetAfterTest(true); | |
545 | ||
546 | // Create a course, with a forum. | |
547 | $course = $this->getDataGenerator()->create_course(); | |
548 | ||
549 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); | |
550 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
551 | ||
552 | // Create two users enrolled in the course as students. | |
553 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
554 | ||
555 | // Post a discussion to the forum. | |
556 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
7122e154 | 557 | $this->helper_update_post_time($post, -90); |
49566c8a AN |
558 | |
559 | // Subscribe the 'recipient' user to the discussion. | |
560 | \mod_forum\subscriptions::subscribe_user_to_discussion($recipient->id, $discussion); | |
7122e154 AN |
561 | $this->helper_update_subscription_time($recipient, $discussion, -60); |
562 | ||
563 | // Initially we don't expect any user to receive this post as you cannot subscribe to a discussion until after | |
564 | // you have read it. | |
565 | $expected = 0; | |
566 | ||
567 | // Run cron and check that the expected number of users received the notification. | |
568 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
569 | ||
570 | // Have a user reply to the discussion. | |
571 | $reply = $this->helper_post_to_discussion($forum, $discussion, $author); | |
572 | $this->helper_update_post_time($reply, -30); | |
49566c8a AN |
573 | |
574 | // We expect only one user to receive this post. | |
575 | $expected = 1; | |
576 | ||
577 | // Run cron and check that the expected number of users received the notification. | |
7122e154 | 578 | $messages = $this->helper_run_cron_check_count($reply, $expected); |
49566c8a AN |
579 | |
580 | $seenauthor = false; | |
581 | $seenrecipient = false; | |
582 | foreach ($messages as $message) { | |
583 | // They should both be from our user. | |
584 | $this->assertEquals($author->id, $message->useridfrom); | |
585 | ||
586 | if ($message->useridto == $author->id) { | |
587 | $seenauthor = true; | |
588 | } else if ($message->useridto = $recipient->id) { | |
589 | $seenrecipient = true; | |
590 | } | |
591 | } | |
592 | ||
593 | // Check we only saw one user. | |
594 | $this->assertFalse($seenauthor); | |
595 | $this->assertTrue($seenrecipient); | |
596 | } | |
597 | ||
598 | public function test_automatic_with_subscribed_discussion_in_unsubscribed_forum() { | |
599 | $this->resetAfterTest(true); | |
600 | ||
601 | // Create a course, with a forum. | |
602 | $course = $this->getDataGenerator()->create_course(); | |
603 | ||
604 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE); | |
605 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
606 | ||
607 | // Create two users enrolled in the course as students. | |
608 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
609 | ||
610 | // Post a discussion to the forum. | |
611 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
7122e154 | 612 | $this->helper_update_post_time($post, -90); |
49566c8a | 613 | |
7122e154 | 614 | // Unsubscribe the 'author' user from the forum. |
49566c8a AN |
615 | \mod_forum\subscriptions::unsubscribe_user($author->id, $forum); |
616 | ||
617 | // Then re-subscribe them to the discussion. | |
618 | \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion); | |
7122e154 | 619 | $this->helper_update_subscription_time($author, $discussion, -60); |
49566c8a | 620 | |
7122e154 AN |
621 | // We expect just the user subscribed to the forum to receive this post at the moment as the discussion |
622 | // subscription time is after the post time. | |
623 | $expected = 1; | |
49566c8a AN |
624 | |
625 | // Run cron and check that the expected number of users received the notification. | |
626 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
627 | ||
628 | $seenauthor = false; | |
629 | $seenrecipient = false; | |
630 | foreach ($messages as $message) { | |
631 | // They should both be from our user. | |
632 | $this->assertEquals($author->id, $message->useridfrom); | |
633 | ||
634 | if ($message->useridto == $author->id) { | |
635 | $seenauthor = true; | |
636 | } else if ($message->useridto = $recipient->id) { | |
637 | $seenrecipient = true; | |
638 | } | |
639 | } | |
640 | ||
641 | // Check we only saw one user. | |
7122e154 AN |
642 | $this->assertFalse($seenauthor); |
643 | $this->assertTrue($seenrecipient); | |
644 | ||
645 | // Now post a reply to the original post. | |
646 | $reply = $this->helper_post_to_discussion($forum, $discussion, $author); | |
647 | $this->helper_update_post_time($reply, -30); | |
648 | ||
649 | // We expect two users to receive this post. | |
650 | $expected = 2; | |
651 | ||
652 | // Run cron and check that the expected number of users received the notification. | |
653 | $messages = $this->helper_run_cron_check_count($reply, $expected); | |
654 | ||
655 | $seenauthor = false; | |
656 | $seenrecipient = false; | |
657 | foreach ($messages as $message) { | |
658 | // They should both be from our user. | |
659 | $this->assertEquals($author->id, $message->useridfrom); | |
660 | ||
661 | if ($message->useridto == $author->id) { | |
662 | $seenauthor = true; | |
663 | } else if ($message->useridto = $recipient->id) { | |
664 | $seenrecipient = true; | |
665 | } | |
666 | } | |
667 | ||
668 | // Check we saw both users. | |
49566c8a AN |
669 | $this->assertTrue($seenauthor); |
670 | $this->assertTrue($seenrecipient); | |
671 | } | |
672 | ||
673 | public function test_optional_with_unsubscribed_discussion_in_subscribed_forum() { | |
674 | $this->resetAfterTest(true); | |
675 | ||
676 | // Create a course, with a forum. | |
677 | $course = $this->getDataGenerator()->create_course(); | |
678 | ||
679 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); | |
680 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
681 | ||
682 | // Create two users enrolled in the course as students. | |
683 | list($author, $recipient) = $this->helper_create_users($course, 2); | |
684 | ||
685 | // Post a discussion to the forum. | |
686 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
687 | ||
688 | // Unsubscribe the 'recipient' user from the discussion. | |
689 | \mod_forum\subscriptions::subscribe_user($recipient->id, $forum); | |
690 | ||
691 | // Then unsubscribe them from the discussion. | |
692 | \mod_forum\subscriptions::unsubscribe_user_from_discussion($recipient->id, $discussion); | |
693 | ||
694 | // We don't expect any users to receive this post. | |
695 | $expected = 0; | |
696 | ||
697 | // Run cron and check that the expected number of users received the notification. | |
698 | $messages = $this->helper_run_cron_check_count($post, $expected); | |
699 | } | |
eb451c79 AN |
700 | |
701 | /** | |
702 | * Test that a user unsubscribed from a forum who has subscribed to a discussion, only receives posts made after | |
703 | * they subscribed to the discussion. | |
704 | */ | |
705 | public function test_forum_discussion_subscription_forum_unsubscribed_discussion_subscribed_after_post() { | |
706 | $this->resetAfterTest(true); | |
eb451c79 AN |
707 | |
708 | // Create a course, with a forum. | |
709 | $course = $this->getDataGenerator()->create_course(); | |
710 | ||
711 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); | |
712 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
713 | ||
714 | $expectedmessages = array(); | |
715 | ||
716 | // Create a user enrolled in the course as a student. | |
717 | list($author) = $this->helper_create_users($course, 1); | |
718 | ||
719 | // Post a discussion to the forum. | |
720 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
7122e154 | 721 | $this->helper_update_post_time($post, -90); |
eb451c79 AN |
722 | |
723 | $expectedmessages[] = array( | |
724 | 'id' => $post->id, | |
725 | 'subject' => $post->subject, | |
726 | 'count' => 0, | |
727 | ); | |
728 | ||
729 | // Then subscribe the user to the discussion. | |
730 | $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion)); | |
7122e154 | 731 | $this->helper_update_subscription_time($author, $discussion, -60); |
eb451c79 AN |
732 | |
733 | // Then post a reply to the first discussion. | |
7122e154 AN |
734 | $reply = $this->helper_post_to_discussion($forum, $discussion, $author); |
735 | $this->helper_update_post_time($reply, -30); | |
eb451c79 AN |
736 | |
737 | $expectedmessages[] = array( | |
738 | 'id' => $reply->id, | |
739 | 'subject' => $reply->subject, | |
740 | 'count' => 1, | |
741 | ); | |
742 | ||
eb451c79 AN |
743 | $expectedcount = 1; |
744 | ||
745 | // Run cron and check that the expected number of users received the notification. | |
746 | $messages = $this->helper_run_cron_check_counts($expectedmessages, $expectedcount); | |
eb451c79 | 747 | } |
e7f0b4d3 AN |
748 | |
749 | public function test_forum_message_inbound_multiple_posts() { | |
750 | $this->resetAfterTest(true); | |
751 | ||
752 | // Create a course, with a forum. | |
753 | $course = $this->getDataGenerator()->create_course(); | |
754 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); | |
755 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
756 | ||
757 | // Create a user enrolled in the course as a student. | |
758 | list($author) = $this->helper_create_users($course, 1); | |
759 | ||
760 | $expectedmessages = array(); | |
761 | ||
762 | // Post a discussion to the forum. | |
763 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author); | |
764 | $this->helper_update_post_time($post, -90); | |
765 | ||
766 | $expectedmessages[] = array( | |
767 | 'id' => $post->id, | |
768 | 'subject' => $post->subject, | |
769 | 'count' => 0, | |
770 | ); | |
771 | ||
772 | // Then post a reply to the first discussion. | |
773 | $reply = $this->helper_post_to_discussion($forum, $discussion, $author); | |
774 | $this->helper_update_post_time($reply, -60); | |
775 | ||
776 | $expectedmessages[] = array( | |
777 | 'id' => $reply->id, | |
778 | 'subject' => $reply->subject, | |
779 | 'count' => 1, | |
780 | ); | |
781 | ||
782 | $expectedcount = 2; | |
783 | ||
784 | // Ensure that messageinbound is enabled and configured for the forum handler. | |
785 | $this->helper_spoof_message_inbound_setup(); | |
786 | ||
787 | $author->emailstop = '0'; | |
788 | set_user_preference('message_provider_mod_forum_posts_loggedoff', 'email', $author); | |
789 | set_user_preference('message_provider_mod_forum_posts_loggedin', 'email', $author); | |
790 | ||
791 | // Run cron and check that the expected number of users received the notification. | |
792 | // Clear the mailsink, and close the messagesink. | |
793 | $this->helper->mailsink->clear(); | |
794 | $this->helper->messagesink->close(); | |
795 | ||
796 | // Cron daily uses mtrace, turn on buffering to silence output. | |
797 | foreach ($expectedmessages as $post) { | |
798 | $this->expectOutputRegex("/{$post['count']} users were sent post {$post['id']}, '{$post['subject']}'/"); | |
799 | } | |
800 | ||
801 | forum_cron(); | |
802 | $messages = $this->helper->mailsink->get_messages(); | |
803 | ||
804 | // There should be the expected number of messages. | |
805 | $this->assertEquals($expectedcount, count($messages)); | |
806 | ||
807 | foreach ($messages as $message) { | |
808 | $this->assertRegExp('/Reply-To: moodlemoodle123\+[^@]*@example.com/', $message->header); | |
809 | } | |
810 | } | |
28c0c4af MG |
811 | |
812 | public function test_long_subject() { | |
813 | $this->resetAfterTest(true); | |
814 | ||
815 | // Create a course, with a forum. | |
816 | $course = $this->getDataGenerator()->create_course(); | |
817 | ||
818 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); | |
819 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
820 | ||
821 | // Create a user enrolled in the course as student. | |
822 | list($author) = $this->helper_create_users($course, 1); | |
823 | ||
824 | // Post a discussion to the forum. | |
825 | $subject = 'This is the very long forum post subject that somebody was very kind of leaving, it is intended to check if long subject comes in mail correctly. Thank you.'; | |
826 | $a = (object)array('courseshortname' => $course->shortname, 'forumname' => $forum->name, 'subject' => $subject); | |
827 | $expectedsubject = get_string('postmailsubject', 'forum', $a); | |
828 | list($discussion, $post) = $this->helper_post_to_forum($forum, $author, array('name' => $subject)); | |
829 | ||
830 | // Run cron and check that the expected number of users received the notification. | |
831 | $messages = $this->helper_run_cron_check_count($post, 1); | |
832 | $message = reset($messages); | |
833 | $this->assertEquals($author->id, $message->useridfrom); | |
834 | $this->assertEquals($expectedsubject, $message->subject); | |
835 | } | |
9dbbdcb4 EL |
836 | |
837 | /** | |
838 | * dataProvider for test_forum_post_email_templates(). | |
839 | */ | |
840 | public function forum_post_email_templates_provider() { | |
841 | // Base information, we'll build variations based on it. | |
842 | $base = array( | |
843 | 'user' => array('firstname' => 'Love', 'lastname' => 'Moodle', 'mailformat' => 0, 'maildigest' => 0), | |
844 | 'course' => array('shortname' => '101', 'fullname' => 'Moodle 101'), | |
845 | 'forums' => array( | |
846 | array( | |
847 | 'name' => 'Moodle Forum', | |
848 | 'forumposts' => array( | |
849 | array( | |
850 | 'name' => 'Hello Moodle', | |
851 | 'message' => 'Welcome to Moodle', | |
852 | 'messageformat' => FORMAT_MOODLE, | |
853 | 'attachments' => array( | |
854 | array( | |
855 | 'filename' => 'example.txt', | |
856 | 'filecontents' => 'Basic information about the course' | |
857 | ), | |
858 | ), | |
859 | ), | |
860 | ), | |
861 | ), | |
862 | ), | |
863 | 'expectations' => array( | |
864 | array( | |
865 | 'subject' => '.*101.*Hello', | |
866 | 'contents' => array( | |
867 | '~{$a', | |
868 | '~&(amp|lt|gt|quot|\#039);(?!course)', | |
869 | 'Attachment example.txt:\n' . | |
870 | 'http://www.example.com/moodle/pluginfile.php/\d*/mod_forum/attachment/\d*/example.txt\n', | |
871 | 'Hello Moodle', 'Moodle Forum', 'Welcome.*Moodle', 'Love Moodle', '1\d1' | |
872 | ), | |
873 | ), | |
874 | ), | |
875 | ); | |
876 | ||
877 | // Build the text cases. | |
878 | $textcases = array('Text mail without ampersands, quotes or lt/gt' => array('data' => $base)); | |
879 | ||
880 | // Single and double quotes everywhere. | |
881 | $newcase = $base; | |
882 | $newcase['user']['lastname'] = 'Moodle\''; | |
883 | // $newcase['user']['lastname'] = 'Moodle\'"'; // TODO: This breaks badly. See MDL-52136. | |
884 | $newcase['course']['shortname'] = '101\''; | |
885 | // $newcase['course']['shortname'] = '101\'"'; // TODO: This breaks badly. See MDL-52136. | |
886 | $newcase['forums'][0]['name'] = 'Moodle Forum\'"'; | |
887 | $newcase['forums'][0]['forumposts'][0]['name'] = 'Hello Moodle\'"'; | |
888 | $newcase['forums'][0]['forumposts'][0]['message'] = 'Welcome to Moodle\'"'; | |
889 | $newcase['expectations'][0]['contents'] = array( | |
890 | 'Attachment example.txt:', '~{\$a', '~&(quot|\#039);', 'Love Moodle\'', '101\'', 'Moodle Forum\'"', | |
891 | 'Hello Moodle\'"', 'Welcome to Moodle\'"'); | |
892 | $textcases['Text mail with quotes everywhere'] = array('data' => $newcase); | |
893 | ||
894 | // Lt and gt everywhere. This case is completely borked because format_string() | |
895 | // strips tags with $CFG->formatstringstriptags and also escapes < and > (correct | |
896 | // for web presentation but not for text email). See MDL-19829. | |
897 | $newcase = $base; | |
898 | $newcase['user']['lastname'] = 'Moodle>'; | |
899 | $newcase['course']['shortname'] = '101>'; | |
900 | $newcase['forums'][0]['name'] = 'Moodle Forum>'; | |
901 | $newcase['forums'][0]['forumposts'][0]['name'] = 'Hello Moodle>'; | |
902 | $newcase['forums'][0]['forumposts'][0]['message'] = 'Welcome to Moodle>'; | |
903 | $newcase['expectations'][0]['contents'] = array( | |
904 | 'Attachment example.txt:', '~{\$a', '~&gt;', 'Love Moodle>', '101>', 'Moodle Forum>', | |
905 | 'Hello Moodle>', 'Welcome to Moodle>'); | |
906 | $textcases['Text mail with gt and lt everywhere'] = array('data' => $newcase); | |
907 | ||
908 | // Ampersands everywhere. This case is completely borked because format_string() | |
909 | // escapes ampersands (correct for web presentation but not for text email). See MDL-19829. | |
910 | $newcase = $base; | |
911 | $newcase['user']['lastname'] = 'Moodle&'; | |
912 | $newcase['course']['shortname'] = '101&'; | |
913 | $newcase['forums'][0]['name'] = 'Moodle Forum&'; | |
914 | $newcase['forums'][0]['forumposts'][0]['name'] = 'Hello Moodle&'; | |
915 | $newcase['forums'][0]['forumposts'][0]['message'] = 'Welcome to Moodle&'; | |
916 | $newcase['expectations'][0]['contents'] = array( | |
917 | 'Attachment example.txt:', '~{\$a', '~&amp;', 'Love Moodle&', '101&', 'Moodle Forum&', | |
918 | 'Hello Moodle&', 'Welcome to Moodle&'); | |
919 | $textcases['Text mail with ampersands everywhere'] = array('data' => $newcase); | |
920 | ||
921 | // Now the html cases. | |
922 | $htmlcases = array(); | |
923 | ||
924 | // New base for html cases, no quotes, lts, gts or ampersands. | |
925 | $htmlbase = $base; | |
926 | $htmlbase['user']['mailformat'] = 1; | |
927 | $htmlbase['expectations'][0]['contents'] = array( | |
928 | '~{\$a', | |
929 | '~&(amp|lt|gt|quot|\#039);(?!course)', | |
930 | '<div class=3D"attachments">( *\n *)?<a href', | |
931 | '<div class=3D"subject">\n.*Hello Moodle', '>Moodle Forum', '>Welcome.*Moodle', '>Love Moodle', '>1\d1'); | |
932 | $htmlcases['HTML mail without ampersands, quotes or lt/gt'] = array('data' => $htmlbase); | |
933 | ||
934 | // Single and double quotes, lt and gt, ampersands everywhere. | |
935 | $newcase = $htmlbase; | |
936 | $newcase['user']['lastname'] = 'Moodle\'>&'; | |
937 | // $newcase['user']['lastname'] = 'Moodle\'">&'; // TODO: This breaks badly. See MDL-52136. | |
938 | $newcase['course']['shortname'] = '101\'>&'; | |
939 | // $newcase['course']['shortname'] = '101\'">&'; // TODO: This breaks badly. See MDL-52136. | |
940 | $newcase['forums'][0]['name'] = 'Moodle Forum\'">&'; | |
941 | $newcase['forums'][0]['forumposts'][0]['name'] = 'Hello Moodle\'">&'; | |
942 | $newcase['forums'][0]['forumposts'][0]['message'] = 'Welcome to Moodle\'">&'; | |
943 | $newcase['expectations'][0]['contents'] = array( | |
944 | '~{\$a', | |
945 | '~&(amp|lt|gt|quot|\#039);', | |
946 | '<div class=3D"attachments">( *\n *)?<a href', | |
947 | '<div class=3D"subject">\n.*Hello Moodle\'">&', '>Moodle Forum\'">&', | |
948 | '>Welcome.*Moodle\'">&', '>Love Moodle&\#039;>&', '>1\d1\'>&'); | |
949 | $htmlcases['HTML mail with quotes, gt, lt and ampersand everywhere'] = array('data' => $newcase); | |
950 | ||
951 | return $textcases + $htmlcases; | |
952 | } | |
953 | ||
954 | /** | |
955 | * Verify forum emails body using templates to generate the expected results. | |
956 | * | |
957 | * @dataProvider forum_post_email_templates_provider | |
958 | * @param array $data provider samples. | |
959 | */ | |
960 | public function test_forum_post_email_templates($data) { | |
961 | global $DB; | |
962 | ||
963 | $this->resetAfterTest(); | |
964 | ||
965 | // Create the course, with the specified options. | |
966 | $options = array(); | |
967 | foreach ($data['course'] as $option => $value) { | |
968 | $options[$option] = $value; | |
969 | } | |
970 | $course = $this->getDataGenerator()->create_course($options); | |
971 | ||
972 | // Create the user, with the specified options and enrol in the course. | |
973 | $options = array(); | |
974 | foreach ($data['user'] as $option => $value) { | |
975 | $options[$option] = $value; | |
976 | } | |
977 | $user = $this->getDataGenerator()->create_user($options); | |
978 | $this->getDataGenerator()->enrol_user($user->id, $course->id); | |
979 | ||
980 | // Create forums, always force susbscribed (for easy), with the specified options. | |
981 | $posts = array(); | |
982 | foreach ($data['forums'] as $dataforum) { | |
983 | $forumposts = isset($dataforum['forumposts']) ? $dataforum['forumposts'] : array(); | |
984 | unset($dataforum['forumposts']); | |
985 | $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); | |
986 | foreach ($dataforum as $option => $value) { | |
987 | $options[$option] = $value; | |
988 | } | |
989 | $forum = $this->getDataGenerator()->create_module('forum', $options); | |
990 | ||
991 | // Create posts, always for immediate delivery (for easy), with the specified options. | |
992 | foreach ($forumposts as $forumpost) { | |
993 | $attachments = isset($forumpost['attachments']) ? $forumpost['attachments'] : array(); | |
994 | unset($forumpost['attachments']); | |
995 | $postoptions = array('course' => $course->id, 'forum' => $forum->id, 'userid' => $user->id, | |
996 | 'mailnow' => 1, 'attachment' => !empty($attachments)); | |
997 | foreach ($forumpost as $option => $value) { | |
998 | $postoptions[$option] = $value; | |
999 | } | |
1000 | list($discussion, $post) = $this->helper_post_to_forum($forum, $user, $postoptions); | |
1001 | $posts[$post->subject] = $post; // Need this to verify cron output. | |
1002 | ||
1003 | // Add the attachments to the post. | |
1004 | if ($attachments) { | |
1005 | $fs = get_file_storage(); | |
1006 | foreach ($attachments as $attachment) { | |
1007 | $filerecord = array( | |
1008 | 'contextid' => context_module::instance($forum->cmid)->id, | |
1009 | 'component' => 'mod_forum', | |
1010 | 'filearea' => 'attachment', | |
1011 | 'itemid' => $post->id, | |
1012 | 'filepath' => '/', | |
1013 | 'filename' => $attachment['filename'] | |
1014 | ); | |
1015 | $fs->create_file_from_string($filerecord, $attachment['filecontents']); | |
1016 | } | |
1017 | $DB->set_field('forum_posts', 'attachment', '1', array('id' => $post->id)); | |
1018 | } | |
1019 | } | |
1020 | } | |
1021 | ||
1022 | // Clear the mailsink and close the messagesink. | |
1023 | // (surely setup should provide us this cleared but...) | |
1024 | $this->helper->mailsink->clear(); | |
1025 | $this->helper->messagesink->close(); | |
1026 | ||
1027 | // Capture and silence cron output, verifying contents. | |
1028 | foreach ($posts as $post) { | |
1029 | $this->expectOutputRegex("/1 users were sent post {$post->id}, '{$post->subject}'/"); | |
1030 | } | |
1031 | forum_cron(); // It's really annoying that we have to run cron to test this. | |
1032 | ||
1033 | // Get the mails. | |
1034 | $mails = $this->helper->mailsink->get_messages(); | |
1035 | ||
1036 | // Start testing the expectations. | |
1037 | $expectations = $data['expectations']; | |
1038 | ||
1039 | // Assert the number is the expected. | |
1040 | $this->assertSame(count($expectations), count($mails)); | |
1041 | ||
1042 | // Start processing mails, first localizing its expectations, then checking them. | |
1043 | foreach ($mails as $mail) { | |
1044 | // Find the corresponding expectation. | |
1045 | $foundexpectation = null; | |
1046 | foreach ($expectations as $key => $expectation) { | |
1047 | // All expectations must have a subject for matching. | |
1048 | if (!isset($expectation['subject'])) { | |
1049 | $this->fail('Provider expectation missing mandatory subject'); | |
1050 | } | |
1051 | if (preg_match('!' . $expectation['subject'] . '!', $mail->subject)) { | |
1052 | // If we already had found the expectation, there are non-unique subjects. Fail. | |
1053 | if (isset($foundexpectation)) { | |
1054 | $this->fail('Multiple expectations found (by subject matching). Please make them unique.'); | |
1055 | } | |
1056 | $foundexpectation = $expectation; | |
1057 | unset($expectations[$key]); | |
1058 | } | |
1059 | } | |
1060 | // Arrived here, we should have found the expectations. | |
1061 | $this->assertNotEmpty($foundexpectation, 'Expectation not found for the mail'); | |
1062 | ||
1063 | // If we have found the expectation and have contents to match, let's do it. | |
1064 | if (isset($foundexpectation) and isset($foundexpectation['contents'])) { | |
1065 | if (!is_array($foundexpectation['contents'])) { // Accept both string and array. | |
1066 | $foundexpectation['contents'] = array($foundexpectation['contents']); | |
1067 | } | |
1068 | foreach ($foundexpectation['contents'] as $content) { | |
1069 | if (strpos($content, '~') !== 0) { | |
1070 | $this->assertRegexp('#' . $content . '#m', $mail->body); | |
1071 | } else { | |
1072 | $this->assertNotRegexp('#' . substr($content, 1) . '#m', $mail->body); | |
1073 | } | |
1074 | } | |
1075 | } | |
1076 | } | |
1077 | // Finished, there should not be remaining expectations. | |
1078 | $this->assertCount(0, $expectations); | |
1079 | } | |
a7a84903 | 1080 | } |