Differences Between: [Versions 310 and 311] [Versions 39 and 311]
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 namespace mod_data; 18 19 /** 20 * Unit tests for import.php. 21 * 22 * @package mod_data 23 * @category test 24 * @copyright 2019 Tobias Reischmann 25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 */ 27 class import_test extends \advanced_testcase { 28 29 /** 30 * Set up function. 31 */ 32 protected function setUp(): void { 33 parent::setUp(); 34 35 global $CFG; 36 require_once($CFG->dirroot . '/mod/data/lib.php'); 37 require_once($CFG->dirroot . '/lib/datalib.php'); 38 require_once($CFG->dirroot . '/lib/csvlib.class.php'); 39 require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php'); 40 require_once($CFG->dirroot . '/mod/data/tests/generator/lib.php'); 41 } 42 43 /** 44 * Get the test data. 45 * In this instance we are setting up database records to be used in the unit tests. 46 * 47 * @return array 48 */ 49 protected function get_test_data(): array { 50 $this->resetAfterTest(true); 51 52 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 53 $course = $this->getDataGenerator()->create_course(); 54 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); 55 $this->setUser($teacher); 56 $student = $this->getDataGenerator()->create_and_enrol($course, 'student', array('username' => 'student')); 57 58 $data = $generator->create_instance(array('course' => $course->id)); 59 $cm = get_coursemodule_from_instance('data', $data->id); 60 61 // Add fields. 62 $fieldrecord = new \stdClass(); 63 $fieldrecord->name = 'ID'; // Identifier of the records for testing. 64 $fieldrecord->type = 'number'; 65 $generator->create_field($fieldrecord, $data); 66 67 $fieldrecord->name = 'Param2'; 68 $fieldrecord->type = 'text'; 69 $generator->create_field($fieldrecord, $data); 70 71 72 return [ 73 'teacher' => $teacher, 74 'student' => $student, 75 'data' => $data, 76 'cm' => $cm, 77 ]; 78 } 79 80 /** 81 * Test uploading entries for a data instance without userdata. 82 * @throws dml_exception 83 */ 84 public function test_import(): void { 85 [ 86 'data' => $data, 87 'cm' => $cm, 88 'teacher' => $teacher, 89 ] = $this->get_test_data(); 90 91 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import.csv'); 92 ob_start(); 93 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 94 ob_end_clean(); 95 96 // No userdata is present in the file: Fallback is to assign the uploading user as author. 97 $expecteduserids = array(); 98 $expecteduserids[1] = $teacher->id; 99 $expecteduserids[2] = $teacher->id; 100 101 $records = $this->get_data_records($data->id); 102 $this->assertCount(2, $records); 103 foreach ($records as $record) { 104 $identifier = $record->items['ID']->content; 105 $this->assertEquals($expecteduserids[$identifier], $record->userid); 106 } 107 } 108 109 /** 110 * Test uploading entries for a data instance with userdata. 111 * 112 * At least one entry has an identifiable user, which is assigned as author. 113 * @throws dml_exception 114 */ 115 public function test_import_with_userdata(): void { 116 [ 117 'data' => $data, 118 'cm' => $cm, 119 'teacher' => $teacher, 120 'student' => $student, 121 ] = $this->get_test_data(); 122 123 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_userdata.csv'); 124 ob_start(); 125 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 126 ob_end_clean(); 127 128 $expecteduserids = array(); 129 $expecteduserids[1] = $student->id; // User student exists and is assigned as author. 130 $expecteduserids[2] = $teacher->id; // User student2 does not exist. Fallback is the uploading user. 131 132 $records = $this->get_data_records($data->id); 133 $this->assertCount(2, $records); 134 foreach ($records as $record) { 135 $identifier = $record->items['ID']->content; 136 $this->assertEquals($expecteduserids[$identifier], $record->userid); 137 } 138 } 139 140 /** 141 * Test uploading entries for a data instance with userdata and a defined field 'Username'. 142 * 143 * This should test the corner case, in which a user has defined a data fields, which has the same name 144 * as the current lang string for username. In that case, the first Username entry is used for the field. 145 * The second one is used to identify the author. 146 * @throws coding_exception 147 * @throws dml_exception 148 */ 149 public function test_import_with_field_username(): void { 150 [ 151 'data' => $data, 152 'cm' => $cm, 153 'teacher' => $teacher, 154 'student' => $student, 155 ] = $this->get_test_data(); 156 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 157 158 // Add username field. 159 $fieldrecord = new \stdClass(); 160 $fieldrecord->name = 'Username'; 161 $fieldrecord->type = 'text'; 162 $generator->create_field($fieldrecord, $data); 163 164 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_field_username.csv'); 165 ob_start(); 166 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 167 ob_end_clean(); 168 169 $expecteduserids = array(); 170 $expecteduserids[1] = $student->id; // User student exists and is assigned as author. 171 $expecteduserids[2] = $teacher->id; // User student2 does not exist. Fallback is the uploading user. 172 $expecteduserids[3] = $student->id; // User student exists and is assigned as author. 173 174 $expectedcontent = array(); 175 $expectedcontent[1] = array( 176 'Username' => 'otherusername1', 177 'Param2' => 'My first entry', 178 ); 179 $expectedcontent[2] = array( 180 'Username' => 'otherusername2', 181 'Param2' => 'My second entry', 182 ); 183 $expectedcontent[3] = array( 184 'Username' => 'otherusername3', 185 'Param2' => 'My third entry', 186 ); 187 188 $records = $this->get_data_records($data->id); 189 $this->assertCount(3, $records); 190 foreach ($records as $record) { 191 $identifier = $record->items['ID']->content; 192 $this->assertEquals($expecteduserids[$identifier], $record->userid); 193 194 foreach ($expectedcontent[$identifier] as $field => $value) { 195 $this->assertEquals($value, $record->items[$field]->content, 196 "The value of field \"$field\" for the record at position \"$identifier\" ". 197 "which is \"{$record->items[$field]->content}\" does not match the expected value \"$value\"."); 198 } 199 } 200 } 201 202 /** 203 * Test uploading entries for a data instance with a field 'Username' but only one occurrence in the csv file. 204 * 205 * This should test the corner case, in which a user has defined a data fields, which has the same name 206 * as the current lang string for username. In that case, the only Username entry is used for the field. 207 * The author should not be set. 208 * @throws coding_exception 209 * @throws dml_exception 210 */ 211 public function test_import_with_field_username_without_userdata(): void { 212 [ 213 'data' => $data, 214 'cm' => $cm, 215 'teacher' => $teacher, 216 'student' => $student, 217 ] = $this->get_test_data(); 218 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 219 220 // Add username field. 221 $fieldrecord = new \stdClass(); 222 $fieldrecord->name = 'Username'; 223 $fieldrecord->type = 'text'; 224 $generator->create_field($fieldrecord, $data); 225 226 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_userdata.csv'); 227 ob_start(); 228 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 229 ob_end_clean(); 230 231 // No userdata is present in the file: Fallback is to assign the uploading user as author. 232 $expecteduserids = array(); 233 $expecteduserids[1] = $teacher->id; 234 $expecteduserids[2] = $teacher->id; 235 236 $expectedcontent = array(); 237 $expectedcontent[1] = array( 238 'Username' => 'student', 239 'Param2' => 'My first entry', 240 ); 241 $expectedcontent[2] = array( 242 'Username' => 'student2', 243 'Param2' => 'My second entry', 244 ); 245 246 $records = $this->get_data_records($data->id); 247 $this->assertCount(2, $records); 248 foreach ($records as $record) { 249 $identifier = $record->items['ID']->content; 250 $this->assertEquals($expecteduserids[$identifier], $record->userid); 251 252 foreach ($expectedcontent[$identifier] as $field => $value) { 253 $this->assertEquals($value, $record->items[$field]->content, 254 "The value of field \"$field\" for the record at position \"$identifier\" ". 255 "which is \"{$record->items[$field]->content}\" does not match the expected value \"$value\"."); 256 } 257 } 258 } 259 260 /** 261 * Returns the records of the data instance. 262 * 263 * Each records has an item entry, which contains all fields associated with this item. 264 * Each fields has the parameters name, type and content. 265 * @param int $dataid Id of the data instance. 266 * @return array The records of the data instance. 267 * @throws dml_exception 268 */ 269 private function get_data_records(int $dataid): array { 270 global $DB; 271 272 $records = $DB->get_records('data_records', ['dataid' => $dataid]); 273 foreach ($records as $record) { 274 $sql = 'SELECT f.name, f.type, con.content FROM 275 {data_content} con JOIN {data_fields} f ON con.fieldid = f.id 276 WHERE con.recordid = :recordid'; 277 $items = $DB->get_records_sql($sql, array('recordid' => $record->id)); 278 $record->items = $items; 279 } 280 return $records; 281 } 282 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body