Rev 1 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>.declare(strict_types=1);namespace core_reportbuilder\local\helpers;use advanced_testcase;use invalid_parameter_exception;use core\clock;use core_cohort\reportbuilder\audience\cohortmember;use core_reportbuilder_generator;use core_reportbuilder\local\models\schedule as model;use core_reportbuilder\reportbuilder\audience\manual;use core_user\reportbuilder\datasource\users;/*** Unit tests for the schedule helper class** @package core_reportbuilder* @covers \core_reportbuilder\local\helpers\schedule* @copyright 2021 Paul Holden <paulh@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/final class schedule_test extends advanced_testcase {/** @var clock $clock */private readonly clock $clock;/*** Mock the clock*/protected function setUp(): void {parent::setUp();$this->clock = $this->mock_clock_with_frozen(1622847600);}/*** Test create schedule*/public function test_create_schedule(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);// Create schedule for tomorrow.$timescheduled = $this->clock->time() + DAYSECS;$schedule = schedule::create_schedule((object) ['name' => 'My schedule','reportid' => $report->get('id'),'format' => 'csv','subject' => 'Hello','message' => 'Hola','timescheduled' => $timescheduled,]);$this->assertEquals('My schedule', $schedule->get('name'));$this->assertEquals($report->get('id'), $schedule->get('reportid'));$this->assertEquals('csv', $schedule->get('format'));$this->assertEquals('Hello', $schedule->get('subject'));$this->assertEquals('Hola', $schedule->get('message'));$this->assertEquals($timescheduled, $schedule->get('timescheduled'));$this->assertEquals($timescheduled, $schedule->get('timenextsend'));}/*** Test update schedule*/public function test_update_schedule(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);// Update some record properties.$record = $schedule->to_record();$record->name = 'My updated schedule';$record->timescheduled += (12 * HOURSECS);$schedule = schedule::update_schedule($record);$this->assertEquals($record->name, $schedule->get('name'));$this->assertEquals($record->timescheduled, $schedule->get('timescheduled'));$this->assertEquals($record->timescheduled, $schedule->get('timenextsend'));}/*** Test update invalid schedule*/public function test_update_schedule_invalid(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$this->expectException(invalid_parameter_exception::class);$this->expectExceptionMessage('Invalid schedule');schedule::update_schedule((object) ['id' => 42, 'reportid' => $report->get('id')]);}/*** Test toggle schedule*/public function test_toggle_schedule(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);// Disable the schedule.schedule::toggle_schedule($report->get('id'), $schedule->get('id'), false);$schedule = $schedule->read();$this->assertFalse($schedule->get('enabled'));// Enable the schedule.schedule::toggle_schedule($report->get('id'), $schedule->get('id'), true);$schedule = $schedule->read();$this->assertTrue($schedule->get('enabled'));}/*** Test toggle invalid schedule*/public function test_toggle_schedule_invalid(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$this->expectException(invalid_parameter_exception::class);$this->expectExceptionMessage('Invalid schedule');schedule::toggle_schedule($report->get('id'), 42, true);}/*** Test delete schedule*/public function test_delete_schedule(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);$scheduleid = $schedule->get('id');schedule::delete_schedule($report->get('id'), $scheduleid);$this->assertFalse($schedule::record_exists($scheduleid));}/*** Test delete invalid schedule*/public function test_delete_schedule_invalid(): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$this->expectException(invalid_parameter_exception::class);$this->expectExceptionMessage('Invalid schedule');schedule::delete_schedule($report->get('id'), 42);}/*** Test getting schedule report users (those in matching audience)*/public function test_get_schedule_report_users(): void {$this->resetAfterTest();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);// Create cohort, with some members.$cohort = $this->getDataGenerator()->create_cohort();$cohortuserone = $this->getDataGenerator()->create_user(['firstname' => 'Zoe', 'lastname' => 'Zebra']);cohort_add_member($cohort->id, $cohortuserone->id);$cohortusertwo = $this->getDataGenerator()->create_user(['firstname' => 'Henrietta', 'lastname' => 'Hamster']);cohort_add_member($cohort->id, $cohortusertwo->id);// Create a third user, to be added manually.$manualuserone = $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Badger']);$audiencecohort = $generator->create_audience(['reportid' => $report->get('id'),'classname' => cohortmember::class,'configdata' => ['cohorts' => [$cohort->id]],]);$audiencemanual = $generator->create_audience(['reportid' => $report->get('id'),'classname' => manual::class,'configdata' => ['users' => [$manualuserone->id]],]);// Now create our schedule.$schedule = $generator->create_schedule(['reportid' => $report->get('id'),'name' => 'My schedule','audiences' => json_encode([$audiencecohort->get_persistent()->get('id'),$audiencemanual->get_persistent()->get('id'),]),]);$users = schedule::get_schedule_report_users($schedule);$this->assertEquals(['Bob','Henrietta','Zoe',], array_column($users, 'firstname'));// Now delete one of our users, ensure they are no longer returned.delete_user($manualuserone);$users = schedule::get_schedule_report_users($schedule);$this->assertEquals(['Henrietta','Zoe',], array_column($users, 'firstname'));}/*** Test getting schedule report row count*/public function test_get_schedule_report_count(): void {$this->resetAfterTest();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);// There is only one row in the report (the only user on the site).$count = schedule::get_schedule_report_count($schedule);$this->assertDebuggingCalled();$this->assertEquals(1, $count);}/*** Data provider for {@see test_get_schedule_report_file}** @return string[]*/public static function get_schedule_report_file_format(): array {return [['csv'],['excel'],['html'],['json'],['ods'],['pdf'],];}/*** Test getting schedule report exported file, in each supported format** @param string $format** @dataProvider get_schedule_report_file_format*/public function test_get_schedule_report_file(string $format): void {$this->resetAfterTest();$this->setAdminUser();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule', 'format' => $format]);// There is only one row in the report (the only user on the site).$file = schedule::get_schedule_report_file($schedule);$this->assertGreaterThan(64, $file->get_filesize());}/*** Data provider for {@see test_should_send_schedule}** @return array[]*/public static function should_send_schedule_provider(): array {return ['Time scheduled in the past' => [model::RECURRENCE_NONE, '-1 hour', null, null, true,],'Time scheduled in the past, already sent prior to schedule' => [model::RECURRENCE_NONE, '-1 hour', '-2 hour', null, true,],'Time scheduled in the past, already sent on schedule' => [model::RECURRENCE_NONE, '-1 hour', '-1 hour', null, false,],'Time scheduled in the future' => [model::RECURRENCE_NONE, '+1 hour', null, null, false,],'Time scheduled in the future, already sent prior to schedule' => [model::RECURRENCE_NONE, '+1 hour', '-1 hour', null, false,],'Next send in the past' => [model::RECURRENCE_DAILY, '-1 hour', null, '-1 hour', true,],'Next send in the future' => [model::RECURRENCE_DAILY, '-1 hour', null, '+1 hour', false,],];}/*** Test for whether a schedule should be sent** @param int $recurrence* @param string $timescheduled Relative time suitable for passing to {@see strtotime}* @param string|null $timelastsent Relative time suitable for passing to {@see strtotime}, or null to ignore* @param string|null $timenextsend Relative time suitable for passing to {@see strtotime}, or null to ignore* @param bool $expected** @dataProvider should_send_schedule_provider*/public function test_should_send_schedule(int $recurrence,string $timescheduled,?string $timelastsent,?string $timenextsend,bool $expected,): void {$this->resetAfterTest();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);// Use relative time period if present, otherwise default to zero (never sent).$scheduletimelastsent = 0;if ($timelastsent !== null) {$scheduletimelastsent = strtotime($timelastsent, $this->clock->time());}$schedule = $generator->create_schedule(['reportid' => $report->get('id'),'name' => 'My schedule','recurrence' => $recurrence,'timescheduled' => strtotime($timescheduled, $this->clock->time()),'timelastsent' => $scheduletimelastsent,]);// If "Time next send" is specified, then override calculated value.if ($timenextsend !== null) {$schedule->set('timenextsend', strtotime($timenextsend, $this->clock->time()));}$this->assertEquals($expected, schedule::should_send_schedule($schedule));}/*** Test for whether a schedule should be sent that has been disabled*/public function test_should_send_schedule_disabled(): void {$this->resetAfterTest();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);$schedule = $generator->create_schedule(['reportid' => $report->get('id'),'name' => 'My schedule','enabled' => 0,]);$this->assertFalse(schedule::should_send_schedule($schedule));}/*** Data provider for {@see test_calculate_next_send_time}** @return array[]*/public static function calculate_next_send_time_provider(): array {// Times are based on the current clock time (Fri Jun 04 2021 23:00:00 UTC).return ['No recurrence' => [model::RECURRENCE_NONE, '2021-06-03 12:00', '2021-06-03 12:00',],'Recurrence, time scheduled in future' => [model::RECURRENCE_DAILY, '2021-06-05 12:00', '2021-06-05 12:00',],'Daily recurrence' => [model::RECURRENCE_DAILY, '2021-06-02 12:00', '2021-06-05 12:00',],'Weekday recurrence' => [model::RECURRENCE_WEEKDAYS, '2021-06-02 12:00', '2021-06-07 12:00',],'Weekly recurrence' => [model::RECURRENCE_WEEKLY, '2021-05-18 12:00', '2021-06-08 12:00',],'Monthy recurrence' => [model::RECURRENCE_MONTHLY, '2021-03-19 12:00', '2021-06-19 12:00',],'Annual recurrence' => [model::RECURRENCE_ANNUALLY, '2019-05-01 12:00', '2022-05-01 12:00',],];}/*** Test for calculating next schedule send time** @param int $recurrence* @param string $timescheduled Absolute time suitable for passing to {@see strtotime}* @param string $expected Absolute time suitable for passing to {@see strtotime}** @dataProvider calculate_next_send_time_provider*/public function test_calculate_next_send_time(int $recurrence, string $timescheduled, string $expected): void {$this->resetAfterTest();/** @var core_reportbuilder_generator $generator */$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);// Create model manually, as the generator automatically calculates next send itself.$schedule = new model(0, (object) ['reportid' => $report->get('id'),'name' => 'My schedule','recurrence' => $recurrence,'timescheduled' => strtotime("{$timescheduled} UTC"),]);$scheduleexpected = strtotime("{$expected} UTC");$this->assertEquals($scheduleexpected, schedule::calculate_next_send_time($schedule));}}