Merge branch 'wip_MDL-40949_m28_pathsettings' of https://github.com/skodak/moodle
[moodle.git] / mod / forum / tests / mail_test.php
CommitLineData
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
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29
30class 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();
38
a7a84903
AN
39 global $CFG;
40 require_once($CFG->dirroot . '/mod/forum/lib.php');
41
42 $helper = new stdClass();
43
44 // Messaging is not compatible with transactions...
45 $this->preventResetByRollback();
46
47 // Catch all messages.
48 $helper->messagesink = $this->redirectMessages();
49 $helper->mailsink = $this->redirectEmails();
50
51 // Confirm that we have an empty message sink so far.
52 $messages = $helper->messagesink->get_messages();
53 $this->assertEquals(0, count($messages));
54
55 $messages = $helper->mailsink->get_messages();
56 $this->assertEquals(0, count($messages));
57
555837c5
AN
58 // Forcibly reduce the maxeditingtime to a second in the past to
59 // ensure that messages are sent out.
60 $CFG->maxeditingtime = -1;
a7a84903
AN
61
62 // Ensure that we don't prevent e-mail as this will cause unit test failures.
63 $CFG->noemailever = false;
64
65 $this->helper = $helper;
66 }
67
68 public function tearDown() {
59075a43
AN
69 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
70 // tests using these functions.
71 \mod_forum\subscriptions::reset_forum_cache();
72
a7a84903
AN
73 $this->helper->messagesink->clear();
74 $this->helper->messagesink->close();
75
76 $this->helper->mailsink->clear();
77 $this->helper->mailsink->close();
78 }
79
80 /**
81 * Helper to create the required number of users in the specified
82 * course.
83 * Users are enrolled as students.
84 *
85 * @param stdClass $course The course object
86 * @param integer $count The number of users to create
87 * @return array The users created
88 */
89 protected function helper_create_users($course, $count) {
90 $users = array();
91
92 for ($i = 0; $i < $count; $i++) {
93 $user = $this->getDataGenerator()->create_user();
94 $this->getDataGenerator()->enrol_user($user->id, $course->id);
95 $users[] = $user;
96 }
97
98 return $users;
99 }
100
101 /**
102 * Create a new discussion and post within the specified forum, as the
103 * specified author.
104 *
105 * @param stdClass $forum The forum to post in
106 * @param stdClass $author The author to post as
107 * @param array An array containing the discussion object, and the post object
108 */
109 protected function helper_post_to_forum($forum, $author) {
555837c5 110 global $DB;
a7a84903
AN
111 $generator = $this->getDataGenerator()->get_plugin_generator('mod_forum');
112
113 // Create a discussion in the forum, and then add a post to that discussion.
114 $record = new stdClass();
115 $record->course = $forum->course;
116 $record->userid = $author->id;
117 $record->forum = $forum->id;
118 $discussion = $generator->create_discussion($record);
119
555837c5
AN
120 // Retrieve the post which was created by create_discussion.
121 $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
a7a84903
AN
122
123 return array($discussion, $post);
124 }
125
126 /**
127 * Run the forum cron, and check that the specified post was sent the
128 * specified number of times.
129 *
130 * @param stdClass $post The forum post object
131 * @param integer $expected The number of times that the post should have been sent
132 * @return array An array of the messages caught by the message sink
133 */
134 protected function helper_run_cron_check_count($post, $expected) {
135 // Clear the sinks before running cron.
136 $this->helper->messagesink->clear();
137 $this->helper->mailsink->clear();
138
139 // Cron daily uses mtrace, turn on buffering to silence output.
140 $this->expectOutputRegex("/{$expected} users were sent post {$post->id}, '{$post->subject}'/");
141 forum_cron();
142
143 // Now check the results in the message sink.
144 $messages = $this->helper->messagesink->get_messages();
145
146 // There should be the expected number of messages.
147 $this->assertEquals($expected, count($messages));
148
149 return $messages;
150 }
151
152 public function test_forced_subscription() {
153 $this->resetAfterTest(true);
154
155 // Create a course, with a forum.
156 $course = $this->getDataGenerator()->create_course();
157
158 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
159 $forum = $this->getDataGenerator()->create_module('forum', $options);
160
161 // Create two users enrolled in the course as students.
162 list($author, $recipient) = $this->helper_create_users($course, 2);
163
164 // Post a discussion to the forum.
165 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
166
167 // We expect both users to receive this post.
168 $expected = 2;
169
170 // Run cron and check that the expected number of users received the notification.
171 $messages = $this->helper_run_cron_check_count($post, $expected);
172
173 $seenauthor = false;
174 $seenrecipient = false;
175 foreach ($messages as $message) {
176 // They should both be from our user.
177 $this->assertEquals($author->id, $message->useridfrom);
178
179 if ($message->useridto == $author->id) {
180 $seenauthor = true;
181 } else if ($message->useridto = $recipient->id) {
182 $seenrecipient = true;
183 }
184 }
185
186 // Check we saw messages for both users.
187 $this->assertTrue($seenauthor);
188 $this->assertTrue($seenrecipient);
189 }
190
191 public function test_subscription_disabled() {
192 global $DB;
193
194 $this->resetAfterTest(true);
195
196 // Create a course, with a forum.
197 $course = $this->getDataGenerator()->create_course();
198
199 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_DISALLOWSUBSCRIBE);
200 $forum = $this->getDataGenerator()->create_module('forum', $options);
201
202 // Create two users enrolled in the course as students.
203 list($author, $recipient) = $this->helper_create_users($course, 2);
204
205 // Post a discussion to the forum.
206 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
207
208 // We expect both users to receive this post.
209 $expected = 0;
210
211 // Run cron and check that the expected number of users received the notification.
212 $messages = $this->helper_run_cron_check_count($post, $expected);
213
214 // A user with the manageactivities capability within the course can subscribe.
215 $expected = 1;
216 $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
217 assign_capability('moodle/course:manageactivities', CAP_ALLOW, $roleids['student'], context_course::instance($course->id));
218 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
219
220 $this->assertEquals($expected, $DB->count_records('forum_subscriptions', array(
221 'userid' => $author->id,
222 'forum' => $forum->id,
223 )));
224
225 // Run cron and check that the expected number of users received the notification.
226 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
227 $messages = $this->helper_run_cron_check_count($post, $expected);
228
229 // Unsubscribe the user again.
230 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum);
231
232 $expected = 0;
233 $this->assertEquals($expected, $DB->count_records('forum_subscriptions', array(
234 'userid' => $author->id,
235 'forum' => $forum->id,
236 )));
237
238 // Run cron and check that the expected number of users received the notification.
239 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
240 $messages = $this->helper_run_cron_check_count($post, $expected);
241
242 // And unsubscribe the user from a new discussion
243 $expected = 1;
244 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
245 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
246 $messages = $this->helper_run_cron_check_count($post, $expected);
247 }
248
249 public function test_automatic() {
250 $this->resetAfterTest(true);
251
252 // Create a course, with a forum.
253 $course = $this->getDataGenerator()->create_course();
254
255 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
256 $forum = $this->getDataGenerator()->create_module('forum', $options);
257
258 // Create two users enrolled in the course as students.
259 list($author, $recipient) = $this->helper_create_users($course, 2);
260
261 // Post a discussion to the forum.
262 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
263
264 // We expect both users to receive this post.
265 $expected = 2;
266
267 // Run cron and check that the expected number of users received the notification.
268 $messages = $this->helper_run_cron_check_count($post, $expected);
269
270 $seenauthor = false;
271 $seenrecipient = false;
272 foreach ($messages as $message) {
273 // They should both be from our user.
274 $this->assertEquals($author->id, $message->useridfrom);
275
276 if ($message->useridto == $author->id) {
277 $seenauthor = true;
278 } else if ($message->useridto = $recipient->id) {
279 $seenrecipient = true;
280 }
281 }
282
283 // Check we saw messages for both users.
284 $this->assertTrue($seenauthor);
285 $this->assertTrue($seenrecipient);
286 }
287
288 public function test_optional() {
289 $this->resetAfterTest(true);
290
291 // Create a course, with a forum.
292 $course = $this->getDataGenerator()->create_course();
293
294 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
295 $forum = $this->getDataGenerator()->create_module('forum', $options);
296
297 // Create two users enrolled in the course as students.
298 list($author, $recipient) = $this->helper_create_users($course, 2);
299
300 // Post a discussion to the forum.
301 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
302
303 // We expect both users to receive this post.
304 $expected = 0;
305
306 // Run cron and check that the expected number of users received the notification.
307 $messages = $this->helper_run_cron_check_count($post, $expected);
308 }
309
310 public function test_automatic_with_unsubscribed_user() {
311 $this->resetAfterTest(true);
312
313 // Create a course, with a forum.
314 $course = $this->getDataGenerator()->create_course();
315
316 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
317 $forum = $this->getDataGenerator()->create_module('forum', $options);
318
319 // Create two users enrolled in the course as students.
320 list($author, $recipient) = $this->helper_create_users($course, 2);
321
322 // Unsubscribe the 'author' user from the forum.
59075a43 323 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum);
a7a84903
AN
324
325 // Post a discussion to the forum.
326 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
327
328 // We expect only one user to receive this post.
329 $expected = 1;
330
331 // Run cron and check that the expected number of users received the notification.
332 $messages = $this->helper_run_cron_check_count($post, $expected);
333
334 $seenauthor = false;
335 $seenrecipient = false;
336 foreach ($messages as $message) {
337 // They should both be from our user.
338 $this->assertEquals($author->id, $message->useridfrom);
339
340 if ($message->useridto == $author->id) {
341 $seenauthor = true;
342 } else if ($message->useridto = $recipient->id) {
343 $seenrecipient = true;
344 }
345 }
346
347 // Check we only saw one user.
348 $this->assertFalse($seenauthor);
349 $this->assertTrue($seenrecipient);
350 }
351
352 public function test_optional_with_subscribed_user() {
353 $this->resetAfterTest(true);
354
355 // Create a course, with a forum.
356 $course = $this->getDataGenerator()->create_course();
357
358 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
359 $forum = $this->getDataGenerator()->create_module('forum', $options);
360
361 // Create two users enrolled in the course as students.
362 list($author, $recipient) = $this->helper_create_users($course, 2);
363
364 // Subscribe the 'recipient' user from the forum.
59075a43 365 \mod_forum\subscriptions::subscribe_user($recipient->id, $forum);
a7a84903
AN
366
367 // Post a discussion to the forum.
368 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
369
370 // We expect only one user to receive this post.
371 $expected = 1;
372
373 // Run cron and check that the expected number of users received the notification.
374 $messages = $this->helper_run_cron_check_count($post, $expected);
375
376 $seenauthor = false;
377 $seenrecipient = false;
378 foreach ($messages as $message) {
379 // They should both be from our user.
380 $this->assertEquals($author->id, $message->useridfrom);
381
382 if ($message->useridto == $author->id) {
383 $seenauthor = true;
384 } else if ($message->useridto = $recipient->id) {
385 $seenrecipient = true;
386 }
387 }
388
389 // Check we only saw one user.
390 $this->assertFalse($seenauthor);
391 $this->assertTrue($seenrecipient);
392 }
393
49566c8a
AN
394 public function test_automatic_with_unsubscribed_discussion() {
395 $this->resetAfterTest(true);
396
397 // Create a course, with a forum.
398 $course = $this->getDataGenerator()->create_course();
399
400 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
401 $forum = $this->getDataGenerator()->create_module('forum', $options);
402
403 // Create two users enrolled in the course as students.
404 list($author, $recipient) = $this->helper_create_users($course, 2);
405
406 // Post a discussion to the forum.
407 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
408
409 // Unsubscribe the 'author' user from the discussion.
410 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
411
412 // We expect only one user to receive this post.
413 $expected = 1;
414
415 // Run cron and check that the expected number of users received the notification.
416 $messages = $this->helper_run_cron_check_count($post, $expected);
417
418 $seenauthor = false;
419 $seenrecipient = false;
420 foreach ($messages as $message) {
421 // They should both be from our user.
422 $this->assertEquals($author->id, $message->useridfrom);
423
424 if ($message->useridto == $author->id) {
425 $seenauthor = true;
426 } else if ($message->useridto = $recipient->id) {
427 $seenrecipient = true;
428 }
429 }
430
431 // Check we only saw one user.
432 $this->assertFalse($seenauthor);
433 $this->assertTrue($seenrecipient);
434 }
435
436 public function test_optional_with_subscribed_discussion() {
437 $this->resetAfterTest(true);
438
439 // Create a course, with a forum.
440 $course = $this->getDataGenerator()->create_course();
441
442 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
443 $forum = $this->getDataGenerator()->create_module('forum', $options);
444
445 // Create two users enrolled in the course as students.
446 list($author, $recipient) = $this->helper_create_users($course, 2);
447
448 // Post a discussion to the forum.
449 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
450
451 // Subscribe the 'recipient' user to the discussion.
452 \mod_forum\subscriptions::subscribe_user_to_discussion($recipient->id, $discussion);
453
454 // We expect only one user to receive this post.
455 $expected = 1;
456
457 // Run cron and check that the expected number of users received the notification.
458 $messages = $this->helper_run_cron_check_count($post, $expected);
459
460 $seenauthor = false;
461 $seenrecipient = false;
462 foreach ($messages as $message) {
463 // They should both be from our user.
464 $this->assertEquals($author->id, $message->useridfrom);
465
466 if ($message->useridto == $author->id) {
467 $seenauthor = true;
468 } else if ($message->useridto = $recipient->id) {
469 $seenrecipient = true;
470 }
471 }
472
473 // Check we only saw one user.
474 $this->assertFalse($seenauthor);
475 $this->assertTrue($seenrecipient);
476 }
477
478 public function test_automatic_with_subscribed_discussion_in_unsubscribed_forum() {
479 $this->resetAfterTest(true);
480
481 // Create a course, with a forum.
482 $course = $this->getDataGenerator()->create_course();
483
484 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
485 $forum = $this->getDataGenerator()->create_module('forum', $options);
486
487 // Create two users enrolled in the course as students.
488 list($author, $recipient) = $this->helper_create_users($course, 2);
489
490 // Post a discussion to the forum.
491 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
492
493 // Unsubscribe the 'author' user from the discussion.
494 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum);
495
496 // Then re-subscribe them to the discussion.
497 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
498
499 // We expect two users to receive this post.
500 $expected = 2;
501
502 // Run cron and check that the expected number of users received the notification.
503 $messages = $this->helper_run_cron_check_count($post, $expected);
504
505 $seenauthor = false;
506 $seenrecipient = false;
507 foreach ($messages as $message) {
508 // They should both be from our user.
509 $this->assertEquals($author->id, $message->useridfrom);
510
511 if ($message->useridto == $author->id) {
512 $seenauthor = true;
513 } else if ($message->useridto = $recipient->id) {
514 $seenrecipient = true;
515 }
516 }
517
518 // Check we only saw one user.
519 $this->assertTrue($seenauthor);
520 $this->assertTrue($seenrecipient);
521 }
522
523 public function test_optional_with_unsubscribed_discussion_in_subscribed_forum() {
524 $this->resetAfterTest(true);
525
526 // Create a course, with a forum.
527 $course = $this->getDataGenerator()->create_course();
528
529 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
530 $forum = $this->getDataGenerator()->create_module('forum', $options);
531
532 // Create two users enrolled in the course as students.
533 list($author, $recipient) = $this->helper_create_users($course, 2);
534
535 // Post a discussion to the forum.
536 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
537
538 // Unsubscribe the 'recipient' user from the discussion.
539 \mod_forum\subscriptions::subscribe_user($recipient->id, $forum);
540
541 // Then unsubscribe them from the discussion.
542 \mod_forum\subscriptions::unsubscribe_user_from_discussion($recipient->id, $discussion);
543
544 // We don't expect any users to receive this post.
545 $expected = 0;
546
547 // Run cron and check that the expected number of users received the notification.
548 $messages = $this->helper_run_cron_check_count($post, $expected);
549 }
a7a84903 550}