MDL-67790 core_contentbank: Unit and behat tests for renaming content
authorAmaia Anabitarte <amaia@moodle.com>
Fri, 17 Apr 2020 11:40:33 +0000 (13:40 +0200)
committerAmaia Anabitarte <amaia@moodle.com>
Mon, 4 May 2020 18:15:05 +0000 (20:15 +0200)
contentbank/contenttype/h5p/tests/behat/manage_content.feature [new file with mode: 0644]
contentbank/contenttype/h5p/tests/content_h5p_test.php
contentbank/tests/content_test.php
contentbank/tests/contenttype_test.php
contentbank/tests/external/rename_content_test.php [new file with mode: 0644]

diff --git a/contentbank/contenttype/h5p/tests/behat/manage_content.feature b/contentbank/contenttype/h5p/tests/behat/manage_content.feature
new file mode 100644 (file)
index 0000000..5705a9e
--- /dev/null
@@ -0,0 +1,47 @@
+@core @core_contentbank @contenttype_h5p @_file_upload @javascript
+Feature: Manage H5P content from the content bank
+  In order to manage H5P content in the content bank
+  As an admin
+  I need to be able to edit any H5P content in the content bank
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email                |
+      | teacher1 | Teacher   | 1        | teacher1@example.com |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1        | 0        |
+    And the following "course enrolments" exist:
+      | user     | course | role           |
+      | teacher1 | C1     | editingteacher |
+    And the following "contentbank content" exist:
+      | course| contenttype     | user     | contentname       |
+      | C1    | contenttype_h5p | admin    | filltheblanks.h5p |
+      | C1    | contenttype_h5p | teacher1 | ipsums.h5p        |
+    And I log in as "admin"
+    And I am on "Course 1" course homepage with editing mode on
+    And I add the "Navigation" block if not present
+    And I log out
+
+  Scenario: Teachers can rename their own content in the content bank
+    Given I log in as "teacher1"
+    And I am on "Course 1" course homepage
+    And I expand "Site pages" node
+    And I click on "Content bank" "link"
+    And I follow "ipsums.h5p"
+    When I open the action menu in "region-main-settings-menu" "region"
+    And I should see "Rename"
+    And I choose "Rename" in the open action menu
+    And I set the field "Content name" to "New name"
+    And I click on "Rename" "button"
+    And I wait until the page is ready
+    Then I should not see "ipsums.h5p"
+    And I should see "New name"
+
+  Scenario: Teachers can't rename content created by other users in the content bank
+    Given I log in as "teacher1"
+    And I am on "Course 1" course homepage
+    And I expand "Site pages" node
+    And I click on "Content bank" "link"
+    When I follow "filltheblanks.h5p"
+    Then "region-main-settings-menu" "region" should not exist
index a4082f8..657a459 100644 (file)
@@ -51,14 +51,14 @@ class contenttype_h5p_content_plugin_testcase extends advanced_testcase {
 
         // Create a dummy file.
         $filename = 'content.h5p';
-        $dummy = array(
+        $dummy = [
             'contextid' => \context_system::instance()->id,
             'component' => 'contentbank',
             'filearea' => 'public',
             'itemid' => $content->get_id(),
             'filepath' => '/',
             'filename' => $filename
-        );
+        ];
         $fs = get_file_storage();
         $fs->create_file_from_string($dummy, 'dummy content');
 
index 04b722f..2fcd66c 100644 (file)
@@ -64,6 +64,55 @@ class core_contenttype_content_testcase extends \advanced_testcase {
         $this->assertEquals($record->name, $content->get_name());
     }
 
+    /**
+     * Data provider for test_set_name.
+     *
+     * @return  array
+     */
+    public function set_name_provider() {
+        return [
+            'Standard name' => ['New name', 'New name'],
+            'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017'],
+            'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle'],
+            'Name with tags' => ['This is <b>bold</b>', 'This is bold'],
+            'Long name' => [str_repeat('a', 100), str_repeat('a', 100)],
+            'Too long name' => [str_repeat('a', 300), str_repeat('a', 255)]
+        ];
+    }
+
+    /**
+     * Tests for 'set_name' behaviour.
+     *
+     * @dataProvider    set_name_provider
+     * @param   string  $newname    The name to set
+     * @param   string   $expected   The name result
+     *
+     * @covers ::set_name
+     */
+    public function test_set_name(string $newname, string $expected) {
+        global $DB;
+
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        $oldname = "Old name";
+        $context = context_system::instance();
+
+        // Create content.
+        $record = new stdClass();
+        $record->name = $oldname;
+
+        $contenttype = new contenttype($context);
+        $content = $contenttype->create_content($record);
+        $this->assertEquals($oldname, $content->get_name());
+
+        $content->set_name($newname);
+        $this->assertEquals($expected, $content->get_name());
+
+        $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
+        $this->assertEquals($expected, $record->name);
+    }
+
     /**
      * Tests for behaviour of get_content_type().
      *
index 7175b63..e74bd1b 100644 (file)
@@ -176,7 +176,6 @@ class core_contenttype_contenttype_testcase extends \advanced_testcase {
         $this->assertInstanceOf('\\contenttype_testable\\content', $content);
     }
 
-
     /**
      * Test the behaviour of can_delete().
      */
