From b3c1d8aaca9079e4a645d578828eefc7ceb601f1 Mon Sep 17 00:00:00 2001 From: Andrii Semenets Date: Sat, 14 Dec 2024 15:17:04 +0200 Subject: [PATCH] new phpunit test_rule_on_freeplace_on_intervals() (#467) --- tests/booking_rules/rules_test.php | 202 ++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 3 deletions(-) diff --git a/tests/booking_rules/rules_test.php b/tests/booking_rules/rules_test.php index 6323d93a5..ebebe632f 100644 --- a/tests/booking_rules/rules_test.php +++ b/tests/booking_rules/rules_test.php @@ -1070,8 +1070,6 @@ public function test_rule_on_freeplaceagain(array $bdata): void { booking_rules::$rules = []; } - - /** * Test rule on option being completed for user. * @@ -1226,7 +1224,7 @@ public function test_rule_on_option_completion(array $bdata): void { * @dataProvider booking_common_settings_provider */ public function test_booking_rules_customform_delete_data(array $bdata): void { - + singleton_service::destroy_instance(); // Setup test data. @@ -1401,6 +1399,204 @@ public function test_booking_rules_customform_delete_data(array $bdata): void { booking_rules::$rules = []; } + /** + * Test rules for "option free to bookagain" and "notification in intervals" events. + * + * @covers \condition\alreadybooked::is_available + * @covers \condition\onwaitinglist::is_available + * @covers \mod_booking\event\bookingoption_freetobookagain + * @covers \mod_booking\event\bookingoptionwaitinglist_booked + * @covers \mod_booking\booking_rules\rules\rule_react_on_event + * @covers \mod_booking\booking_rules\actions\send_mail + * @covers \mod_booking\booking_rules\conditions\select_teacher_in_bo + * @covers \mod_booking\booking_rules\conditions\select_student_in_bo + * + * @param array $bdata + * @throws \coding_exception + * @throws \dml_exception + * + * @dataProvider booking_common_settings_provider + */ + public function test_rule_on_freeplace_on_intervals(array $bdata): void { + global $DB, $CFG; + + $bdata['cancancelbook'] = 1; + + // Create course. + $course1 = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); + + // Create users. + $student1 = $this->getDataGenerator()->create_user(); + $student2 = $this->getDataGenerator()->create_user(); + $student3 = $this->getDataGenerator()->create_user(); + $teacher1 = $this->getDataGenerator()->create_user(); + + $bdata['course'] = $course1->id; + $bdata['bookingmanager'] = $teacher1->username; + + $booking1 = $this->getDataGenerator()->create_module('booking', $bdata); + + $this->setAdminUser(); + + $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student'); + $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student'); + $this->getDataGenerator()->enrol_user($student3->id, $course1->id, 'student'); + $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher'); + + /** @var mod_booking_generator $plugingenerator */ + $plugingenerator = self::getDataGenerator()->get_plugin_generator('mod_booking'); + + // Create booking rule 1 - "bookingoption_freetobookagain" with delays. + $boevent1 = '"boevent":"\\\\mod_booking\\\\event\\\\bookingoption_freetobookagain"'; + $ruledata1 = [ + 'name' => 'intervlqs', + 'conditionname' => 'select_student_in_bo', + 'contextid' => 1, + 'conditiondata' => '{"borole":"smallerthan1"}', + 'actionname' => 'send_mail_interval', + 'actiondata' => '{"interval":1,"subject":"freeplacedelaysubj","template":"freeplacedelaymsg","templateformat":"1"}', + 'rulename' => 'rule_react_on_event', + 'ruledata' => '{' . $boevent1 . ',"aftercompletion":0,"cancelrules":[],"condition":"2"}', + ]; + $rule1 = $plugingenerator->create_rule($ruledata1); + + // Create booking rule 2 - "bookingoption_freetobookagain". + $boevent2 = '"boevent":"\\\\mod_booking\\\\event\\\\bookingoption_freetobookagain"'; + $ruledata2 = [ + 'name' => 'override', + 'conditionname' => 'select_student_in_bo', + 'contextid' => 1, + 'conditiondata' => '{"borole":"1"}', + 'actionname' => 'send_mail', + 'actiondata' => '{"subject":"freeplacesubj","template":"freeplacemsg","templateformat":"1"}', + 'rulename' => 'rule_react_on_event', + 'ruledata' => '{' . $boevent2 . ',"aftercompletion":"","condition":"0"}', + ]; + $rule2 = $plugingenerator->create_rule($ruledata2); + + // Create booking option 1. + $record = new stdClass(); + $record->bookingid = $booking1->id; + $record->text = 'football'; + $record->chooseorcreatecourse = 1; // Connected existing course. + $record->courseid = $course1->id; + $record->maxanswers = 1; + $record->maxoverbooking = 3; // Enable waitinglist. + $record->waitforconfirmation = 1; // Do not force waitinglist. + $record->description = 'Will start in 2050'; + $record->optiondateid_1 = "0"; + $record->daystonotify_1 = "0"; + $record->coursestarttime_1 = strtotime('20 June 2050 15:00'); + $record->courseendtime_1 = strtotime('20 July 2050 14:00'); + $record->teachersforoption = $teacher1->username; + $option1 = $plugingenerator->create_option($record); + singleton_service::destroy_booking_option_singleton($option1->id); + + $settings = singleton_service::get_instance_of_booking_option_settings($option1->id); + $boinfo = new bo_info($settings); + $option = singleton_service::get_instance_of_booking_option($settings->cmid, $settings->id); + + // Create a booking option answer - book student2. + $this->setUser($student2); + singleton_service::destroy_user($student2->id); + $result = booking_bookit::bookit('option', $settings->id, $student2->id); + list($id, $isavailable, $description) = $boinfo->is_available($settings->id, $student2->id, true); + $this->assertEquals(MOD_BOOKING_BO_COND_ONWAITINGLIST, $id); + + // Confirm booking as admin. + $this->setAdminUser(); + $option->user_submit_response($student2, 0, 0, 0, MOD_BOOKING_VERIFIED); + list($id, $isavailable, $description) = $boinfo->is_available($settings->id, $student2->id, true); + $this->assertEquals(MOD_BOOKING_BO_COND_ALREADYBOOKED, $id); + + // Book the student1 via waitinglist. + $this->setUser($student1); + singleton_service::destroy_user($student1->id); + $result = booking_bookit::bookit('option', $settings->id, $student1->id); + list($id, $isavailable, $description) = $boinfo->is_available($settings->id, $student1->id, true); + $this->assertEquals(MOD_BOOKING_BO_COND_ONWAITINGLIST, $id); + + // Book the student3 via waitinglist. + $this->setUser($student3); + singleton_service::destroy_user($student3->id); + $result = booking_bookit::bookit('option', $settings->id, $student3->id); + list($id, $isavailable, $description) = $boinfo->is_available($settings->id, $student3->id, true); + $this->assertEquals(MOD_BOOKING_BO_COND_ONWAITINGLIST, $id); + + // Now take student 2 from the list, for a place to free up. + $this->setUser($student2); + $option->user_delete_response($student2->id); + singleton_service::destroy_booking_option_singleton($option1->id); + singleton_service::destroy_booking_answers($option1->id); + + // Execute tasks, get messages and validate it. + $this->setAdminUser(); + + // Get all scheduled task messages. + $tasks = \core\task\manager::get_adhoc_tasks('\mod_booking\task\send_mail_by_rule_adhoc'); + + $this->assertCount(4, $tasks); + // Validate task messages. Might be free order. + foreach ($tasks as $key => $task) { + $customdata = $task->get_custom_data(); + if (strpos($customdata->customsubject, "freeplacesubj") !== false) { + // Validate 2 task messages on the bookingoption_freetobookagain event. + $this->assertEquals("freeplacesubj", $customdata->customsubject); + $this->assertEquals("freeplacemsg", $customdata->custommessage); + $this->assertContains($customdata->userid, [$student1->id, $student3->id]); + $this->assertStringContainsString($boevent2, $customdata->rulejson); + $this->assertStringContainsString($ruledata2['conditiondata'], $customdata->rulejson); + $this->assertStringContainsString($ruledata2['actiondata'], $customdata->rulejson); + $this->assertContains($task->get_userid(), [$student1->id, $student3->id]); + $rulejson = json_decode($customdata->rulejson); + $this->assertEmpty($rulejson->datafromevent->relateduserid); + $this->assertEquals($student2->id, $rulejson->datafromevent->userid); + } else { + // Validate 2 task messages on the bookingoption_freetobookagain with delay event. + $this->assertEquals("freeplacedelaysubj", $customdata->customsubject); + $this->assertEquals("freeplacedelaymsg", $customdata->custommessage); + $this->assertContains($customdata->userid, [$student1->id, $student3->id]); + $this->assertStringContainsString($boevent1, $customdata->rulejson); + $this->assertStringContainsString($ruledata1['conditiondata'], $customdata->rulejson); + $this->assertStringContainsString($ruledata1['actiondata'], $customdata->rulejson); + $this->assertContains($task->get_userid(), [$student1->id, $student3->id]); + $rulejson = json_decode($customdata->rulejson); + $this->assertEmpty($rulejson->datafromevent->relateduserid); + $this->assertEquals($student2->id, $rulejson->datafromevent->userid); + } + } + + // Run adhock tasks. + $sink = $this->redirectMessages(); + $tasks = \core\task\manager::get_adhoc_tasks('\mod_booking\task\send_mail_by_rule_adhoc'); + ob_start(); + $this->runAdhocTasks(); + $messages = $sink->get_messages(); + $res = ob_get_clean(); + $sink->close(); + + $this->assertCount(3, $messages); + // Validate ACTUAL task messages. Might be free order. + foreach ($messages as $key => $message) { + if (strpos($message->subject, "freeplacesubj") !== false) { + // Validate 2 task messages on the bookingoption_freetobookagain event. + $this->assertEquals("freeplacesubj", $message->subject); + $this->assertEquals("freeplacemsg", $message->fullmessage); + $this->assertContains($message->useridto, [$student1->id, $student3->id]); + } else { + // Validate 1 task messages on the bookingoption_freetobookagain with delay event. + $this->assertEquals("freeplacedelaysubj", $message->subject); + $this->assertEquals("freeplacedelaymsg", $message->fullmessage); + $this->assertEquals($student1->id, $message->useridto); + } + } + // Mandatory to solve potential cache issues. + singleton_service::destroy_instance(); + // Mandatory to deal with static variable in the booking_rules. + rules_info::$rulestoexecute = []; + booking_rules::$rules = []; + } + /** * Data provider for condition_bookingpolicy_test *