Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * This file contains tests for the repository_nextcloud class.
 *
 * @package     repository_nextcloud
 * @copyright  2017 Project seminar (Learnweb, University of Münster)
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
> namespace repository_nextcloud; > defined('MOODLE_INTERNAL') || die(); > use repository; > use repository_nextcloud;
global $CFG; require_once($CFG->dirroot . '/repository/lib.php'); require_once($CFG->libdir . '/webdavlib.php'); /** * Class repository_nextcloud_lib_testcase * @group repository_nextcloud * @copyright 2017 Project seminar (Learnweb, University of Münster) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */
< class repository_nextcloud_lib_testcase extends advanced_testcase {
> class lib_test extends \advanced_testcase {
/** @var null|\repository_nextcloud the repository_nextcloud object, which the tests are run on. */ private $repo = null; /** @var null|\core\oauth2\issuer which belongs to the repository_nextcloud object.*/ private $issuer = null; /** * SetUp to create an repository instance. */
< protected function setUp() {
> protected function setUp(): void {
$this->resetAfterTest(true); // Admin is neccessary to create api and issuer objects. $this->setAdminUser(); /** @var repository_nextcloud_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('repository_nextcloud'); $this->issuer = $generator->test_create_issuer(); // Create Endpoints for issuer. $generator->test_create_endpoints($this->issuer->get('id')); // Params for the config form. $reptype = $generator->create_type([ 'visible' => 1, 'enableuserinstances' => 0, 'enablecourseinstances' => 0, ]); $instance = $generator->create_instance([ 'issuerid' => $this->issuer->get('id'), 'pluginname' => 'Nextcloud', 'controlledlinkfoldername' => 'Moodlefiles', 'supportedreturntypes' => 'both', 'defaultreturntype' => FILE_INTERNAL, ]); // At last, create a repository_nextcloud object from the instance id. $this->repo = new repository_nextcloud($instance->id); $this->repo->options['typeid'] = $reptype->id; $this->repo->options['sortorder'] = 1; $this->resetAfterTest(true); } /** * Checks the is_visible method in case the repository is set to hidden in the database. */ public function test_is_visible_parent_false() { global $DB; $id = $this->repo->options['typeid']; // Check, if the method returns false, when the repository is set to visible in the database // and the client configuration data is complete. $DB->update_record('repository', (object) array('id' => $id, 'visible' => 0)); $this->assertFalse($this->repo->is_visible()); } /** * Test whether the repo is disabled. */ public function test_repo_creation() { $issuerid = $this->repo->get_option('issuerid'); // Config saves the right id. $this->assertEquals($this->issuer->get('id'), $issuerid); // Function that is used in construct method returns the right id. $constructissuer = \core\oauth2\api::get_issuer($issuerid); $this->assertEquals($this->issuer->get('id'), $constructissuer->get('id')); $this->assertEquals(true, $constructissuer->get('enabled')); $this->assertFalse($this->repo->disabled); } /** * Returns an array of endpoints or null. * @param string $endpointname * @return array|null */ private function get_endpoint_id($endpointname) { $endpoints = \core\oauth2\api::get_endpoints($this->issuer); $id = array(); foreach ($endpoints as $endpoint) { $name = $endpoint->get('name'); if ($name === $endpointname) { $id[$endpoint->get('id')] = $endpoint->get('id'); } } if (empty($id)) { return null; } return $id; } /** * Test if repository is disabled when webdav_endpoint is deleted. */ public function test_issuer_webdav() { $idwebdav = $this->get_endpoint_id('webdav_endpoint'); if (!empty($idwebdav)) { foreach ($idwebdav as $id) { \core\oauth2\api::delete_endpoint($id); } } $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); } /** * Test if repository is disabled when ocs_endpoint is deleted. */ public function test_issuer_ocs() { $idocs = $this->get_endpoint_id('ocs_endpoint'); if (!empty($idocs)) { foreach ($idocs as $id) { \core\oauth2\api::delete_endpoint($id); } } $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); } /** * Test if repository is disabled when userinfo_endpoint is deleted. */ public function test_issuer_userinfo() { $idtoken = $this->get_endpoint_id('userinfo_endpoint'); if (!empty($idtoken)) { foreach ($idtoken as $id) { \core\oauth2\api::delete_endpoint($id); } } $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); } /** * Test if repository is disabled when token_endpoint is deleted. */ public function test_issuer_token() { $idtoken = $this->get_endpoint_id('token_endpoint'); if (!empty($idtoken)) { foreach ($idtoken as $id) { \core\oauth2\api::delete_endpoint($id); } } $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); } /** * Test if repository is disabled when auth_endpoint is deleted. */ public function test_issuer_authorization() { $idauth = $this->get_endpoint_id('authorization_endpoint'); if (!empty($idauth)) { foreach ($idauth as $id) { \core\oauth2\api::delete_endpoint($id); } } $this->assertFalse(\repository_nextcloud\issuer_management::is_valid_issuer($this->issuer)); } /** * Test if repository throws an error when endpoint does not exist. */ public function test_parse_endpoint_url_error() { $this->expectException(\repository_nextcloud\configuration_exception::class); \repository_nextcloud\issuer_management::parse_endpoint_url('notexisting', $this->issuer); } /** * Test get_listing method with an example directory. Tests error cases. */ public function test_get_listing_error() { $ret = $this->get_initialised_return_array(); $this->setUser(); // WebDAV socket is not opened. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(false)); $private = $this->set_private_property($mock, 'dav'); $this->assertEquals($ret, $this->repo->get_listing('/')); // Response is not an array. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(true)); $mock->expects($this->once())->method('ls')->will($this->returnValue('notanarray')); $private->setValue($this->repo, $mock); $this->assertEquals($ret, $this->repo->get_listing('/')); } /** * Test get_listing method with an example directory. Tests the root directory. */ public function test_get_listing_root() { $this->setUser(); $ret = $this->get_initialised_return_array(); // This is the expected response from the ls method. $response = array( array( 'href' => 'remote.php/webdav/', 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 'resourcetype' => 'collection', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '' ), array( 'href' => 'remote.php/webdav/Documents/', 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 'resourcetype' => 'collection', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '' ), array( 'href' => 'remote.php/webdav/welcome.txt', 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '163' ) ); // The expected result from the get_listing method in the repository_nextcloud class. $ret['list'] = array( 'DOCUMENTS/' => array( 'title' => 'Documents', 'thumbnail' => null, 'children' => array(), 'datemodified' => 1481213186, 'path' => '/Documents/' ), 'WELCOME.TXT' => array( 'title' => 'welcome.txt', 'thumbnail' => null, 'size' => '163', 'datemodified' => 1481213186, 'source' => '/welcome.txt' ) ); // Valid response from the client. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(true)); $mock->expects($this->once())->method('ls')->will($this->returnValue($response)); $this->set_private_property($mock, 'dav'); $ls = $this->repo->get_listing('/'); // Those attributes can not be tested properly. $ls['list']['DOCUMENTS/']['thumbnail'] = null; $ls['list']['WELCOME.TXT']['thumbnail'] = null; $this->assertEquals($ret, $ls); } /** * Test get_listing method with an example directory. Tests a different directory than the root * directory. */ public function test_get_listing_directory() { $ret = $this->get_initialised_return_array(); $this->setUser(); // An additional directory path has to be added to the 'path' field within the returned array. $ret['path'][1] = array( 'name' => 'dir', 'path' => '/dir/' ); // This is the expected response from the get_listing method in the Nextcloud client. $response = array( array( 'href' => 'remote.php/webdav/dir/', 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 'resourcetype' => 'collection', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '' ), array( 'href' => 'remote.php/webdav/dir/Documents/', 'lastmodified' => null, 'resourcetype' => 'collection', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '' ), array( 'href' => 'remote.php/webdav/dir/welcome.txt', 'lastmodified' => 'Thu, 08 Dec 2016 16:06:26 GMT', 'status' => 'HTTP/1.1 200 OK', 'getcontentlength' => '163' ) ); // The expected result from the get_listing method in the repository_nextcloud class. $ret['list'] = array( 'DOCUMENTS/' => array( 'title' => 'Documents', 'thumbnail' => null, 'children' => array(), 'datemodified' => null, 'path' => '/dir/Documents/' ), 'WELCOME.TXT' => array( 'title' => 'welcome.txt', 'thumbnail' => null, 'size' => '163', 'datemodified' => 1481213186, 'source' => '/dir/welcome.txt' ) ); // Valid response from the client. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(true)); $mock->expects($this->once())->method('ls')->will($this->returnValue($response)); $this->set_private_property($mock, 'dav'); $ls = $this->repo->get_listing('/dir/'); // Can not be tested properly. $ls['list']['DOCUMENTS/']['thumbnail'] = null; $ls['list']['WELCOME.TXT']['thumbnail'] = null; $this->assertEquals($ret, $ls); } /** * Test the get_link method. */ public function test_get_link_success() { $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( )->getMock(); $file = '/datei'; $expectedresponse = <<<XML <?xml version="1.0"?> <ocs> <meta> <status>ok</status> <statuscode>100</statuscode> <message/> </meta> <data> <id>2</id> <share_type>3</share_type> <uid_owner>admin</uid_owner> <displayname_owner>admin</displayname_owner> <permissions>1</permissions> <stime>1502883721</stime> <parent/> <expiration/> <token>QXbqrJj8DcMaXen</token> <uid_file_owner>admin</uid_file_owner> <displayname_file_owner>admin</displayname_file_owner> <path>/somefile</path> <item_type>file</item_type> <mimetype>application/pdf</mimetype> <storage_id>home::admin</storage_id> <storage>1</storage> <item_source>6</item_source> <file_source>6</file_source> <file_parent>4</file_parent> <file_target>/somefile</file_target> <share_with/> <share_with_displayname/> <name/> <url>https://www.default.test/somefile</url> <mail_send>0</mail_send> </data> </ocs> XML; // Expected Parameters. $ocsquery = [ 'path' => $file, 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 'publicUpload' => false, 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ ]; // With test whether mock is called with right parameters. $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); $this->set_private_property($mock, 'ocsclient'); // Method does extract the link from the xml format. $this->assertEquals('https://www.default.test/somefile/download', $this->repo->get_link($file)); } /** * get_link can get OCS failure responses. Test that this is handled appropriately. */ public function test_get_link_failure() { $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( )->getMock(); $file = '/datei'; $expectedresponse = <<<XML <?xml version="1.0"?> <ocs> <meta> <status>failure</status> <statuscode>404</statuscode> <message>Msg</message> </meta> <data/> </ocs> XML; // Expected Parameters. $ocsquery = [ 'path' => $file, 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 'publicUpload' => false, 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ ]; // With test whether mock is called with right parameters. $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); $this->set_private_property($mock, 'ocsclient'); // Suppress (expected) XML parse error... Nextcloud sometimes returns JSON on extremely bad errors. libxml_use_internal_errors(true); // Method get_link correctly raises an exception that contains error code and message. $this->expectException(\repository_nextcloud\request_exception::class); $params = array('instance' => $this->repo->get_name(), 'errormessage' => sprintf('(%s) %s', '404', 'Msg')); $this->expectExceptionMessage(get_string('request_exception', 'repository_nextcloud', $params)); $this->repo->get_link($file); } /** * get_link can get OCS responses that are not actually XML. Test that this is handled appropriately. */ public function test_get_link_problem() { $mock = $this->getMockBuilder(\repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone( )->getMock(); $file = '/datei'; $expectedresponse = <<<JSON {"message":"CSRF check failed"} JSON; // Expected Parameters. $ocsquery = [ 'path' => $file, 'shareType' => \repository_nextcloud\ocs_client::SHARE_TYPE_PUBLIC, 'publicUpload' => false, 'permissions' => \repository_nextcloud\ocs_client::SHARE_PERMISSION_READ ]; // With test whether mock is called with right parameters. $mock->expects($this->once())->method('call')->with('create_share', $ocsquery)->will($this->returnValue($expectedresponse)); $this->set_private_property($mock, 'ocsclient'); // Suppress (expected) XML parse error... Nextcloud sometimes returns JSON on extremely bad errors. libxml_use_internal_errors(true); // Method get_link correctly raises an exception. $this->expectException(\repository_nextcloud\request_exception::class); $this->repo->get_link($file); } /** * Test get_file reference, merely returns the input if no optional_param is set. */ public function test_get_file_reference_withoutoptionalparam() { $this->assertEquals('/somefile', $this->repo->get_file_reference('/somefile')); } /** * Test logout. */ public function test_logout() { $mock = $this->createMock(\core\oauth2\client::class); $mock->expects($this->exactly(2))->method('log_out'); $this->set_private_property($mock, 'client'); $this->repo->options['ajax'] = false; $this->expectOutputString('<a target="_blank" rel="noopener noreferrer">Log in to your account</a>' . '<a target="_blank" rel="noopener noreferrer">Log in to your account</a>'); $this->assertEquals($this->repo->print_login(), $this->repo->logout());
< $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new moodle_url('url')));
> $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new \moodle_url('url')));
$this->repo->options['ajax'] = true; $this->assertEquals($this->repo->print_login(), $this->repo->logout()); } /** * Test for the get_file method from the repository_nextcloud class. */ public function test_get_file() { // WebDAV socket is not open. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(false)); $private = $this->set_private_property($mock, 'dav'); $this->assertFalse($this->repo->get_file('path')); // WebDAV socket is open and the request successful. $mock = $this->createMock(\webdav_client::class); $mock->expects($this->once())->method('open')->will($this->returnValue(true)); $mock->expects($this->once())->method('get_file')->will($this->returnValue(true)); $private->setValue($this->repo, $mock); $result = $this->repo->get_file('path', 'file'); $this->assertNotNull($result['path']); } /** * Test callback. */ public function test_callback() { $mock = $this->createMock(\core\oauth2\client::class); // Should call check_login exactly once. $mock->expects($this->once())->method('log_out'); $mock->expects($this->once())->method('is_logged_in'); $this->set_private_property($mock, 'client'); $this->repo->callback(); } /** * Test check_login. */ public function test_check_login() { $mock = $this->createMock(\core\oauth2\client::class); $mock->expects($this->once())->method('is_logged_in')->will($this->returnValue(true)); $this->set_private_property($mock, 'client'); $this->assertTrue($this->repo->check_login()); } /** * Test print_login. */ public function test_print_login() { $mock = $this->createMock(\core\oauth2\client::class);
< $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new moodle_url('url')));
> $mock->expects($this->exactly(2))->method('get_login_url')->will($this->returnValue(new \moodle_url('url')));
$this->set_private_property($mock, 'client'); // Test with ajax activated. $this->repo->options['ajax'] = true;
< $url = new moodle_url('url');
> $url = new \moodle_url('url');
$ret = array(); $btn = new \stdClass(); $btn->type = 'popup'; $btn->url = $url->out(false); $ret['login'] = array($btn); $this->assertEquals($ret, $this->repo->print_login()); // Test without ajax. $this->repo->options['ajax'] = false;
< $output = html_writer::link($url, get_string('login', 'repository'),
> $output = \html_writer::link($url, get_string('login', 'repository'),
array('target' => '_blank', 'rel' => 'noopener noreferrer')); $this->expectOutputString($output); $this->repo->print_login(); } /** * Test the initiate_webdavclient function. */ public function test_initiate_webdavclient() { global $CFG; $idwebdav = $this->get_endpoint_id('webdav_endpoint'); if (!empty($idwebdav)) { foreach ($idwebdav as $id) { \core\oauth2\api::delete_endpoint($id); } } $generator = $this->getDataGenerator()->get_plugin_generator('repository_nextcloud'); $generator->test_create_single_endpoint($this->issuer->get('id'), "webdav_endpoint", "https://www.default.test:8080/webdav/index.php");
< $fakeaccesstoken = new stdClass();
> $fakeaccesstoken = new \stdClass();
$fakeaccesstoken->token = "fake access token"; $oauthmock = $this->createMock(\core\oauth2\client::class); $oauthmock->expects($this->once())->method('get_accesstoken')->will($this->returnValue($fakeaccesstoken)); $this->set_private_property($oauthmock, 'client');
< $dav = phpunit_util::call_internal_method($this->repo, "initiate_webdavclient", [], 'repository_nextcloud');
> $dav = \phpunit_util::call_internal_method($this->repo, "initiate_webdavclient", [], 'repository_nextcloud');
// Verify that port is set correctly (private property).
< $refclient = new ReflectionClass($dav);
> $refclient = new \ReflectionClass($dav);
$property = $refclient->getProperty('_port'); $property->setAccessible(true); $port = $property->getValue($dav); $this->assertEquals('8080', $port); } /** * Test supported_returntypes.
< * FILE_INTERNAL when no system account is connected. < * FILE_INTERNAL | FILE_CONTROLLED_LINK when a system account is connected.
> * FILE_INTERNAL | FILE_REFERENCE when no system account is connected. > * FILE_INTERNAL | FILE_CONTROLLED_LINK | FILE_REFERENCE when a system account is connected.
*/ public function test_supported_returntypes() { global $DB;
< $this->assertEquals(FILE_INTERNAL, $this->repo->supported_returntypes()); < $dataobject = new stdClass();
> $this->assertEquals(FILE_INTERNAL | FILE_REFERENCE, $this->repo->supported_returntypes()); > $dataobject = new \stdClass();
$dataobject->timecreated = time(); $dataobject->timemodified = time(); $dataobject->usermodified = 2; $dataobject->issuerid = $this->issuer->get('id'); $dataobject->refreshtoken = 'sometokenthatwillnotbeused'; $dataobject->grantedscopes = 'openid profile email'; $dataobject->email = 'some.email@some.de'; $dataobject->username = 'someusername'; $DB->insert_record('oauth2_system_account', $dataobject); // When a system account is registered the file_type FILE_CONTROLLED_LINK is supported.
< $this->assertEquals(FILE_INTERNAL | FILE_CONTROLLED_LINK,
> $this->assertEquals(FILE_INTERNAL | FILE_CONTROLLED_LINK | FILE_REFERENCE,
$this->repo->supported_returntypes()); } /**
< * The reference_file_selected() methode is called every time a FILE_CONTROLLED_LINK is chosen for upload.
> * The reference_file_selected() method is called every time a FILE_CONTROLLED_LINK is chosen for upload.
* Since the function is very long the private function are tested separately, and merely the abortion of the * function are tested. * */ public function test_reference_file_selected_error() { $this->repo->disabled = true; $this->expectException(\repository_exception::class);
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->disabled = false; $this->expectException(\repository_exception::class); $this->expectExceptionMessage('Cannot connect as system user');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$mock = $this->createMock(\core\oauth2\client::class); $mock->expects($this->once())->method('get_system_oauth_client')->with($this->issuer)->willReturn(true); $this->expectException(\repository_exception::class); $this->expectExceptionMessage('Cannot connect as current user');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); $this->expectException(\repository_exception::class); $this->expectExceptionMessage('cannotdownload');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); $this->expectException(\repository_exception::class); $this->expectExceptionMessage('cannotdownload');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => array('success' => 400))); $this->expectException(\repository_exception::class); $this->expectExceptionMessage('Could not copy file');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => array('success' => 201))); $this->repo->expects($this->once())->method('delete_share_dataowner_sysaccount')->willReturn( array('statuscode' => array('success' => 400))); $this->expectException(\repository_exception::class); $this->expectExceptionMessage('Share is still present');
< $this->repo->reference_file_selected('', context_system::instance(), '', '', '');
> $this->repo->reference_file_selected('', \context_system::instance(), '', '', '');
$this->repo->expects($this->once())->method('get_user_oauth_client')->willReturn(true); $this->repo->expects($this->once())->method('copy_file_to_path')->willReturn(array('statuscode' => array('success' => 201))); $this->repo->expects($this->once())->method('delete_share_dataowner_sysaccount')->willReturn( array('statuscode' => array('success' => 100)));
< $filereturn = array();
> $filereturn = new \stdClass();
$filereturn->link = 'some/fullpath' . 'some/target/path'; $filereturn->name = 'mysource'; $filereturn->usesystem = true; $filereturn = json_encode($filereturn);
< $return = $this->repo->reference_file_selected('mysource', context_system::instance(), '', '', '');
> $return = $this->repo->reference_file_selected('mysource', \context_system::instance(), '', '', '');
$this->assertEquals($filereturn, $return); } /** * Test the send_file function for access controlled links. */ public function test_send_file_errors() { $fs = get_file_storage(); $storedfile = $fs->create_file_from_reference([
< 'contextid' => context_system::instance()->id,
> 'contextid' => \context_system::instance()->id,
'component' => 'core', 'filearea' => 'unittest', 'itemid' => 0, 'filepath' => '/', 'filename' => 'testfile.txt', ], $this->repo->id, json_encode([ 'type' => 'FILE_CONTROLLED_LINK', 'link' => 'https://test.local/fakelink/', 'usesystem' => true, ])); $this->set_private_property('', 'client'); $this->expectException(repository_nextcloud\request_exception::class); $this->expectExceptionMessage(get_string('contactadminwith', 'repository_nextcloud', 'The OAuth clients could not be connected.')); $this->repo->send_file($storedfile, '', '', ''); // Testing whether the mock up appears is topic to behat. $mock = $this->createMock(\core\oauth2\client::class); $mock->expects($this->once())->method('is_logged_in')->willReturn(true); $this->repo->send_file($storedfile, '', '', ''); // Checks that setting for foldername are used. $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(false); // In case of false as return value mkcol is called to create the folder. $parsedwebdavurl = parse_url($this->issuer->get_endpoint_url('webdav')); $webdavprefix = $parsedwebdavurl['path']; $mock->expects($this->once())->method('mkcol')->with( $webdavprefix . 'Moodlefiles')->willReturn(400); $this->expectException(\repository_nextcloud\request_exception::class); $this->expectExceptionMessage(get_string('requestnotexecuted', 'repository_nextcloud')); $this->repo->send_file($storedfile, '', '', ''); $expectedresponse = <<<XML <?xml version="1.0"?> <ocs> <meta> <status>ok</status> <statuscode>100</statuscode> <message/> </meta> <data> <element> <id>6</id> <share_type>0</share_type> <uid_owner>tech</uid_owner> <displayname_owner>tech</displayname_owner> <permissions>19</permissions> <stime>1511877999</stime> <parent/> <expiration/> <token/> <uid_file_owner>tech</uid_file_owner> <displayname_file_owner>tech</displayname_file_owner>
< <path>/System/Category Miscellaneous/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path>
> <path>/System/Category Category 1/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path>
<item_type>file</item_type> <mimetype>text/plain</mimetype> <storage_id>home::tech</storage_id> <storage>4</storage> <item_source>824</item_source> <file_source>824</file_source> <file_parent>823</file_parent> <file_target>/merge (3).txt</file_target> <share_with>user2</share_with> <share_with_displayname>user1</share_with_displayname> <mail_send>0</mail_send> </element> <element> <id>5</id> <share_type>0</share_type> <uid_owner>tech</uid_owner> <displayname_owner>tech</displayname_owner> <permissions>19</permissions> <stime>1511877999</stime> <parent/> <expiration/> <token/> <uid_file_owner>tech</uid_file_owner> <displayname_file_owner>tech</displayname_file_owner>
< <path>/System/Category Miscellaneous/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path>
> <path>/System/Category Category 1/Course Example Course/File morefiles/mod_resource/content/0/merge.txt</path>
<item_type>file</item_type> <mimetype>text/plain</mimetype> <storage_id>home::tech</storage_id> <storage>4</storage> <item_source>824</item_source> <file_source>824</file_source> <file_parent>823</file_parent> <file_target>/merged (3).txt</file_target> <share_with>user1</share_with> <share_with_displayname>user1</share_with_displayname> <mail_send>0</mail_send> </element> </data> </ocs> XML; // Checks that setting for foldername are used. $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(true); // In case of true as return value mkcol is not called to create the folder. $shareid = 5; $mockocsclient = $this->getMockBuilder( \repository_nextcloud\ocs_client::class)->disableOriginalConstructor()->disableOriginalClone()->getMock(); $mockocsclient->expects($this->exactly(2))->method('call')->with('get_information_of_share', array('share_id' => $shareid))->will($this->returnValue($expectedresponse)); $this->set_private_property($mock, 'ocsclient'); $this->repo->expects($this->once())->method('move_file_to_folder')->with('/merged (3).txt', 'Moodlefiles', $mock)->willReturn(array('success' => 201)); $this->repo->send_file('', '', '', ''); // Create test for statuscode 403. // Checks that setting for foldername are used. $mock->expects($this->once())->method('is_dir')->with('Moodlefiles')->willReturn(true); // In case of true as return value mkcol is not called to create the folder. $shareid = 5; $mockocsclient = $this->getMockBuilder(\repository_nextcloud\ocs_client::class )->disableOriginalConstructor()->disableOriginalClone()->getMock(); $mockocsclient->expects($this->exactly(1))->method('call')->with('get_shares', array('path' => '/merged (3).txt', 'reshares' => true))->will($this->returnValue($expectedresponse)); $mockocsclient->expects($this->exactly(1))->method('call')->with('get_information_of_share', array('share_id' => $shareid))->will($this->returnValue($expectedresponse)); $this->set_private_property($mock, 'ocsclient'); $this->repo->expects($this->once())->method('move_file_to_folder')->with('/merged (3).txt', 'Moodlefiles', $mock)->willReturn(array('success' => 201)); $this->repo->send_file('', '', '', ''); } /**
> * This function provides the data for test_sync_reference * Helper method, which inserts a given mock value into the repository_nextcloud object. > * * > * @return array[] * @param mixed $value mock value that will be inserted. > */ * @param string $propertyname name of the private property. > public function sync_reference_provider():array { * @return ReflectionProperty the resulting reflection property. > return [ */ > 'referecncelastsync done recently' => [ protected function set_private_property($value, $propertyname) { > [ $refclient = new ReflectionClass($this->repo); > 'storedfile_record' => [ $private = $refclient->getProperty($propertyname); > 'contextid' => \context_system::instance()->id, $private->setAccessible(true); > 'component' => 'core', $private->setValue($this->repo, $value); > 'filearea' => 'unittest', > 'itemid' => 0, return $private; > 'filepath' => '/', } > 'filename' => 'testfile.txt', /** > ], * Helper method to set required return parameters for get_listing. > 'storedfile_reference' => json_encode( * > [ * @return array array, which contains the parameters. > 'type' => 'FILE_REFERENCE', */ > 'link' => 'https://test.local/fakelink/', protected function get_initialised_return_array() { > 'usesystem' => true, $ret = array(); > 'referencelastsync' => DAYSECS + time() $ret['dynload'] = true; > ] $ret['nosearch'] = true; > ), $ret['nologin'] = false; > ], $ret['path'] = [ > 'mockfunctions' => ['get_referencelastsync'], [ > 'expectedresult' => false 'name' => $this->repo->get_meta()->name, > ], 'path' => '', > 'file without link' => [ ] > [ ]; > 'storedfile_record' => [ $ret['manage'] = ''; > 'contextid' => \context_system::instance()->id, $ret['defaultreturntype'] = FILE_INTERNAL; > 'component' => 'core', $ret['list'] = array(); > 'filearea' => 'unittest', > 'itemid' => 0, return $ret; > 'filepath' => '/', } > 'filename' => 'testfile.txt', } > ], > 'storedfile_reference' => json_encode( > [ > 'type' => 'FILE_REFERENCE', > 'usesystem' => true, > ] > ), > ], > 'mockfunctions' => [], > 'expectedresult' => false > ], > 'file extenstion to exclude' => [ > [ > 'storedfile_record' => [ > 'contextid' => \context_system::instance()->id, > 'component' => 'core', > 'filearea' => 'unittest', > 'itemid' => 0, > 'filepath' => '/', > 'filename' => 'testfile.txt', > ], > 'storedfile_reference' => json_encode( > [ > 'link' => 'https://test.local/fakelink/', > 'type' => 'FILE_REFERENCE', > 'usesystem' => true, > ] > ), > ], > 'mockfunctions' => [], > 'expectedresult' => false > ], > 'file extenstion for image' => [ > [ > 'storedfile_record' => [ > 'contextid' => \context_system::instance()->id, > 'component' => 'core', > 'filearea' => 'unittest', > 'itemid' => 0, > 'filepath' => '/', > 'filename' => 'testfile.png', > ], > 'storedfile_reference' => json_encode( > [ > 'link' => 'https://test.local/fakelink/', > 'type' => 'FILE_REFERENCE', > 'usesystem' => true, > ] > ), > 'mock_curl' => true, > ], > 'mockfunctions' => [''], > 'expectedresult' => true > ], > ]; > } > > /** > * Testing sync_reference > * > * @dataProvider sync_reference_provider > * @param array $storedfileargs > * @param array $storedfilemethodsmock > * @param bool $expectedresult > * @return void > */ > public function test_sync_reference(array $storedfileargs, $storedfilemethodsmock, bool $expectedresult):void { > $this->resetAfterTest(true); > > if (isset($storedfilemethodsmock[0])) { > $storedfile = $this->createMock(\stored_file::class); > > if ($storedfilemethodsmock[0] === 'get_referencelastsync') { > if (!$expectedresult) { > $storedfile->method('get_referencelastsync')->willReturn(DAYSECS + time()); > } > } else { > $storedfile->method('get_referencelastsync')->willReturn(null); > } > > $storedfile->method('get_reference')->willReturn($storedfileargs['storedfile_reference']); > $storedfile->method('get_filepath')->willReturn($storedfileargs['storedfile_record']['filepath']); > $storedfile->method('get_filename')->willReturn($storedfileargs['storedfile_record']['filename']); > > if ((isset($storedfileargs['mock_curl']) && $storedfileargs)) { > // Lets mock curl, else it would not serve the purpose here. > $curl = $this->createMock(\curl::class); > $curl->method('download_one')->willReturn(true); > $curl->method('get_info')->willReturn(['http_code' => 200]); > > $reflectionproperty = new \ReflectionProperty($this->repo, 'curl'); > $reflectionproperty->setAccessible(true); > $reflectionproperty->setValue($this->repo, $curl); > } > } else { > $fs = get_file_storage(); > $storedfile = $fs->create_file_from_reference( > $storedfileargs['storedfile_record'], > $this->repo->id, > $storedfileargs['storedfile_reference']); > } > > $actualresult = $this->repo->sync_reference($storedfile); > $this->assertEquals($expectedresult, $actualresult); > } > > /**
< $refclient = new ReflectionClass($this->repo);
> $refclient = new \ReflectionClass($this->repo);
> > $ret['filereferencewarning'] = get_string('externalpubliclinkwarning', 'repository_nextcloud');