@@ -254,4 +253,105 @@ class core_contenttype_contenttype_testcase extends \advanced_testcase {
 
         $this->contenttype = new \contenttype_testable\contenttype($systemcontext);
     }
+
+    /**
+     * Data provider for test_rename_content.
+     *
+     * @return  array
+     */
+    public function rename_content_provider() {
+        return [
+            'Standard name' => ['New name', 'New name'],
+            'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017'],
+            'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle'],
+            'Name with tags' => ['This is <b>bold</b>', 'This is bold'],
+            'Long name' => [str_repeat('a', 100), str_repeat('a', 100)],
+            'Too long name' => [str_repeat('a', 300), str_repeat('a', 255)]
+        ];
+    }
+
+    /**
+     * Test the behaviour of rename_content().
+     *
+     * @dataProvider    rename_content_provider
+     * @param   string  $newname    The name to set
+     * @param   string   $expected   The name result
+     *
+     * @covers ::rename_content
+     */
+    public function test_rename_content(string $newname, string $expected) {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        // Create course and teacher user.
+        $course = $this->getDataGenerator()->create_course();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
+        $coursecontext = \context_course::instance($course->id);
+        $contenttype = new contenttype($coursecontext);
+
+        // Add some content to the content bank as teacher.
+        $this->setUser($teacher);
+        $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
+        $contents = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id);
+        $content = array_shift($contents);
+
+        $oldname = $content->get_name();
+
+        // Check the content is renamed as expected by a user with permission.
+        $renamed = $contenttype->rename_content($content, $newname);
+        $this->assertTrue($renamed);
+        $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
+        $this->assertNotEquals($oldname, $record->name);
+        $this->assertEquals($expected, $record->name);
+    }
+
+    /**
+     * Test the behaviour of can_manage().
+     *
+     * @covers ::can_manage
+     */
+    public function test_can_manage() {
+        global $DB, $USER;
+
+        $this->resetAfterTest();
+        $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
+
+        // Create course and teacher user.
+        $teacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
+        $course = $this->getDataGenerator()->create_course();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
+        $manager = $this->getDataGenerator()->create_and_enrol($course, 'manager');
+        $coursecontext = \context_course::instance($course->id);
+
+        $contenttype = new contenttype($coursecontext);
+
+        // Add some content to the content bank as admin.
+        $this->setAdminUser();
+        $contentsbyadmin = $generator->generate_contentbank_data('contenttype_testable', 1, $USER->id, $coursecontext);
+        $contentbyadmin = array_shift($contentsbyadmin);
+
+        // Add some content to the content bank as teacher.
+        $contentsbyteacher = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id, $coursecontext);
+        $contentbyteacher = array_shift($contentsbyteacher);
+
+        // Check the content has been created as expected.
+        $records = $DB->count_records('contentbank_content');
+        $this->assertEquals(2, $records);
+
+        // Check manager can manage by default all the contents created.
+        $this->setUser($manager);
+        $this->assertTrue($contenttype->can_manage($contentbyteacher));
+        $this->assertTrue($contenttype->can_manage($contentbyadmin));
+
+        // Check teacher can only edit their own content.
+        $this->setUser($teacher);
+        $this->assertTrue($contenttype->can_manage($contentbyteacher));
+        $this->assertFalse($contenttype->can_manage($contentbyadmin));
+
+        // Unassign capability to teacher role and check they not can not edit any content.
+        unassign_capability('moodle/contentbank:manageowncontent', $teacherroleid);
+        $this->assertFalse($contenttype->can_manage($contentbyteacher));
+        $this->assertFalse($contenttype->can_manage($contentbyadmin));
+    }
 }
