MDL-66722 core_grades: Add simple direct grading to gradingpanel
[moodle.git] / grade / tests / grades_grader_gradingpanel_point_external_fetch_test.php
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/>.
17 /**
18  * Unit tests for core_grades\component_gradeitems;
19  *
20  * @package   core_grades
21  * @category  test
22  * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU Public License
24  */
26 declare(strict_types = 1);
28 namespace core_grades\grades\grader\gradingpanel\point\external;
30 use advanced_testcase;
31 use coding_exception;
32 use core_grades\component_gradeitem;
33 use external_api;
34 use mod_forum\local\entities\forum as forum_entity;
35 use moodle_exception;
37 /**
38  * Unit tests for core_grades\component_gradeitems;
39  *
40  * @package   core_grades
41  * @category  test
42  * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
43  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44  */
45 class fetch_test extends advanced_testcase {
47     public static function setupBeforeClass(): void {
48         global $CFG;
49         require_once("{$CFG->libdir}/externallib.php");
50     }
52     /**
53      * Ensure that an execute with an invalid component is rejected.
54      */
55     public function test_execute_invalid_component(): void {
56         $this->resetAfterTest();
57         $user = $this->getDataGenerator()->create_user();
58         $this->setUser($user);
60         $this->expectException(coding_exception::class);
61         $this->expectExceptionMessage("The 'foo' item is not valid for the 'mod_invalid' component");
62         fetch::execute('mod_invalid', 1, 'foo', 2);
63     }
65     /**
66      * Ensure that an execute with an invalid itemname on a valid component is rejected.
67      */
68     public function test_execute_invalid_itemname(): void {
69         $this->resetAfterTest();
70         $user = $this->getDataGenerator()->create_user();
71         $this->setUser($user);
73         $this->expectException(coding_exception::class);
74         $this->expectExceptionMessage("The 'foo' item is not valid for the 'mod_forum' component");
75         fetch::execute('mod_forum', 1, 'foo', 2);
76     }
78     /**
79      * Ensure that an execute against a different grading method is rejected.
80      */
81     public function test_execute_incorrect_type(): void {
82         $this->resetAfterTest();
84         $forum = $this->get_forum_instance([
85             // Negative numbers mean a scale.
86             'grade_forum' => -1,
87         ]);
88         $course = $forum->get_course_record();
89         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
90         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
91         $this->setUser($teacher);
93         $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
95         $this->expectException(moodle_exception::class);
96         $this->expectExceptionMessage("not configured for direct grading");
97         fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $student->id);
98     }
100     /**
101      * Ensure that an execute against the correct grading method returns the current state of the user.
102      */
103     public function test_execute_fetch_empty(): void {
104         $this->resetAfterTest();
106         $forum = $this->get_forum_instance([
107             // Negative numbers mean a scale.
108             'grade_forum' => 5,
109         ]);
110         $course = $forum->get_course_record();
111         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
112         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
113         $this->setUser($teacher);
115         $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
117         $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $student->id);
118         $result = external_api::clean_returnvalue(fetch::execute_returns(), $result);
120         $this->assertIsArray($result);
121         $this->assertArrayHasKey('templatename', $result);
123         $this->assertEquals('core_grades/grades/grader/gradingpanel/point', $result['templatename']);
125         $this->assertArrayHasKey('grade', $result);
126         $this->assertIsArray($result['grade']);
127         $this->assertArrayHasKey('grade', $result['grade']);
128         $this->assertEmpty($result['grade']['grade']);
129         $this->assertArrayHasKey('timecreated', $result['grade']);
130         $this->assertIsInt($result['grade']['timecreated']);
131         $this->assertArrayHasKey('timemodified', $result['grade']);
132         $this->assertIsInt($result['grade']['timemodified']);
134         $this->assertArrayHasKey('warnings', $result);
135         $this->assertIsArray($result['warnings']);
136         $this->assertEmpty($result['warnings']);
137     }
139     /**
140      * Ensure that an execute against the correct grading method returns the current state of the user.
141      */
142     public function test_execute_fetch_graded(): void {
143         $this->resetAfterTest();
145         $forum = $this->get_forum_instance([
146             // Negative numbers mean a scale.
147             'grade_forum' => 5,
148         ]);
149         $course = $forum->get_course_record();
150         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
151         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
152         $this->setUser($teacher);
154         $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
155         $gradeitem->store_grade_from_formdata($student, $teacher, (object) [
156             'grade' => 4,
157         ]);
159         $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $student->id);
160         $result = external_api::clean_returnvalue(fetch::execute_returns(), $result);
162         $this->assertIsArray($result);
163         $this->assertArrayHasKey('templatename', $result);
165         $this->assertEquals('core_grades/grades/grader/gradingpanel/point', $result['templatename']);
167         $this->assertArrayHasKey('grade', $result);
168         $this->assertIsArray($result['grade']);
169         $this->assertArrayHasKey('grade', $result['grade']);
170         $this->assertIsFloat($result['grade']['grade']);
171         $this->assertEquals(grade_floatval(unformat_float(4)), $result['grade']['grade']);
172         $this->assertArrayHasKey('timecreated', $result['grade']);
173         $this->assertIsInt($result['grade']['timecreated']);
174         $this->assertArrayHasKey('timemodified', $result['grade']);
175         $this->assertIsInt($result['grade']['timemodified']);
177         $this->assertArrayHasKey('warnings', $result);
178         $this->assertIsArray($result['warnings']);
179         $this->assertEmpty($result['warnings']);
180     }
182     /**
183      * Get a forum instance.
184      *
185      * @param array $config
186      * @return forum_entity
187      */
188     protected function get_forum_instance(array $config = []): forum_entity {
189         $this->resetAfterTest();
191         $datagenerator = $this->getDataGenerator();
192         $course = $datagenerator->create_course();
193         $forum = $datagenerator->create_module('forum', array_merge($config, ['course' => $course->id]));
195         $vaultfactory = \mod_forum\local\container::get_vault_factory();
196         $vault = $vaultfactory->get_forum_vault();
198         return $vault->get_from_id((int) $forum->id);
199     }