Commit | Line | Data |
---|---|---|
6b7df0b5 EL |
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 | /** | |
f5700877 | 18 | * Unit tests for the lib/upgradelib.php library. |
6b7df0b5 EL |
19 | * |
20 | * @package core | |
21 | * @category phpunit | |
22 | * @copyright 2013 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
27 | ||
28 | global $CFG; | |
29 | require_once($CFG->libdir.'/upgradelib.php'); | |
30 | ||
6b7df0b5 | 31 | /** |
f5700877 | 32 | * Tests various classes and functions in upgradelib.php library. |
6b7df0b5 | 33 | */ |
f5700877 | 34 | class core_upgradelib_testcase extends advanced_testcase { |
6b7df0b5 EL |
35 | |
36 | /** | |
37 | * Test the {@link upgrade_stale_php_files_present() function | |
38 | */ | |
39 | public function test_upgrade_stale_php_files_present() { | |
40 | // Just call the function, must return bool false always | |
41 | // if there aren't any old files in the codebase. | |
42 | $this->assertFalse(upgrade_stale_php_files_present()); | |
43 | } | |
2a9d7a42 | 44 | |
2a9d7a42 DP |
45 | /** |
46 | * Populate some fake grade items into the database with specified | |
47 | * sortorder and course id. | |
48 | * | |
49 | * NOTE: This function doesn't make much attempt to respect the | |
50 | * gradebook internals, its simply used to fake some data for | |
51 | * testing the upgradelib function. Please don't use it for other | |
52 | * purposes. | |
53 | * | |
54 | * @param int $courseid id of course | |
55 | * @param int $sortorder numeric sorting order of item | |
56 | * @return stdClass grade item object from the database. | |
57 | */ | |
58 | private function insert_fake_grade_item_sortorder($courseid, $sortorder) { | |
59 | global $DB, $CFG; | |
60 | require_once($CFG->libdir.'/gradelib.php'); | |
61 | ||
62 | $item = new stdClass(); | |
63 | $item->courseid = $courseid; | |
64 | $item->sortorder = $sortorder; | |
65 | $item->gradetype = GRADE_TYPE_VALUE; | |
66 | $item->grademin = 30; | |
67 | $item->grademax = 110; | |
68 | $item->itemnumber = 1; | |
69 | $item->iteminfo = ''; | |
70 | $item->timecreated = time(); | |
71 | $item->timemodified = time(); | |
72 | ||
73 | $item->id = $DB->insert_record('grade_items', $item); | |
74 | ||
75 | return $DB->get_record('grade_items', array('id' => $item->id)); | |
76 | } | |
119cf17e | 77 | |
156d0486 MG |
78 | public function test_upgrade_extra_credit_weightoverride() { |
79 | global $DB, $CFG; | |
80 | ||
81 | $this->resetAfterTest(true); | |
82 | ||
1405f010 EL |
83 | require_once($CFG->libdir . '/db/upgradelib.php'); |
84 | ||
156d0486 MG |
85 | $c = array(); |
86 | $a = array(); | |
87 | $gi = array(); | |
88 | for ($i=0; $i<5; $i++) { | |
89 | $c[$i] = $this->getDataGenerator()->create_course(); | |
90 | $a[$i] = array(); | |
91 | $gi[$i] = array(); | |
92 | for ($j=0;$j<3;$j++) { | |
93 | $a[$i][$j] = $this->getDataGenerator()->create_module('assign', array('course' => $c[$i], 'grade' => 100)); | |
94 | $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a[$i][$j]->id, | |
95 | 'courseid' => $c[$i]->id, 'itemnumber' => 0); | |
96 | $gi[$i][$j] = grade_item::fetch($giparams); | |
97 | } | |
98 | } | |
99 | ||
100 | // Case 1: Course $c[0] has aggregation method different from natural. | |
101 | $coursecategory = grade_category::fetch_course_category($c[0]->id); | |
102 | $coursecategory->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN; | |
103 | $coursecategory->update(); | |
104 | $gi[0][1]->aggregationcoef = 1; | |
105 | $gi[0][1]->update(); | |
106 | $gi[0][2]->weightoverride = 1; | |
107 | $gi[0][2]->update(); | |
108 | ||
109 | // Case 2: Course $c[1] has neither extra credits nor overrides | |
110 | ||
111 | // Case 3: Course $c[2] has extra credits but no overrides | |
112 | $gi[2][1]->aggregationcoef = 1; | |
113 | $gi[2][1]->update(); | |
114 | ||
115 | // Case 4: Course $c[3] has no extra credits and has overrides | |
116 | $gi[3][2]->weightoverride = 1; | |
117 | $gi[3][2]->update(); | |
118 | ||
119 | // Case 5: Course $c[4] has both extra credits and overrides | |
120 | $gi[4][1]->aggregationcoef = 1; | |
121 | $gi[4][1]->update(); | |
122 | $gi[4][2]->weightoverride = 1; | |
123 | $gi[4][2]->update(); | |
124 | ||
125 | // Run the upgrade script and make sure only course $c[4] was marked as needed to be fixed. | |
126 | upgrade_extra_credit_weightoverride(); | |
127 | ||
128 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id})); | |
129 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[1]->id})); | |
130 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[2]->id})); | |
131 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[3]->id})); | |
132 | $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id}); | |
133 | ||
134 | set_config('gradebook_calculations_freeze_' . $c[4]->id, null); | |
135 | ||
136 | // Run the upgrade script for a single course only. | |
137 | upgrade_extra_credit_weightoverride($c[0]->id); | |
138 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id})); | |
139 | upgrade_extra_credit_weightoverride($c[4]->id); | |
140 | $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id}); | |
141 | } | |
716c0810 AG |
142 | |
143 | /** | |
144 | * Test the upgrade function for flagging courses with calculated grade item problems. | |
145 | */ | |
316c560c | 146 | public function test_upgrade_calculated_grade_items_freeze() { |
716c0810 | 147 | global $DB, $CFG; |
1405f010 | 148 | |
716c0810 AG |
149 | $this->resetAfterTest(); |
150 | ||
1405f010 EL |
151 | require_once($CFG->libdir . '/db/upgradelib.php'); |
152 | ||
716c0810 AG |
153 | // Create a user. |
154 | $user = $this->getDataGenerator()->create_user(); | |
155 | ||
156 | // Create a couple of courses. | |
157 | $course1 = $this->getDataGenerator()->create_course(); | |
158 | $course2 = $this->getDataGenerator()->create_course(); | |
159 | $course3 = $this->getDataGenerator()->create_course(); | |
160 | ||
161 | // Enrol the user in the courses. | |
162 | $studentrole = $DB->get_record('role', array('shortname' => 'student')); | |
163 | $maninstance1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST); | |
164 | $maninstance2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST); | |
165 | $maninstance3 = $DB->get_record('enrol', array('courseid' => $course3->id, 'enrol' => 'manual'), '*', MUST_EXIST); | |
166 | $manual = enrol_get_plugin('manual'); | |
167 | $manual->enrol_user($maninstance1, $user->id, $studentrole->id); | |
168 | $manual->enrol_user($maninstance2, $user->id, $studentrole->id); | |
169 | $manual->enrol_user($maninstance3, $user->id, $studentrole->id); | |
170 | ||
171 | // To create the data we need we freeze the grade book to use the old behaviour. | |
172 | set_config('gradebook_calculations_freeze_' . $course1->id, 20150627); | |
173 | set_config('gradebook_calculations_freeze_' . $course2->id, 20150627); | |
174 | set_config('gradebook_calculations_freeze_' . $course3->id, 20150627); | |
175 | $CFG->grade_minmaxtouse = 2; | |
176 | ||
177 | // Creating a category for a grade item. | |
178 | $gradecategory = new grade_category(); | |
179 | $gradecategory->fullname = 'calculated grade category'; | |
180 | $gradecategory->courseid = $course1->id; | |
181 | $gradecategory->insert(); | |
182 | $gradecategoryid = $gradecategory->id; | |
183 | ||
184 | // This is a manual grade item. | |
185 | $gradeitem = new grade_item(); | |
186 | $gradeitem->itemname = 'grade item one'; | |
187 | $gradeitem->itemtype = 'manual'; | |
188 | $gradeitem->categoryid = $gradecategoryid; | |
189 | $gradeitem->courseid = $course1->id; | |
190 | $gradeitem->idnumber = 'gi1'; | |
191 | $gradeitem->insert(); | |
192 | ||
193 | // Changing the category into a calculated grade category. | |
194 | $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id)); | |
195 | $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2'; | |
196 | $gradecategoryitem->update(); | |
197 | ||
198 | // Setting a grade for the student. | |
199 | $grade = $gradeitem->get_grade($user->id, true); | |
200 | $grade->finalgrade = 50; | |
201 | $grade->update(); | |
202 | // Creating all the grade_grade items. | |
203 | grade_regrade_final_grades($course1->id); | |
204 | // Updating the grade category to a new grade max and min. | |
205 | $gradecategoryitem->grademax = 50; | |
206 | $gradecategoryitem->grademin = 5; | |
207 | $gradecategoryitem->update(); | |
208 | ||
209 | // Different manual grade item for course 2. We are creating a course with a calculated grade item that has a grade max of | |
210 | // 50. The grade_grade will have a rawgrademax of 100 regardless. | |
211 | $gradeitem = new grade_item(); | |
212 | $gradeitem->itemname = 'grade item one'; | |
213 | $gradeitem->itemtype = 'manual'; | |
214 | $gradeitem->courseid = $course2->id; | |
215 | $gradeitem->idnumber = 'gi1'; | |
216 | $gradeitem->grademax = 25; | |
217 | $gradeitem->insert(); | |
218 | ||
219 | // Calculated grade item for course 2. | |
220 | $calculatedgradeitem = new grade_item(); | |
221 | $calculatedgradeitem->itemname = 'calculated grade'; | |
222 | $calculatedgradeitem->itemtype = 'manual'; | |
223 | $calculatedgradeitem->courseid = $course2->id; | |
224 | $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2'; | |
225 | $calculatedgradeitem->grademax = 50; | |
226 | $calculatedgradeitem->insert(); | |
227 | ||
228 | // Assigning a grade for the user. | |
229 | $grade = $gradeitem->get_grade($user->id, true); | |
230 | $grade->finalgrade = 10; | |
231 | $grade->update(); | |
232 | ||
233 | // Setting all of the grade_grade items. | |
234 | grade_regrade_final_grades($course2->id); | |
235 | ||
236 | // Different manual grade item for course 3. We are creating a course with a calculated grade item that has a grade max of | |
237 | // 50. The grade_grade will have a rawgrademax of 100 regardless. | |
238 | $gradeitem = new grade_item(); | |
239 | $gradeitem->itemname = 'grade item one'; | |
240 | $gradeitem->itemtype = 'manual'; | |
241 | $gradeitem->courseid = $course3->id; | |
242 | $gradeitem->idnumber = 'gi1'; | |
243 | $gradeitem->grademax = 25; | |
244 | $gradeitem->insert(); | |
245 | ||
246 | // Calculated grade item for course 2. | |
247 | $calculatedgradeitem = new grade_item(); | |
248 | $calculatedgradeitem->itemname = 'calculated grade'; | |
249 | $calculatedgradeitem->itemtype = 'manual'; | |
250 | $calculatedgradeitem->courseid = $course3->id; | |
251 | $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2'; | |
252 | $calculatedgradeitem->grademax = 50; | |
253 | $calculatedgradeitem->insert(); | |
254 | ||
255 | // Assigning a grade for the user. | |
256 | $grade = $gradeitem->get_grade($user->id, true); | |
257 | $grade->finalgrade = 10; | |
258 | $grade->update(); | |
259 | ||
260 | // Setting all of the grade_grade items. | |
261 | grade_regrade_final_grades($course3->id); | |
262 | // Need to do this first before changing the other courses, otherwise they will be flagged too early. | |
263 | set_config('gradebook_calculations_freeze_' . $course3->id, null); | |
264 | upgrade_calculated_grade_items($course3->id); | |
265 | $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course3->id}); | |
266 | ||
267 | // Change the setting back to null. | |
268 | set_config('gradebook_calculations_freeze_' . $course1->id, null); | |
269 | set_config('gradebook_calculations_freeze_' . $course2->id, null); | |
270 | // Run the upgrade. | |
271 | upgrade_calculated_grade_items(); | |
272 | // The setting should be set again after the upgrade. | |
273 | $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course1->id}); | |
274 | $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course2->id}); | |
275 | } | |
316c560c AG |
276 | |
277 | function test_upgrade_calculated_grade_items_regrade() { | |
278 | global $DB, $CFG; | |
1405f010 | 279 | |
316c560c AG |
280 | $this->resetAfterTest(); |
281 | ||
1405f010 EL |
282 | require_once($CFG->libdir . '/db/upgradelib.php'); |
283 | ||
316c560c AG |
284 | // Create a user. |
285 | $user = $this->getDataGenerator()->create_user(); | |
286 | ||
287 | // Create a course. | |
288 | $course = $this->getDataGenerator()->create_course(); | |
289 | ||
290 | // Enrol the user in the course. | |
291 | $studentrole = $DB->get_record('role', array('shortname' => 'student')); | |
292 | $maninstance1 = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); | |
293 | $manual = enrol_get_plugin('manual'); | |
294 | $manual->enrol_user($maninstance1, $user->id, $studentrole->id); | |
295 | ||
296 | set_config('upgrade_calculatedgradeitemsonlyregrade', 1); | |
297 | ||
298 | // Creating a category for a grade item. | |
299 | $gradecategory = new grade_category(); | |
300 | $gradecategory->fullname = 'calculated grade category'; | |
301 | $gradecategory->courseid = $course->id; | |
302 | $gradecategory->insert(); | |
303 | $gradecategoryid = $gradecategory->id; | |
304 | ||
305 | // This is a manual grade item. | |
306 | $gradeitem = new grade_item(); | |
307 | $gradeitem->itemname = 'grade item one'; | |
308 | $gradeitem->itemtype = 'manual'; | |
309 | $gradeitem->categoryid = $gradecategoryid; | |
310 | $gradeitem->courseid = $course->id; | |
311 | $gradeitem->idnumber = 'gi1'; | |
312 | $gradeitem->insert(); | |
313 | ||
314 | // Changing the category into a calculated grade category. | |
315 | $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id)); | |
316 | $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2'; | |
317 | $gradecategoryitem->grademax = 50; | |
318 | $gradecategoryitem->grademin = 15; | |
319 | $gradecategoryitem->update(); | |
320 | ||
321 | // Setting a grade for the student. | |
322 | $grade = $gradeitem->get_grade($user->id, true); | |
323 | $grade->finalgrade = 50; | |
324 | $grade->update(); | |
325 | ||
326 | grade_regrade_final_grades($course->id); | |
327 | $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id)); | |
328 | $grade->rawgrademax = 100; | |
329 | $grade->rawgrademin = 0; | |
330 | $grade->update(); | |
331 | $this->assertNotEquals($gradecategoryitem->grademax, $grade->rawgrademax); | |
332 | $this->assertNotEquals($gradecategoryitem->grademin, $grade->rawgrademin); | |
333 | ||
334 | // This is the function that we are testing. If we comment out this line, then the test fails because the grade items | |
335 | // are not flagged for regrading. | |
336 | upgrade_calculated_grade_items(); | |
337 | grade_regrade_final_grades($course->id); | |
338 | ||
339 | $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id)); | |
340 | ||
341 | $this->assertEquals($gradecategoryitem->grademax, $grade->rawgrademax); | |
342 | $this->assertEquals($gradecategoryitem->grademin, $grade->rawgrademin); | |
343 | } | |
0d1e5456 | 344 | |
70dfd48f AG |
345 | /** |
346 | * Test that the upgrade script correctly flags courses to be frozen due to letter boundary problems. | |
347 | */ | |
348 | public function test_upgrade_course_letter_boundary() { | |
349 | global $CFG, $DB; | |
350 | $this->resetAfterTest(true); | |
351 | ||
ece791db DM |
352 | require_once($CFG->libdir . '/db/upgradelib.php'); |
353 | ||
70dfd48f AG |
354 | // Create a user. |
355 | $user = $this->getDataGenerator()->create_user(); | |
356 | ||
357 | // Create some courses. | |
358 | $courses = array(); | |
359 | $contexts = array(); | |
97a85bf6 | 360 | for ($i = 0; $i < 45; $i++) { |
70dfd48f AG |
361 | $course = $this->getDataGenerator()->create_course(); |
362 | $context = context_course::instance($course->id); | |
ece791db | 363 | if (in_array($i, array(2, 5, 10, 13, 14, 19, 23, 25, 30, 34, 36))) { |
70dfd48f AG |
364 | // Assign good letter boundaries. |
365 | $this->assign_good_letter_boundary($context->id); | |
366 | } | |
ece791db | 367 | if (in_array($i, array(3, 6, 11, 15, 20, 24, 26, 31, 35))) { |
70dfd48f AG |
368 | // Assign bad letter boundaries. |
369 | $this->assign_bad_letter_boundary($context->id); | |
370 | } | |
371 | ||
97a85bf6 | 372 | if (in_array($i, array(3, 9, 10, 11, 18, 19, 20, 29, 30, 31, 40))) { |
70dfd48f | 373 | grade_set_setting($course->id, 'displaytype', '3'); |
ece791db | 374 | } else if (in_array($i, array(8, 17, 28))) { |
70dfd48f AG |
375 | grade_set_setting($course->id, 'displaytype', '2'); |
376 | } | |
377 | ||
97a85bf6 AG |
378 | if (in_array($i, array(37, 43))) { |
379 | // Show. | |
380 | grade_set_setting($course->id, 'report_user_showlettergrade', '1'); | |
381 | } else if (in_array($i, array(38, 42))) { | |
382 | // Hide. | |
383 | grade_set_setting($course->id, 'report_user_showlettergrade', '0'); | |
70dfd48f AG |
384 | } |
385 | ||
97a85bf6 AG |
386 | $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Test!')); |
387 | $gi = grade_item::fetch( | |
388 | array('itemtype' => 'mod', | |
389 | 'itemmodule' => 'assign', | |
390 | 'iteminstance' => $assignrow->id, | |
391 | 'courseid' => $course->id)); | |
392 | if (in_array($i, array(6, 13, 14, 15, 23, 24, 34, 35, 36, 41))) { | |
393 | grade_item::set_properties($gi, array('display' => 3)); | |
394 | $gi->update(); | |
395 | } else if (in_array($i, array(12, 21, 32))) { | |
396 | grade_item::set_properties($gi, array('display' => 2)); | |
397 | $gi->update(); | |
398 | } | |
399 | $gradegrade = new grade_grade(); | |
400 | $gradegrade->itemid = $gi->id; | |
401 | $gradegrade->userid = $user->id; | |
402 | $gradegrade->rawgrade = 55.5563; | |
403 | $gradegrade->finalgrade = 55.5563; | |
404 | $gradegrade->rawgrademax = 100; | |
405 | $gradegrade->rawgrademin = 0; | |
406 | $gradegrade->timecreated = time(); | |
407 | $gradegrade->timemodified = time(); | |
408 | $gradegrade->insert(); | |
409 | ||
70dfd48f AG |
410 | $contexts[] = $context; |
411 | $courses[] = $course; | |
412 | } | |
413 | ||
414 | upgrade_course_letter_boundary(); | |
415 | ||
416 | // No system setting for grade letter boundaries. | |
417 | // [0] A course with no letter boundaries. | |
418 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[0]->id})); | |
419 | // [1] A course with letter boundaries which are default. | |
420 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[1]->id})); | |
421 | // [2] A course with letter boundaries which are custom but not affected. | |
422 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[2]->id})); | |
423 | // [3] A course with letter boundaries which are custom and will be affected. | |
41abbbbd | 424 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[3]->id}); |
70dfd48f AG |
425 | // [4] A course with no letter boundaries, but with a grade item with letter boundaries which are default. |
426 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[4]->id})); | |
427 | // [5] A course with no letter boundaries, but with a grade item with letter boundaries which are not default, but not affected. | |
428 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[5]->id})); | |
429 | // [6] A course with no letter boundaries, but with a grade item with letter boundaries which are not default which will be affected. | |
41abbbbd | 430 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[6]->id}); |
70dfd48f AG |
431 | |
432 | // System setting for grade letter boundaries (default). | |
433 | set_config('grade_displaytype', '3'); | |
97a85bf6 | 434 | for ($i = 0; $i < 45; $i++) { |
ece791db DM |
435 | unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); |
436 | } | |
70dfd48f | 437 | upgrade_course_letter_boundary(); |
ece791db | 438 | |
70dfd48f AG |
439 | // [7] A course with no grade display settings for the course or grade items. |
440 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[7]->id})); | |
441 | // [8] A course with grade display settings, but for something that isn't letters. | |
442 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[8]->id})); | |
443 | // [9] A course with grade display settings of letters which are default. | |
444 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[9]->id})); | |
445 | // [10] A course with grade display settings of letters which are not default, but not affected. | |
446 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[10]->id})); | |
447 | // [11] A course with grade display settings of letters which are not default, which will be affected. | |
41abbbbd | 448 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[11]->id}); |
70dfd48f AG |
449 | // [12] A grade item with display settings that are not letters. |
450 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[12]->id})); | |
451 | // [13] A grade item with display settings of letters which are default. | |
452 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[13]->id})); | |
453 | // [14] A grade item with display settings of letters which are not default, but not affected. | |
454 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[14]->id})); | |
455 | // [15] A grade item with display settings of letters which are not default, which will be affected. | |
41abbbbd | 456 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[15]->id}); |
70dfd48f AG |
457 | |
458 | // System setting for grade letter boundaries (custom with problem). | |
459 | $systemcontext = context_system::instance(); | |
460 | $this->assign_bad_letter_boundary($systemcontext->id); | |
97a85bf6 | 461 | for ($i = 0; $i < 45; $i++) { |
ece791db DM |
462 | unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); |
463 | } | |
70dfd48f AG |
464 | upgrade_course_letter_boundary(); |
465 | ||
466 | // [16] A course with no grade display settings for the course or grade items. | |
41abbbbd | 467 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[16]->id}); |
70dfd48f AG |
468 | // [17] A course with grade display settings, but for something that isn't letters. |
469 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[17]->id})); | |
470 | // [18] A course with grade display settings of letters which are default. | |
41abbbbd | 471 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[18]->id}); |
70dfd48f AG |
472 | // [19] A course with grade display settings of letters which are not default, but not affected. |
473 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[19]->id})); | |
474 | // [20] A course with grade display settings of letters which are not default, which will be affected. | |
41abbbbd | 475 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[20]->id}); |
70dfd48f | 476 | // [21] A grade item with display settings which are not letters. Grade total will be affected so should be frozen. |
41abbbbd | 477 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[21]->id}); |
70dfd48f | 478 | // [22] A grade item with display settings of letters which are default. |
41abbbbd | 479 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[22]->id}); |
70dfd48f AG |
480 | // [23] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting. |
481 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[23]->id})); | |
482 | // [24] A grade item with display settings of letters which are not default, which will be affected. | |
41abbbbd | 483 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[24]->id}); |
70dfd48f AG |
484 | // [25] A course which is using the default grade display setting, but has updated the grade letter boundary (not 57) Should not be frozen. |
485 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[25]->id})); | |
486 | // [26] A course that is using the default display setting (letters) and altered the letter boundary with 57. Should be frozen. | |
41abbbbd | 487 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[26]->id}); |
ece791db DM |
488 | |
489 | // System setting not showing letters. | |
490 | set_config('grade_displaytype', '2'); | |
97a85bf6 | 491 | for ($i = 0; $i < 45; $i++) { |
ece791db DM |
492 | unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); |
493 | } | |
494 | upgrade_course_letter_boundary(); | |
495 | ||
496 | // [27] A course with no grade display settings for the course or grade items. | |
497 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[27]->id})); | |
498 | // [28] A course with grade display settings, but for something that isn't letters. | |
499 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[28]->id})); | |
500 | // [29] A course with grade display settings of letters which are default. | |
41abbbbd | 501 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[29]->id}); |
ece791db DM |
502 | // [30] A course with grade display settings of letters which are not default, but not affected. |
503 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[30]->id})); | |
504 | // [31] A course with grade display settings of letters which are not default, which will be affected. | |
41abbbbd | 505 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[31]->id}); |
ece791db DM |
506 | // [32] A grade item with display settings which are not letters. |
507 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[32]->id})); | |
508 | // [33] All system defaults. | |
509 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[33]->id})); | |
510 | // [34] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting. | |
511 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[34]->id})); | |
512 | // [35] A grade item with display settings of letters which are not default, which will be affected. | |
41abbbbd | 513 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[35]->id}); |
ece791db DM |
514 | // [36] A course with grade display settings of letters with modified and good boundary (not 57) Should not be frozen. |
515 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[36]->id})); | |
97a85bf6 AG |
516 | |
517 | // Previous site conditions still exist. | |
518 | for ($i = 0; $i < 45; $i++) { | |
519 | unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); | |
520 | } | |
521 | upgrade_course_letter_boundary(); | |
522 | ||
523 | // [37] Site setting for not showing the letter column and course setting set to show (frozen). | |
524 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[37]->id}); | |
525 | // [38] Site setting for not showing the letter column and course setting set to hide. | |
526 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[38]->id})); | |
527 | // [39] Site setting for not showing the letter column and course setting set to default. | |
528 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[39]->id})); | |
529 | // [40] Site setting for not showing the letter column and course setting set to default. Course display set to letters (frozen). | |
530 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[40]->id}); | |
531 | // [41] Site setting for not showing the letter column and course setting set to default. Grade item display set to letters (frozen). | |
532 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[41]->id}); | |
533 | ||
534 | // Previous site conditions still exist. | |
535 | for ($i = 0; $i < 45; $i++) { | |
536 | unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); | |
537 | } | |
538 | set_config('grade_report_user_showlettergrade', '1'); | |
539 | upgrade_course_letter_boundary(); | |
540 | ||
541 | // [42] Site setting for showing the letter column, but course setting set to hide. | |
542 | $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[42]->id})); | |
543 | // [43] Site setting for showing the letter column and course setting set to show (frozen). | |
544 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[43]->id}); | |
545 | // [44] Site setting for showing the letter column and course setting set to default (frozen). | |
546 | $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[44]->id}); | |
70dfd48f AG |
547 | } |
548 | ||
549 | /** | |
550 | * Test upgrade_letter_boundary_needs_freeze function. | |
551 | */ | |
552 | public function test_upgrade_letter_boundary_needs_freeze() { | |
ece791db DM |
553 | global $CFG; |
554 | ||
70dfd48f AG |
555 | $this->resetAfterTest(); |
556 | ||
ece791db DM |
557 | require_once($CFG->libdir . '/db/upgradelib.php'); |
558 | ||
70dfd48f AG |
559 | $courses = array(); |
560 | $contexts = array(); | |
561 | for ($i = 0; $i < 3; $i++) { | |
562 | $courses[] = $this->getDataGenerator()->create_course(); | |
563 | $contexts[] = context_course::instance($courses[$i]->id); | |
564 | } | |
565 | ||
566 | // Course one is not using a letter boundary. | |
567 | $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[0])); | |
568 | ||
569 | // Let's make course 2 use the bad boundary. | |
570 | $this->assign_bad_letter_boundary($contexts[1]->id); | |
571 | $this->assertTrue(upgrade_letter_boundary_needs_freeze($contexts[1])); | |
572 | // Course 3 has letter boundaries that are fine. | |
573 | $this->assign_good_letter_boundary($contexts[2]->id); | |
574 | $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[2])); | |
575 | // Try the system context not using a letter boundary. | |
576 | $systemcontext = context_system::instance(); | |
577 | $this->assertFalse(upgrade_letter_boundary_needs_freeze($systemcontext)); | |
578 | } | |
579 | ||
580 | /** | |
581 | * Assigns letter boundaries with comparison problems. | |
582 | * | |
583 | * @param int $contextid Context ID. | |
584 | */ | |
585 | private function assign_bad_letter_boundary($contextid) { | |
586 | global $DB; | |
587 | $newlettersscale = array( | |
588 | array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'), | |
589 | array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'), | |
590 | array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'), | |
591 | array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'), | |
592 | array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'), | |
593 | array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'), | |
594 | array('contextid' => $contextid, 'lowerboundary' => 57.00000, 'letter' => 'C'), | |
595 | array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'), | |
596 | array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'), | |
597 | array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'), | |
598 | array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'), | |
599 | ); | |
ece791db DM |
600 | |
601 | $DB->delete_records('grade_letters', array('contextid' => $contextid)); | |
70dfd48f AG |
602 | foreach ($newlettersscale as $record) { |
603 | // There is no API to do this, so we have to manually insert into the database. | |
604 | $DB->insert_record('grade_letters', $record); | |
605 | } | |
606 | } | |
607 | ||
608 | /** | |
609 | * Assigns letter boundaries with no comparison problems. | |
610 | * | |
611 | * @param int $contextid Context ID. | |
612 | */ | |
613 | private function assign_good_letter_boundary($contextid) { | |
614 | global $DB; | |
615 | $newlettersscale = array( | |
616 | array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'), | |
617 | array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'), | |
618 | array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'), | |
619 | array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'), | |
620 | array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'), | |
621 | array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'), | |
622 | array('contextid' => $contextid, 'lowerboundary' => 54.00000, 'letter' => 'C'), | |
623 | array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'), | |
624 | array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'), | |
625 | array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'), | |
626 | array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'), | |
627 | ); | |
ece791db DM |
628 | |
629 | $DB->delete_records('grade_letters', array('contextid' => $contextid)); | |
70dfd48f AG |
630 | foreach ($newlettersscale as $record) { |
631 | // There is no API to do this, so we have to manually insert into the database. | |
632 | $DB->insert_record('grade_letters', $record); | |
633 | } | |
634 | } | |
f2330472 AA |
635 | |
636 | /** | |
637 | * Test libcurl custom check api. | |
638 | */ | |
639 | public function test_check_libcurl_version() { | |
640 | $supportedversion = 0x071304; | |
641 | $curlinfo = curl_version(); | |
642 | $currentversion = $curlinfo['version_number']; | |
643 | ||
644 | $result = new environment_results("custom_checks"); | |
645 | if ($currentversion < $supportedversion) { | |
646 | $this->assertFalse(check_libcurl_version($result)->getStatus()); | |
647 | } else { | |
648 | $this->assertNull(check_libcurl_version($result)); | |
649 | } | |
650 | } | |
a5722727 MG |
651 | |
652 | /** | |
653 | * Create two pages with blocks, delete one page and make sure upgrade script deletes orphaned blocks | |
654 | */ | |
655 | public function test_delete_block_positions() { | |
656 | global $DB, $CFG; | |
657 | require_once($CFG->dirroot . '/my/lib.php'); | |
658 | $this->resetAfterTest(); | |
659 | ||
660 | // Make sure each block on system dashboard page has a position. | |
661 | $systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => MY_PAGE_PRIVATE)); | |
662 | $systemcontext = context_system::instance(); | |
663 | $blockinstances = $DB->get_records('block_instances', array('parentcontextid' => $systemcontext->id, | |
664 | 'pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id)); | |
665 | $this->assertNotEmpty($blockinstances); | |
666 | foreach ($blockinstances as $bi) { | |
667 | $DB->insert_record('block_positions', ['subpage' => $systempage->id, 'pagetype' => 'my-index', 'contextid' => $systemcontext->id, | |
668 | 'blockinstanceid' => $bi->id, 'visible' => 1, 'weight' => $bi->defaultweight]); | |
669 | } | |
670 | ||
671 | // Create two users and make two copies of the system dashboard. | |
672 | $user1 = $this->getDataGenerator()->create_user(); | |
673 | $user2 = $this->getDataGenerator()->create_user(); | |
674 | $page1 = my_copy_page($user1->id, MY_PAGE_PRIVATE, 'my-index'); | |
675 | $page2 = my_copy_page($user2->id, MY_PAGE_PRIVATE, 'my-index'); | |
676 | ||
677 | $context1 = context_user::instance($user1->id); | |
678 | $context2 = context_user::instance($user2->id); | |
679 | ||
680 | // Delete second page without deleting block positions. | |
681 | $DB->delete_records('my_pages', ['id' => $page2->id]); | |
682 | ||
683 | // Blocks are still here. | |
684 | $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page1->id, 'pagetype' => 'my-index', 'contextid' => $context1->id])); | |
685 | $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page2->id, 'pagetype' => 'my-index', 'contextid' => $context2->id])); | |
686 | ||
687 | // Run upgrade script that should delete orphaned block_positions. | |
688 | upgrade_block_positions(); | |
689 | ||
690 | // First user still has all his block_positions, second user does not. | |
691 | $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page1->id, 'pagetype' => 'my-index', 'contextid' => $context1->id])); | |
692 | $this->assertEquals(0, $DB->count_records('block_positions', ['subpage' => $page2->id, 'pagetype' => 'my-index'])); | |
693 | } | |
31bd1023 DM |
694 | |
695 | /** | |
696 | * Test the conversion of auth plugin settings names. | |
697 | */ | |
698 | public function test_upgrade_fix_config_auth_plugin_names() { | |
699 | $this->resetAfterTest(); | |
700 | ||
701 | // Let the plugin auth_foo use legacy format only. | |
702 | set_config('name1', 'val1', 'auth/foo'); | |
703 | set_config('name2', 'val2', 'auth/foo'); | |
704 | ||
705 | // Let the plugin auth_bar use new format only. | |
706 | set_config('name1', 'val1', 'auth_bar'); | |
707 | set_config('name2', 'val2', 'auth_bar'); | |
708 | ||
709 | // Let the plugin auth_baz use a mix of legacy and new format, with no conflicts. | |
710 | set_config('name1', 'val1', 'auth_baz'); | |
711 | set_config('name1', 'val1', 'auth/baz'); | |
712 | set_config('name2', 'val2', 'auth/baz'); | |
713 | set_config('name3', 'val3', 'auth_baz'); | |
714 | ||
715 | // Let the plugin auth_qux use a mix of legacy and new format, with conflicts. | |
716 | set_config('name1', 'val1', 'auth_qux'); | |
717 | set_config('name1', 'val2', 'auth/qux'); | |
718 | ||
719 | // Execute the migration. | |
720 | upgrade_fix_config_auth_plugin_names('foo'); | |
721 | upgrade_fix_config_auth_plugin_names('bar'); | |
722 | upgrade_fix_config_auth_plugin_names('baz'); | |
723 | upgrade_fix_config_auth_plugin_names('qux'); | |
724 | ||
725 | // Assert that legacy settings are gone and no new were introduced. | |
726 | $this->assertEmpty((array) get_config('auth/foo')); | |
727 | $this->assertEmpty((array) get_config('auth/bar')); | |
728 | $this->assertEmpty((array) get_config('auth/baz')); | |
729 | $this->assertEmpty((array) get_config('auth/qux')); | |
730 | ||
731 | // Assert values were simply kept where there was no conflict. | |
732 | $this->assertSame('val1', get_config('auth_foo', 'name1')); | |
733 | $this->assertSame('val2', get_config('auth_foo', 'name2')); | |
734 | ||
735 | $this->assertSame('val1', get_config('auth_bar', 'name1')); | |
736 | $this->assertSame('val2', get_config('auth_bar', 'name2')); | |
737 | ||
738 | $this->assertSame('val1', get_config('auth_baz', 'name1')); | |
739 | $this->assertSame('val2', get_config('auth_baz', 'name2')); | |
740 | $this->assertSame('val3', get_config('auth_baz', 'name3')); | |
741 | ||
742 | // Assert the new format took precedence in case of conflict. | |
743 | $this->assertSame('val1', get_config('auth_qux', 'name1')); | |
744 | } | |
e46fde42 JO |
745 | |
746 | /** | |
747 | * Create a collection of test themes to test determining parent themes. | |
748 | * | |
749 | * @return Url to the path containing the test themes | |
750 | */ | |
751 | public function create_testthemes() { | |
752 | global $CFG; | |
753 | ||
754 | $themedircontent = [ | |
755 | 'testtheme' => [ | |
756 | 'config.php' => '<?php $THEME->name = "testtheme"; $THEME->parents = [""];', | |
757 | ], | |
758 | 'childoftesttheme' => [ | |
759 | 'config.php' => '<?php $THEME->name = "childofboost"; $THEME->parents = ["testtheme"];', | |
760 | ], | |
761 | 'infinite' => [ | |
762 | 'config.php' => '<?php $THEME->name = "infinite"; $THEME->parents = ["forever"];', | |
763 | ], | |
764 | 'forever' => [ | |
765 | 'config.php' => '<?php $THEME->name = "forever"; $THEME->parents = ["infinite", "childoftesttheme"];', | |
766 | ], | |
767 | 'orphantheme' => [ | |
768 | 'config.php' => '<?php $THEME->name = "orphantheme"; $THEME->parents = [];', | |
769 | ], | |
770 | 'loop' => [ | |
771 | 'config.php' => '<?php $THEME->name = "loop"; $THEME->parents = ["around"];', | |
772 | ], | |
773 | 'around' => [ | |
774 | 'config.php' => '<?php $THEME->name = "around"; $THEME->parents = ["loop"];', | |
775 | ], | |
776 | 'themewithbrokenparent' => [ | |
777 | 'config.php' => '<?php $THEME->name = "orphantheme"; $THEME->parents = ["nonexistent", "testtheme"];', | |
778 | ], | |
779 | ]; | |
780 | $vthemedir = \org\bovigo\vfs\vfsStream::setup('themes', null, $themedircontent); | |
781 | ||
782 | return \org\bovigo\vfs\vfsStream::url('themes'); | |
783 | } | |
784 | ||
785 | /** | |
786 | * Test finding theme locations. | |
787 | */ | |
788 | public function test_upgrade_find_theme_location() { | |
789 | global $CFG; | |
790 | ||
791 | $this->resetAfterTest(); | |
792 | ||
793 | $CFG->themedir = $this->create_testthemes(); | |
794 | ||
795 | $this->assertSame($CFG->dirroot . '/theme/boost', upgrade_find_theme_location('boost')); | |
796 | $this->assertSame($CFG->dirroot . '/theme/clean', upgrade_find_theme_location('clean')); | |
797 | $this->assertSame($CFG->dirroot . '/theme/bootstrapbase', upgrade_find_theme_location('bootstrapbase')); | |
798 | ||
799 | $this->assertSame($CFG->themedir . '/testtheme', upgrade_find_theme_location('testtheme')); | |
800 | $this->assertSame($CFG->themedir . '/childoftesttheme', upgrade_find_theme_location('childoftesttheme')); | |
801 | } | |
802 | ||
803 | /** | |
804 | * Test figuring out if theme is or is a child of a certain theme. | |
805 | */ | |
806 | public function test_upgrade_theme_is_from_family() { | |
807 | global $CFG; | |
808 | ||
809 | $this->resetAfterTest(); | |
810 | ||
811 | $CFG->themedir = $this->create_testthemes(); | |
812 | ||
813 | $this->assertTrue(upgrade_theme_is_from_family('boost', 'boost'), 'Boost is a boost theme'); | |
814 | $this->assertTrue(upgrade_theme_is_from_family('bootstrapbase', 'clean'), 'Clean is a bootstrap base theme'); | |
815 | $this->assertFalse(upgrade_theme_is_from_family('boost', 'clean'), 'Clean is not a boost theme'); | |
816 | ||
817 | $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'childoftesttheme'), 'childoftesttheme is a testtheme'); | |
818 | $this->assertFalse(upgrade_theme_is_from_family('testtheme', 'orphantheme'), 'ofphantheme is not a testtheme'); | |
819 | $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'infinite'), 'Infinite loop with testtheme parent is true'); | |
820 | $this->assertFalse(upgrade_theme_is_from_family('testtheme', 'loop'), 'Infinite loop without testtheme parent is false'); | |
821 | $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'themewithbrokenparent'), 'No error on broken parent'); | |
822 | } | |
6b7df0b5 | 823 | } |