Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]
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 declare(strict_types=1); 18 19 namespace core_reportbuilder\local\helpers; 20 21 use advanced_testcase; 22 use invalid_parameter_exception; 23 use core_cohort\reportbuilder\audience\cohortmember; 24 use core_reportbuilder_generator; 25 use core_reportbuilder\local\models\schedule as model; 26 use core_reportbuilder\reportbuilder\audience\manual; 27 use core_user\reportbuilder\datasource\users; 28 29 /** 30 * Unit tests for the schedule helper class 31 * 32 * @package core_reportbuilder 33 * @covers \core_reportbuilder\local\helpers\schedule 34 * @copyright 2021 Paul Holden <paulh@moodle.com> 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class schedule_test extends advanced_testcase { 38 39 /** 40 * Test create schedule 41 */ 42 public function test_create_schedule(): void { 43 $this->resetAfterTest(); 44 $this->setAdminUser(); 45 46 /** @var core_reportbuilder_generator $generator */ 47 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 48 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 49 50 $timescheduled = time() + DAYSECS; 51 $schedule = schedule::create_schedule((object) [ 52 'name' => 'My schedule', 53 'reportid' => $report->get('id'), 54 'format' => 'csv', 55 'subject' => 'Hello', 56 'message' => 'Hola', 57 'timescheduled' => $timescheduled, 58 ]); 59 60 $this->assertEquals('My schedule', $schedule->get('name')); 61 $this->assertEquals($report->get('id'), $schedule->get('reportid')); 62 $this->assertEquals('csv', $schedule->get('format')); 63 $this->assertEquals('Hello', $schedule->get('subject')); 64 $this->assertEquals('Hola', $schedule->get('message')); 65 $this->assertEquals($timescheduled, $schedule->get('timescheduled')); 66 $this->assertEquals($timescheduled, $schedule->get('timenextsend')); 67 } 68 69 /** 70 * Test update schedule 71 */ 72 public function test_update_schedule(): void { 73 $this->resetAfterTest(); 74 $this->setAdminUser(); 75 76 /** @var core_reportbuilder_generator $generator */ 77 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 78 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 79 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']); 80 81 // Update some record properties. 82 $record = $schedule->to_record(); 83 $record->name = 'My updated schedule'; 84 $record->timescheduled = 1861340400; // 25/12/2028 07:00 UTC. 85 86 $schedule = schedule::update_schedule($record); 87 $this->assertEquals($record->name, $schedule->get('name')); 88 $this->assertEquals($record->timescheduled, $schedule->get('timescheduled')); 89 } 90 91 /** 92 * Test update invalid schedule 93 */ 94 public function test_update_schedule_invalid(): void { 95 $this->resetAfterTest(); 96 $this->setAdminUser(); 97 98 /** @var core_reportbuilder_generator $generator */ 99 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 100 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 101 102 $this->expectException(invalid_parameter_exception::class); 103 $this->expectExceptionMessage('Invalid schedule'); 104 schedule::update_schedule((object) ['id' => 42, 'reportid' => $report->get('id')]); 105 } 106 107 /** 108 * Test toggle schedule 109 */ 110 public function test_toggle_schedule(): void { 111 $this->resetAfterTest(); 112 $this->setAdminUser(); 113 114 /** @var core_reportbuilder_generator $generator */ 115 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 116 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 117 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']); 118 119 // Disable the schedule. 120 schedule::toggle_schedule($report->get('id'), $schedule->get('id'), false); 121 $schedule = $schedule->read(); 122 $this->assertFalse($schedule->get('enabled')); 123 124 // Enable the schedule. 125 schedule::toggle_schedule($report->get('id'), $schedule->get('id'), true); 126 $schedule = $schedule->read(); 127 $this->assertTrue($schedule->get('enabled')); 128 } 129 130 /** 131 * Test toggle invalid schedule 132 */ 133 public function test_toggle_schedule_invalid(): void { 134 $this->resetAfterTest(); 135 $this->setAdminUser(); 136 137 /** @var core_reportbuilder_generator $generator */ 138 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 139 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 140 141 $this->expectException(invalid_parameter_exception::class); 142 $this->expectExceptionMessage('Invalid schedule'); 143 schedule::toggle_schedule($report->get('id'), 42, true); 144 } 145 146 /** 147 * Test delete schedule 148 */ 149 public function test_delete_schedule(): void { 150 $this->resetAfterTest(); 151 $this->setAdminUser(); 152 153 /** @var core_reportbuilder_generator $generator */ 154 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 155 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 156 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']); 157 158 $scheduleid = $schedule->get('id'); 159 160 schedule::delete_schedule($report->get('id'), $scheduleid); 161 $this->assertFalse($schedule::record_exists($scheduleid)); 162 } 163 164 /** 165 * Test delete invalid schedule 166 */ 167 public function test_delete_schedule_invalid(): void { 168 $this->resetAfterTest(); 169 $this->setAdminUser(); 170 171 /** @var core_reportbuilder_generator $generator */ 172 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 173 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 174 175 $this->expectException(invalid_parameter_exception::class); 176 $this->expectExceptionMessage('Invalid schedule'); 177 schedule::delete_schedule($report->get('id'), 42); 178 } 179 180 /** 181 * Test getting schedule report users (those in matching audience) 182 */ 183 public function test_get_schedule_report_users(): void { 184 $this->resetAfterTest(); 185 186 /** @var core_reportbuilder_generator $generator */ 187 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 188 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 189 190 // Create cohort, with some members. 191 $cohort = $this->getDataGenerator()->create_cohort(); 192 $cohortuserone = $this->getDataGenerator()->create_user(['firstname' => 'Zoe', 'lastname' => 'Zebra']); 193 cohort_add_member($cohort->id, $cohortuserone->id); 194 $cohortusertwo = $this->getDataGenerator()->create_user(['firstname' => 'Henrietta', 'lastname' => 'Hamster']); 195 cohort_add_member($cohort->id, $cohortusertwo->id); 196 197 // Create a third user, to be added manually. 198 $manualuserone = $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Badger']); 199 200 $audiencecohort = $generator->create_audience([ 201 'reportid' => $report->get('id'), 202 'classname' => cohortmember::class, 203 'configdata' => ['cohorts' => [$cohort->id]], 204 ]); 205 206 $audiencemanual = $generator->create_audience([ 207 'reportid' => $report->get('id'), 208 'classname' => manual::class, 209 'configdata' => ['users' => [$manualuserone->id]], 210 ]); 211 212 // Now create our schedule. 213 $schedule = $generator->create_schedule([ 214 'reportid' => $report->get('id'), 215 'name' => 'My schedule', 216 'audiences' => json_encode([ 217 $audiencecohort->get_persistent()->get('id'), 218 $audiencemanual->get_persistent()->get('id'), 219 ]), 220 ]); 221 222 $users = schedule::get_schedule_report_users($schedule); 223 $this->assertEquals([ 224 'Bob', 225 'Henrietta', 226 'Zoe', 227 ], array_column($users, 'firstname')); 228 } 229 230 /** 231 * Test getting schedule report row count 232 */ 233 public function test_get_schedule_report_count(): void { 234 $this->resetAfterTest(); 235 236 /** @var core_reportbuilder_generator $generator */ 237 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 238 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 239 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']); 240 241 // There is only one row in the report (the only user on the site). 242 $count = schedule::get_schedule_report_count($schedule); 243 $this->assertEquals(1, $count); 244 } 245 246 /** 247 * Data provider for {@see test_get_schedule_report_file} 248 * 249 * @return string[] 250 */ 251 public function get_schedule_report_file_format(): array { 252 return [ 253 ['csv'], 254 ['excel'], 255 ['html'], 256 ['json'], 257 ['ods'], 258 ['pdf'], 259 ]; 260 } 261 262 /** 263 * Test getting schedule report exported file, in each supported format 264 * 265 * @param string $format 266 * 267 * @dataProvider get_schedule_report_file_format 268 */ 269 public function test_get_schedule_report_file(string $format): void { 270 $this->resetAfterTest(); 271 $this->setAdminUser(); 272 273 /** @var core_reportbuilder_generator $generator */ 274 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 275 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 276 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule', 'format' => $format]); 277 278 // There is only one row in the report (the only user on the site). 279 $file = schedule::get_schedule_report_file($schedule); 280 $this->assertGreaterThan(64, $file->get_filesize()); 281 } 282 283 /** 284 * Data provider for {@see test_should_send_schedule} 285 * 286 * @return array[] 287 */ 288 public function should_send_schedule_provider(): array { 289 $time = time(); 290 291 // We just need large offsets for dates in the past/future. 292 $yesterday = $time - DAYSECS; 293 $tomorrow = $time + DAYSECS; 294 295 return [ 296 'Disabled' => [[ 297 'enabled' => false, 298 ], false], 299 'Time scheduled in the past' => [[ 300 'recurrence' => model::RECURRENCE_NONE, 301 'timescheduled' => $yesterday, 302 ], true], 303 'Time scheduled in the past, already sent prior to schedule' => [[ 304 'recurrence' => model::RECURRENCE_NONE, 305 'timescheduled' => $yesterday, 306 'timelastsent' => $yesterday - HOURSECS, 307 ], true], 308 'Time scheduled in the past, already sent on schedule' => [[ 309 'recurrence' => model::RECURRENCE_NONE, 310 'timescheduled' => $yesterday, 311 'timelastsent' => $yesterday, 312 ], false], 313 'Time scheduled in the future' => [[ 314 'recurrence' => model::RECURRENCE_NONE, 315 'timescheduled' => $tomorrow, 316 ], false], 317 'Time scheduled in the future, already sent prior to schedule' => [[ 318 'recurrence' => model::RECURRENCE_NONE, 319 'timelastsent' => $yesterday, 320 'timescheduled' => $tomorrow, 321 ], false], 322 'Next send in the past' => [[ 323 'recurrence' => model::RECURRENCE_DAILY, 324 'timescheduled' => $yesterday, 325 'timenextsend' => $yesterday, 326 ], true], 327 'Next send in the future' => [[ 328 'recurrence' => model::RECURRENCE_DAILY, 329 'timescheduled' => $yesterday, 330 'timenextsend' => $tomorrow, 331 ], false], 332 ]; 333 } 334 335 /** 336 * Test for whether a schedule should be sent 337 * 338 * @param array $properties 339 * @param bool $expected 340 * 341 * @dataProvider should_send_schedule_provider 342 */ 343 public function test_should_send_schedule(array $properties, bool $expected): void { 344 $this->resetAfterTest(); 345 346 /** @var core_reportbuilder_generator $generator */ 347 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 348 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 349 350 $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule'] + $properties); 351 352 // If "Time next send" is specified, then override calculated value. 353 if (array_key_exists('timenextsend', $properties)) { 354 $schedule->set('timenextsend', $properties['timenextsend']); 355 } 356 357 $this->assertEquals($expected, schedule::should_send_schedule($schedule)); 358 } 359 360 /** 361 * Data provider for {@see test_calculate_next_send_time} 362 * 363 * @return array[] 364 */ 365 public function calculate_next_send_time_provider(): array { 366 $timescheduled = 1635865200; // Tue Nov 02 2021 15:00:00 GMT+0000. 367 $timenow = 1639846800; // Sat Dec 18 2021 17:00:00 GMT+0000. 368 369 return [ 370 'No recurrence' => [model::RECURRENCE_NONE, $timescheduled, $timenow, $timescheduled], 371 'Recurrence, time scheduled in future' => [model::RECURRENCE_DAILY, $timenow + DAYSECS, $timenow, $timenow + DAYSECS], 372 // Sun Dec 19 2021 15:00:00 GMT+0000. 373 'Daily recurrence' => [model::RECURRENCE_DAILY, $timescheduled, $timenow, 1639926000], 374 // Mon Dec 20 2021 15:00:00 GMT+0000. 375 'Weekday recurrence' => [model::RECURRENCE_WEEKDAYS, $timescheduled, $timenow, 1640012400], 376 // Tue Dec 21 2021 15:00:00 GMT+0000. 377 'Weekly recurrence' => [model::RECURRENCE_WEEKLY, $timescheduled, $timenow, 1640098800], 378 // Sun Jan 02 2022 15:00:00 GMT+0000. 379 'Monthy recurrence' => [model::RECURRENCE_MONTHLY, $timescheduled, $timenow, 1641135600], 380 // Wed Nov 02 2022 15:00:00 GMT+0000. 381 'Annual recurrence' => [model::RECURRENCE_ANNUALLY, $timescheduled, $timenow, 1667401200], 382 ]; 383 } 384 385 /** 386 * Test for calculating next schedule send time 387 * 388 * @param int $recurrence 389 * @param int $timescheduled 390 * @param int $timenow 391 * @param int $expected 392 * 393 * @dataProvider calculate_next_send_time_provider 394 */ 395 public function test_calculate_next_send_time(int $recurrence, int $timescheduled, int $timenow, int $expected): void { 396 $this->resetAfterTest(); 397 398 /** @var core_reportbuilder_generator $generator */ 399 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 400 $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); 401 402 $schedule = $generator->create_schedule([ 403 'reportid' => $report->get('id'), 404 'name' => 'My schedule', 405 'recurrence' => $recurrence, 406 'timescheduled' => $timescheduled, 407 'timenow' => $timenow, 408 ]); 409 410 $this->assertEquals($expected, schedule::calculate_next_send_time($schedule, $timenow)); 411 } 412 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body