See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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 /** 18 * This file contains tests for the repository_nextcloud class. 19 * 20 * @package repository_nextcloud 21 * @copyright 2017 Project seminar (Learnweb, University of Münster) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once($CFG->dirroot . '/repository/lib.php'); 29 require_once($CFG->libdir . '/webdavlib.php'); 30 31 /** 32 * Class repository_nextcloud_lib_testcase 33 * @group repository_nextcloud 34 * @copyright 2017 Project seminar (Learnweb, University of Münster) 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class repository_nextcloud_lib_testcase extends advanced_testcase { 38 39 /** @var null|\repository_nextcloud the repository_nextcloud object, which the tests are run on. */ 40 private $repo = null; 41 42 /** @var null|\core\oauth2\issuer which belongs to the repository_nextcloud object.*/ 43 private $issuer = null; 44 45 /** 46 * SetUp to create an repository instance. 47 */ 48 protected function setUp() { 49 $this->resetAfterTest(true); 50 51 // Admin is neccessary to create api and issuer objects. 52 $this->setAdminUser(); 53 54 /** @var repository_nextcloud_generator $generator */ 55 $generator = $this->getDataGenerator()->get_plugin_generator('repository_nextcloud'); 56 $this->issuer = $generator->test_create_issuer(); 57 58 // Create Endpoints for issuer. 59 $generator->test_create_endpoints($this->issuer->get('id')); 60 61 // Params for the config form. 62 $reptype = $generator->create_type([ 63 'visible' => 1, 64 'enableuserinstances' => 0, 65 'enablecourseinstances' => 0, 66 ]); 67 68 $instance = $generator->create_instance([ 69 'issuerid' => $this->issuer->get('id'), 70 'pluginname' => 'Nextcloud', 71 'controlledlinkfoldername' => 'Moodlefiles', 72 'supportedreturntypes' => 'both', 73 'defaultreturntype' => FILE_INTERNAL, 74 ]); 75 76 // At last, create a repository_nextcloud object from the instance id. 77 $this->repo = new repository_nextcloud($instance->id); 78 $this->repo->options['typeid'] = $reptype->id; 79 $this->repo->options['sortorder'] = 1; 80 $this->resetAfterTest(true); 81 } 82 83 /** 84 * Checks the is_visible method in case the repository is set to hidden in the database. 85 */ 86 public function test_is_visible_parent_false() { 87 global $DB; 88 $id = $this->repo->options['typeid']; 89 90 // Check, if the method returns false, when the repository is set to visible in the database 91 // and the client configuration data is complete. 92 $DB->update_record('repository', (object) array('id' => $id, 'visible' => 0)); 93 94 $this->assertFalse($this->repo->is_visible()); 95 } 96 97 /** 98 * Test whether the repo is disabled. 99 */ 100 public function test_repo_creation() { 101 $issuerid = $this->repo->get_option('issuerid'); 102 103 // Config saves the right id. 104 $this->assertEquals($this->issuer->get('id'), $issuerid); 105 106 // Function that is used in construct method returns the right id. 107 $constructissuer = \core\oauth2\api::get_issuer($issuerid); 108 $this->assertEquals($this->issuer->get('id'), $constructissuer->get('id')); 109 110 $this->assertEquals(true, $constructissuer->get('enabled')); 111 $this->assertFalse($this->repo->disabled); 112 } 113 114 /** 115 * Returns an array of endpoints or null. 116 * @param string $endpointname 117 * @return array|null 118 */ 119 private function get_endpoint_id($endpointname) { 120 $endpoints = \core\oauth2\api::get_endpoints($this->issuer); 121 $id = array(); 122 foreach ($endpoints as $endpoint) { 123 $name = $endpoint->get('name'); 124 if ($name === $endpointname) { 125 $id[$endpoint->get('id')] = $endpoint->get('id'); 126 } 127 } 128 if (empty($id)) { 129 return null; 130 } 131 return $id; 132 } 133 /** 134 * Test if repository is disabled when webdav_endpoint is deleted. 135 */ 136 public function test_issuer_webdav() { 137 $idwebdav = $this->get_endpoint_id('webdav_endpoint'); 138 if (!empty($idwebdav)) { 139 foreach ($idwebdav as $id) { 140 \core\oauth2\api::delete_endpoint($id); 141 } 142 } 143 $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); 144 } 145 /** 146 * Test if repository is disabled when ocs_endpoint is deleted. 147 */ 148 public function test_issuer_ocs() { 149 $idocs = $this->get_endpoint_id('ocs_endpoint'); 150 if (!empty($idocs)) { 151 foreach ($idocs as $id) { 152 \core\oauth2\api::delete_endpoint($id); 153 } 154 } 155 $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); 156 } 157 158 /** 159 * Test if repository is disabled when userinfo_endpoint is deleted. 160 */ 161 public function test_issuer_userinfo() { 162 $idtoken = $this->get_endpoint_id('userinfo_endpoint'); 163 if (!empty($idtoken)) { 164 foreach ($idtoken as $id) { 165 \core\oauth2\api::delete_endpoint($id); 166 } 167 } 168 $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); 169 } 170 171 /** 172 * Test if repository is disabled when token_endpoint is deleted. 173 */ 174 public function test_issuer_token() { 175 $idtoken = $this->get_endpoint_id('token_endpoint'); 176 if (!empty($idtoken)) { 177 foreach ($idtoken as $id) { 178 \core\oauth2\api::delete_endpoint($id); 179 } 180 } 181 $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); 182 } 183 184 /** 185 * Test if repository is disabled when auth_endpoint is deleted. 186 */ 187 public function test_issuer_authorization() { 188 $idauth = $this->get_endpoint_id('authorization_endpoint'); 189 if (!empty($idauth)) { 190 foreach ($idauth as $id) { 191 \core\oauth2\api::delete_endpoint($id); 192 } 193 } 194 $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); 195 } 196 /** 197 * Test if repository throws an error when endpoint does not exist. 198 */ 199 public function test_parse_endpoint_url_error() { 200 $this->expectException(\repository_nextcloud\configuration_exception::class); 201 \repository_nextcloud\issuer_management::parse_endpoint_url('notexisting', $this->issuer); 202 } 203 /** 204 * Test get_listing method with an example directory. Tests error cases. 205 */ 206 public function test_get_listing_error() { 207 $ret = $this->get_initialised_return_array(); 208 $this->setUser(); 209 // WebDAV socket is not opened. 210 $mock = $this->createMock(\webdav_client::class); 211 $mock->expects($this->once())->method('open')->will($this->returnValue(false)); 212 $private = $this->set_private_property($mock, 'dav'); 213 214 $this->assertEquals($ret, $this->repo->get_listing('/')); 215 216 // Response is not an array. 217 $mock = $this->createMock(\webdav_client::class); 218 $mock->expects($this->once())->method('open')->will($this->returnValue(true)); 219 $mock->expects($this->once())->method('ls')->will($this->returnValue('notanarray')); 220 $private->setValue($this->repo, $mock); 221 222 $this->assertEquals($ret, $this->repo->get_listing('/')); 223 } 224 /** 225 * Test get_listing method with an example directory. Tests the root directory. 226 */ 227 public function test_get_listing_root() { 228 $this->setUser(); 229 $ret = $this->get_initialised_return_array(); 230 231 // This is the expected response from the ls method. 232 $response = array( 233 array( 234 'href' => 'remote.php/webdav/', 235 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 236 'resourcetype' => 'collection', 237 'status' => 'HTTP/1.1 200 OK', 238 'getcontentlength' => '' 239 ), 240 array( 241 'href' => 'remote.php/webdav/Documents/', 242 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 243 'resourcetype' => 'collection', 244 'status' => 'HTTP/1.1 200 OK', 245 'getcontentlength' => '' 246 ), 247 array( 248 'href' => 'remote.php/webdav/welcome.txt', 249 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 250 'status' => 'HTTP/1.1 200 OK', 251 'getcontentlength' => '163' 252 ) 253 ); 254 255 // The expected result from the get_listing method in the repository_nextcloud class. 256 $ret['list'] = array( 257 'DOCUMENTS/' => array( 258 'title' => 'Documents', 259 'thumbnail' => null, 260 'children' => array(), 261 'datemodified' => 1481213186, 262 'path' => '/Documents/' 263 ), 264 'WELCOME.TXT' => array( 265 'title' => 'welcome.txt', 266 'thumbnail' => null, 267 'size' => '163', 268 'datemodified' => 1481213186, 269 'source' => '/welcome.txt' 270 ) 271 ); 272 273 // Valid response from the client. 274 $mock = $this->createMock(\webdav_client::class); 275 $mock->expects($this->once())->method('open')->will($this->returnValue(true)); 276 $mock->expects($this->once())->method('ls')->will($this->returnValue($response)); 277 $this->set_private_property($mock, 'dav'); 278 279 $ls = $this->repo->get_listing('/'); 280 281 // Those attributes can not be tested properly. 282 $ls['list']['DOCUMENTS/']['thumbnail'] = null; 283 $ls['list']['WELCOME.TXT']['thumbnail'] = null; 284 285 $this->assertEquals($ret, $ls); 286 } 287 /** 288 * Test get_listing method with an example directory. Tests a different directory than the root 289 * directory. 290 */ 291 public function test_get_listing_directory() { 292 $ret = $this->get_initialised_return_array(); 293 $this->setUser(); 294 295 // An additional directory path has to be added to the 'path' field within the returned array. 296 $ret['path'][1] = array( 297 'name' => 'dir', 298 'path' => '/dir/' 299 ); 300 301 // This is the expected response from the get_listing method in the Nextcloud client. 302 $response = array( 303 array( 304 'href' => 'remote.php/webdav/dir/', 305 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 306 'resourcetype' => 'collection', 307 'status' => 'HTTP/1.1 200 OK', 308 'getcontentlength' => '' 309 ), 310 array( 311 'href' => 'remote.php/webdav/dir/Documents/', 312 'lastmodified' => null, 313 'resourcetype' => 'collection', 314 'status' => 'HTTP/1.1 200 OK', 315 'getcontentlength' => '' 316 ), 317 array( 318 'href' => 'remote.php/webdav/dir/welcome.txt', 319 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 320 'status' => 'HTTP/1.1 200 OK', 321 'getcontentlength' => '163' 322 ) 323 ); 324 325 // The expected result from the get_listing method in the repository_nextcloud class. 326 $ret['list'] = array( 327 'DOCUMENTS/' => array( 328 'title' => 'Documents', 329 'thumbnail' => null, 330 'children' => array(), 331 'datemodified' => null, 332 'path' => '/dir/Documents/' 333 ), 334 'WELCOME.TXT' => array( 335 'title' => 'welcome.txt', 336 'thumbnail' => null, 337 'size' => '163', 338 'datemodified' => 1481213186, 339 'source' => '/dir/welcome.txt' 340 ) 341 ); 342 343 // Valid response from the client. 344 $mock = $this->createMock(\webdav_client::class); 345 $mock->expects($this->once())->method('open')->will($this->returnValue(true)); 346 $mock->expects($this->once())->method('ls')->will($this->returnValue($response)); 347 $this->set_private_property($mock, 'dav'); 348 349 $ls = $this->repo->get_listing('/dir/'); 350 351 // Can not be tested properly. 352 $ls['list']['DOCUMENTS/']['thumbnail'] = null; 353 $ls['list']['WELCOME.TXT']['thumbnail'] = null; 354 355 $this->assertEquals($ret, $ls); 356 } 357 /** 358 * Test the get_link method. 359 */ 360 public function test_get_link_success() { 361 $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( 362 )->getMock(); 363 $file = '/datei'; 364 $expectedresponse = <<<XML 365 <?xml version="1.0"?> 366 <ocs> 367 <meta> 368 <status>ok</status> 369 <statuscode>100</statuscode> 370 <message/> 371 </meta> 372 <data> 373 <id>2</id> 374 <share_type>3</share_type> 375 <uid_owner>admin</uid_owner> 376 <displayname_owner>admin</displayname_owner> 377 <permissions>1</permissions> 378 <stime>1502883721</stime> 379 <parent/> 380 <expiration/> 381 <token>QXbqrJj8DcMaXen</token> 382 <uid_file_owner>admin</uid_file_owner> 383 <displayname_file_owner>admin</displayname_file_owner> 384 <path>/somefile</path> 385 <item_type>file</item_type> 386 <mimetype>application/pdf</mimetype> 387 <storage_id>home::admin</storage_id> 388 <storage>1</storage> 389 <item_source>6</item_source> 390 <file_source>6</file_source> 391 <file_parent>4</file_parent> 392 <file_target>/somefile</file_target> 393 <share_with/> 394 <share_with_displayname/> 395 <name/> 396 <url>https://www.default.test/somefile</url> 397 <mail_send>0</mail_send> 398 </data> 399 </ocs> 400 XML; 401 // Expected Parameters. 402 $ocsquery = [ 403 'path' => $file, 404 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 405 'publicUpload' => false, 406 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ 407 ]; 408 409 // With test whether mock is called with right parameters. 410 $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); 411 $this->set_private_property($mock, 'ocsclient'); 412 413 // Method does extract the link from the xml format. 414 $this->assertEquals('https://www.default.test/somefile/download', $this->repo->get_link($file)); 415 } 416 417 /** 418 * get_link can get OCS failure responses. Test that this is handled appropriately. 419 */ 420 public function test_get_link_failure() { 421 $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( 422 )->getMock(); 423 $file = '/datei'; 424 $expectedresponse = <<<XML 425 <?xml version="1.0"?> 426 <ocs> 427 <meta> 428 <status>failure</status> 429 <statuscode>404</statuscode> 430 <message>Msg</message> 431 </meta> 432 <data/> 433 </ocs> 434 XML; 435 // Expected Parameters. 436 $ocsquery = [ 437 'path' => $file, 438 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 439 'publicUpload' => false, 440 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ 441 ]; 442 443 // With test whether mock is called with right parameters. 444 $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); 445 $this->set_private_property($mock, 'ocsclient'); 446 447 // Suppress (expected) XML parse error... Nextcloud sometimes returns JSON on extremely bad errors. 448 libxml_use_internal_errors(true); 449 450 // Method get_link correctly raises an exception that contains error code and message. 451 $this->expectException(\repository_nextcloud\request_exception::class); 452 $params = array('instance' => $this->repo->get_name(), 'errormessage' => sprintf('(%s) %s', '404', 'Msg')); 453 $this->expectExceptionMessage(get_string('request_exception', 'repository_nextcloud', $params)); 454 $this->repo->get_link($file); 455 } 456 457 /** 458 * get_link can get OCS responses that are not actually XML. Test that this is handled appropriately. 459 */ 460 public function test_get_link_problem() { 461 $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( 462 )->getMock(); 463 $file = '/datei'; 464 $expectedresponse = <<<JSON 465 {"message":"CSRF check failed"} 466 JSON; 467 // Expected Parameters. 468 $ocsquery = [ 469 'path' => $file, 470 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 471 'publicUpload' => false, 472 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ 473 ]; 474 475 // With test whether mock is called with right parameters. 476 $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); 477 $this->set_private_property($mock, 'ocsclient'); 478 479 // Suppress (expected) XML parse error... Nextcloud sometimes returns JSON on extremely bad errors. 480 libxml_use_internal_errors(true); 481 482 // Method get_link correctly raises an exception. 483 $this->expectException(\repository_nextcloud\request_exception::class); 484 $this->repo->get_link($file); 485 } 486 487 /** 488 * Test get_file reference, merely returns the input if no optional_param is set. 489 */ 490 public function test_get_file_reference_withoutoptionalparam() { 491 $this->assertEquals('/somefile', $this->repo->get_file_reference('/somefile')); 492 } 493 494 /** 495 * Test logout. 496 */ 497 public function test_logout() { 498 $mock = $this->createMock(\core\oauth2\client::class); 499 500 $mock->expects($this->exactly(2))->method('log_out'); 501 $this->set_private_property($mock, 'client'); 502 $this->repo->options['ajax'] = false; 503 $this->expectOutputString('<a target="_blank" rel="noopener noreferrer">Log in to your account</a>' . 504 '<a target="_blank" rel="noopener noreferrer">Log in to your account</a>'); 505 506 $this->assertEquals($this->repo->print_login(), $this->repo->logout()); 507 508 $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new moodle_url('url'))); 509 510 $this->repo->options['ajax'] = true; 511 $this->assertEquals($this->repo->print_login(), $this->repo->logout()); 512 513 } 514 /** 515 * Test for the get_file method from the repository_nextcloud class. 516 */ 517 public function test_get_file() { 518 // WebDAV socket is not open. 519 $mock = $this->createMock(\webdav_client::class); 520 $mock->expects($this->once())->method('open')->will($this->returnValue(false)); 521 $private = $this->set_private_property($mock, 'dav'); 522 523 $this->assertFalse($this->repo->get_file('path')); 524 525 // WebDAV socket is open and the request successful. 526 $mock = $this->createMock(\webdav_client::class); 527 $mock->expects($this->once())->method('open')->will($this->returnValue(true)); 528 $mock->expects($this->once())->method('get_file')->will($this->returnValue(true)); 529 $private->setValue($this->repo, $mock); 530 531 $result = $this->repo->get_file('path', 'file'); 532 533 $this->assertNotNull($result['path']); 534 } 535 536 /** 537 * Test callback. 538 */ 539 public function test_callback() { 540 $mock = $this->createMock(\core\oauth2\client::class); 541 // Should call check_login exactly once. 542 $mock->expects($this->once())->method('log_out'); 543 $mock->expects($this->once())->method('is_logged_in'); 544 545 $this->set_private_property($mock, 'client'); 546 547 $this->repo->callback(); 548 } 549 /** 550 * Test check_login. 551 */ 552 public function test_check_login() { 553 $mock = $this->createMock(\core\oauth2\client::class); 554 $mock->expects($this->once())->method('is_logged_in')->will($this->returnValue(true)); 555 $this->set_private_property($mock, 'client'); 556 557 $this->assertTrue($this->repo->check_login()); 558 } 559 /** 560 * Test print_login. 561 */ 562 public function test_print_login() { 563 $mock = $this->createMock(\core\oauth2\client::class); 564 $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new moodle_url('url'))); 565 $this->set_private_property($mock, 'client'); 566 567 // Test with ajax activated. 568 $this->repo->options['ajax'] = true; 569 570 $url = new moodle_url('url'); 571 $ret = array(); 572 $btn = new \stdClass(); 573 $btn->type = 'popup'; 574 $btn->url = $url->out(false); 575 $ret['login'] = array($btn); 576 577 $this->assertEquals($ret, $this->repo->print_login()); 578 579 // Test without ajax. 580 $this->repo->options['ajax'] = false; 581 582 $output = html_writer::link($url, get_string('login', 'repository'), 583 array('target' => '_blank', 'rel' => 'noopener noreferrer')); 584 $this->expectOutputString($output); 585 $this->repo->print_login(); 586 } 587 588 /** 589 * Test the initiate_webdavclient function. 590 */ 591 public function test_initiate_webdavclient() { 592 global $CFG; 593 594 $idwebdav = $this->get_endpoint_id('webdav_endpoint'); 595 if (!empty($idwebdav)) { 596 foreach ($idwebdav as $id) { 597 \core\oauth2\api::delete_endpoint($id); 598 } 599 } 600 601 $generator = $this->getDataGenerator()->get_plugin_generator('repository_nextcloud'); 602 $generator->test_create_single_endpoint($this->issuer->get('id'), "webdav_endpoint", 603 "https://www.default.test:8080/webdav/index.php"); 604 605 $fakeaccesstoken = new stdClass(); 606 $fakeaccesstoken->token = "fake access token"; 607 $oauthmock = $this->createMock(\core\oauth2\client::class); 608 $oauthmock->expects($this->once())->method('get_accesstoken')->will($this->returnValue($fakeaccesstoken)); 609 $this->set_private_property($oauthmock, 'client'); 610 611 $dav = phpunit_util::call_internal_method($this->repo, "initiate_webdavclient", [], 'repository_nextcloud'); 612 613 // Verify that port is set correctly (private property). 614 $refclient = new ReflectionClass($dav); 615 616 $property = $refclient->getProperty('_port'); 617 $property->setAccessible(true); 618 619 $port = $property->getValue($dav); 620 621 $this->assertEquals('8080', $port); 622 } 623 624 /** 625 * Test supported_returntypes. 626 * FILE_INTERNAL when no system account is connected. 627 * FILE_INTERNAL | FILE_CONTROLLED_LINK when a system account is connected. 628 */ 629 public function test_supported_returntypes() { 630 global $DB; 631 $this->assertEquals(FILE_INTERNAL, $this->repo->supported_returntypes()); 632 $dataobject = new stdClass(); 633 $dataobject->timecreated = time(); 634 $dataobject->timemodified = time(); 635 $dataobject->usermodified = 2; 636 $dataobject->issuerid = $this->issuer->get('id'); 637 $dataobject->refreshtoken = 'sometokenthatwillnotbeused'; 638 $dataobject->grantedscopes = 'openid profile email'; 639 $dataobject->email = 'some.email@some.de'; 640 $dataobject->username = 'someusername'; 641 642 $DB->insert_record('oauth2_system_account', $dataobject); 643 // When a system account is registered the file_type FILE_CONTROLLED_LINK is supported. 644 $this->assertEquals(FILE_INTERNAL | FILE_CONTROLLED_LINK, 645 $this->repo->supported_returntypes()); 646 } 647 648 /** 649 * The reference_file_selected() methode is called every time a FILE_CONTROLLED_LINK is chosen for upload. 650 * Since the function is very long the private function are tested separately, and merely the abortion of the 651 * function are tested. 652 * 653 */ 654 public function test_reference_file_selected_error() { 655 $this->repo->disabled = true; 656 $this->expectException(\repository_exception::class); 657 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 658 659 $this->repo->disabled = false; 660 $this->expectException(\repository_exception::class); 661 $this->expectExceptionMessage('Cannot connect as system user'); 662 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 663 664 $mock = $this->createMock(\core\oauth2\client::class); 665 $mock->expects($this->once())->method('get_system_oauth_client')->with($this->issuer)->willReturn(true); 666 667 $this->expectException(\repository_exception::class); 668 $this->expectExceptionMessage('Cannot connect as current user'); 669 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 670 671 $this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); 672 $this->expectException(\repository_exception::class); 673 $this->expectExceptionMessage('cannotdownload'); 674 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 675 676 $this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); 677 $this->expectException(\repository_exception::class); 678 $this->expectExceptionMessage('cannotdownload'); 679 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 680 681 $this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); 682 $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => 683 array('success' => 400))); 684 $this->expectException(\repository_exception::class); 685 $this->expectExceptionMessage('Could not copy file'); 686 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 687 688 $this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); 689 $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => 690 array('success' => 201))); 691 $this->repo->expects($this->once())->method('delete_share_dataowner_sysaccount')->willReturn( 692 array('statuscode' => array('success' => 400))); 693 $this->expectException(\repository_exception::class); 694 $this->expectExceptionMessage('Share is still present'); 695 $this->repo->reference_file_selected('', context_system::instance(), '', '', ''); 696 697 $this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); 698 $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => 699 array('success' => 201))); 700 $this->repo->expects($this->once())->method('delete_share_dataowner_sysaccount')->willReturn( 701 array('statuscode' => array('success' => 100))); 702 $filereturn = array(); 703 $filereturn->link = 'some/fullpath' . 'some/target/path'; 704 $filereturn->name = 'mysource'; 705 $filereturn->usesystem = true; 706 $filereturn = json_encode($filereturn); 707 $return = $this->repo->reference_file_selected('mysource', context_system::instance(), '', '', ''); 708 $this->assertEquals($filereturn, $return); 709 } 710 711 /** 712 * Test the send_file function for access controlled links. 713 */ 714 public function test_send_file_errors() { 715 $fs = get_file_storage(); 716 $storedfile = $fs->create_file_from_reference([ 717 'contextid' => context_system::instance()->id, 718 'component' => 'core', 719 'filearea' => 'unittest', 720 'itemid' => 0, 721 'filepath' => '/', 722 'filename' => 'testfile.txt', 723 ], $this->repo->id, json_encode([ 724 'type' => 'FILE_CONTROLLED_LINK', 725 'link' => 'https://test.local/fakelink/', 726 'usesystem' => true, 727 ])); 728 $this->set_private_property('', 'client'); 729 $this->expectException(repository_nextcloud\request_exception::class); 730 $this->expectExceptionMessage(get_string('contactadminwith', 'repository_nextcloud', 731 'The OAuth clients could not be connected.')); 732 733 $this->repo->send_file($storedfile, '', '', ''); 734 735 // Testing whether the mock up appears is topic to behat. 736 $mock = $this->createMock(\core\oauth2\client::class); 737 $mock->expects($this->once())->method('is_logged_in')->willReturn(true); 738 $this->repo->send_file($storedfile, '', '', ''); 739 740 // Checks that setting for foldername are used. 741 $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(false); 742 // In case of false as return value mkcol is called to create the folder. 743 $parsedwebdavurl = parse_url($this->issuer->get_endpoint_url('webdav')); 744 $webdavprefix = $parsedwebdavurl['path']; 745 $mock->expects($this->once())->method('mkcol')->with( 746 $webdavprefix . 'Moodlefiles')->willReturn(400); 747 $this->expectException(\repository_nextcloud\request_exception::class); 748 $this->expectExceptionMessage(get_string('requestnotexecuted', 'repository_nextcloud')); 749 $this->repo->send_file($storedfile, '', '', ''); 750 751 $expectedresponse = <<<XML 752 <?xml version="1.0"?> 753 <ocs> 754 <meta> 755 <status>ok</status> 756 <statuscode>100</statuscode> 757 <message/> 758 </meta> 759 <data> 760 <element> 761 <id>6</id> 762 <share_type>0</share_type> 763 <uid_owner>tech</uid_owner> 764 <displayname_owner>tech</displayname_owner> 765 <permissions>19</permissions> 766 <stime>1511877999</stime> 767 <parent/> 768 <expiration/> 769 <token/> 770 <uid_file_owner>tech</uid_file_owner> 771 <displayname_file_owner>tech</displayname_file_owner> 772 <path>/System/Category Miscellaneous/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path> 773 <item_type>file</item_type> 774 <mimetype>text/plain</mimetype> 775 <storage_id>home::tech</storage_id> 776 <storage>4</storage> 777 <item_source>824</item_source> 778 <file_source>824</file_source> 779 <file_parent>823</file_parent> 780 <file_target>/merge (3).txt</file_target> 781 <share_with>user2</share_with> 782 <share_with_displayname>user1</share_with_displayname> 783 <mail_send>0</mail_send> 784 </element> 785 <element> 786 <id>5</id> 787 <share_type>0</share_type> 788 <uid_owner>tech</uid_owner> 789 <displayname_owner>tech</displayname_owner> 790 <permissions>19</permissions> 791 <stime>1511877999</stime> 792 <parent/> 793 <expiration/> 794 <token/> 795 <uid_file_owner>tech</uid_file_owner> 796 <displayname_file_owner>tech</displayname_file_owner> 797 <path>/System/Category Miscellaneous/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path> 798 <item_type>file</item_type> 799 <mimetype>text/plain</mimetype> 800 <storage_id>home::tech</storage_id> 801 <storage>4</storage> 802 <item_source>824</item_source> 803 <file_source>824</file_source> 804 <file_parent>823</file_parent> 805 <file_target>/merged (3).txt</file_target> 806 <share_with>user1</share_with> 807 <share_with_displayname>user1</share_with_displayname> 808 <mail_send>0</mail_send> 809 </element> 810 </data> 811 </ocs> 812 XML; 813 814 // Checks that setting for foldername are used. 815 $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(true); 816 // In case of true as return value mkcol is not called to create the folder. 817 $shareid = 5; 818 819 $mockocsclient = $this->getMockBuilder( 820 \repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone()->getMock(); 821 $mockocsclient->expects($this->exactly(2))->method('call')->with('get_information_of_share', 822 array('share_id' => $shareid))->will($this->returnValue($expectedresponse)); 823 $this->set_private_property($mock, 'ocsclient'); 824 $this->repo->expects($this->once())->method('move_file_to_folder')->with('/merged (3).txt', 'Moodlefiles', 825 $mock)->willReturn(array('success' => 201)); 826 827 $this->repo->send_file('', '', '', ''); 828 829 // Create test for statuscode 403. 830 831 // Checks that setting for foldername are used. 832 $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(true); 833 // In case of true as return value mkcol is not called to create the folder. 834 $shareid = 5; 835 $mockocsclient = $this->getMockBuilder(\repository_nextcloud\ocs_client::class 836 )->disableOriginalConstructor()->disableOriginalClone()->getMock(); 837 $mockocsclient->expects($this->exactly(1))->method('call')->with('get_shares', 838 array('path' => '/merged (3).txt', 'reshares' => true))->will($this->returnValue($expectedresponse)); 839 $mockocsclient->expects($this->exactly(1))->method('call')->with('get_information_of_share', 840 array('share_id' => $shareid))->will($this->returnValue($expectedresponse)); 841 $this->set_private_property($mock, 'ocsclient'); 842 $this->repo->expects($this->once())->method('move_file_to_folder')->with('/merged (3).txt', 'Moodlefiles', 843 $mock)->willReturn(array('success' => 201)); 844 $this->repo->send_file('', '', '', ''); 845 } 846 847 /** 848 * Helper method, which inserts a given mock value into the repository_nextcloud object. 849 * 850 * @param mixed $value mock value that will be inserted. 851 * @param string $propertyname name of the private property. 852 * @return ReflectionProperty the resulting reflection property. 853 */ 854 protected function set_private_property($value, $propertyname) { 855 $refclient = new ReflectionClass($this->repo); 856 $private = $refclient->getProperty($propertyname); 857 $private->setAccessible(true); 858 $private->setValue($this->repo, $value); 859 860 return $private; 861 } 862 /** 863 * Helper method to set required return parameters for get_listing. 864 * 865 * @return array array, which contains the parameters. 866 */ 867 protected function get_initialised_return_array() { 868 $ret = array(); 869 $ret['dynload'] = true; 870 $ret['nosearch'] = true; 871 $ret['nologin'] = false; 872 $ret['path'] = [ 873 [ 874 'name' => $this->repo->get_meta()->name, 875 'path' => '', 876 ] 877 ]; 878 $ret['manage'] = ''; 879 $ret['defaultreturntype'] = FILE_INTERNAL; 880 $ret['list'] = array(); 881 882 return $ret; 883 } 884 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body