diff --git a/contentbank/tests/external/rename_content_test.php b/contentbank/tests/external/rename_content_test.php
new file mode 100644 (file)
index 0000000..4b1bf6b
--- /dev/null
@@ -0,0 +1,140 @@
+<?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/>.
+
+/**
+ * Core content bank external functions tests.
+ *
+ * @package    core_contentbank
+ * @category   external
+ * @copyright  2020 Sara Arjona <sara@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.9
+ */
+
+namespace core_contentbank;
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
+require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
+require_once($CFG->dirroot . '/webservice/tests/helpers.php');
+
+use core_contentbank\external\delete_content;
+use core_contentbank\external\external;
+use core_contentbank\external\rename_content;
+use external_api;
+
+/**
+ * Core content bank external functions tests.
+ *
+ * @package    core_contentbank
+ * @copyright  2020 Sara Arjona <sara@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @coversDefaultClass \core_contentbank\external
+ */
+class rename_content_testcase extends \externallib_advanced_testcase {
+
+    /**
+     * Data provider for test_rename_content.
+     *
+     * @return  array
+     */
+    public function rename_content_provider() {
+        return [
+            'Standard name' => ['New name', 'New name'],
+            'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017'],
+            'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle'],
+            'Name with tags' => ['This is <b>bold</b>', 'This is bold'],
+            'Long name' => [str_repeat('a', 100), str_repeat('a', 100)],
+            'Too long name' => [str_repeat('a', 300), str_repeat('a', 255)]
+        ];
+    }
+
+    /**
+     * Test the behaviour of rename_content() for users with permission.
+     *
+     * @dataProvider    rename_content_provider
+     * @param   string  $newname    The name to set
+     * @param   string   $expected   The name result
+     *
+     * @covers ::execute
+     */
+    public function test_rename_content_with_permission(string $newname, string $expected) {
+        global $DB;
+        $this->resetAfterTest();
+
+        // Create users.
+        $roleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
+        $teacher = $this->getDataGenerator()->create_user();
+
+        $this->getDataGenerator()->role_assign($roleid, $teacher->id);
+        $this->setUser($teacher);
+
+        // Add some content to the content bank as teacher.
+        $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
+        $contents = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id);
+        $content = array_shift($contents);
+
+        $oldname = $content->get_name();
+
+        // Call the WS and check the content is renamed as expected.
+        $result = rename_content::execute($content->get_id(), $newname);
+        $result = external_api::clean_returnvalue(rename_content::execute_returns(), $result);
+        $this->assertTrue($result['result']);
+        $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
+        $this->assertNotEquals($oldname, $record->name);
+        $this->assertEquals($expected, $record->name);
+
+        // Call the WS using an unexisting contentid and check an error is thrown.
+        $this->expectException(\invalid_response_exception::class);
+        $result = rename_content::execute_returns($content->get_id() + 1, $oldname);
+        $result = external_api::clean_returnvalue(rename_content::execute_returns(), $result);
+        $this->assertFalse($result['result']);
+    }
+
+    /**
+     * Test the behaviour of rename_content() for users with permission.
+     *
+     * @covers ::execute
+     */
+    public function test_rename_content_without_permission() {
+        global $DB;
+        $this->resetAfterTest();
+
+        // Create users.
+        $course = $this->getDataGenerator()->create_course();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
+        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
+
+        // Add some content to the content bank as teacher.
+        $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
+        $contents = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id);
+        $content = array_shift($contents);
+
+        $oldname = $content->get_name();
+        $newname = 'New name';
+
+        // Call the WS and check the content has not been renamed by the student.
+        $this->setUser($student);
+        $result = rename_content::execute($content->get_id(), $newname);
+        $result = external_api::clean_returnvalue(rename_content::execute_returns(), $result);
+        $this->assertFalse($result['result']);
+        $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
+        $this->assertEquals($oldname, $record->name);
+        $this->assertNotEquals($newname, $record->name);
+    }
+}