Merge branch 'install_master' of https://git.in.moodle.com/amosbot/moodle-install
authorDan Poltawski <dan@moodle.com>
Thu, 12 Jan 2017 07:42:24 +0000 (07:42 +0000)
committerDan Poltawski <dan@moodle.com>
Thu, 12 Jan 2017 07:42:24 +0000 (07:42 +0000)
131 files changed:
.gherkin-lintrc [new file with mode: 0644]
Gruntfile.js
admin/tool/behat/tests/behat/get_and_set_fields.feature
admin/tool/behat/tests/behat/list_steps.feature
admin/tool/langimport/classes/output/langimport_page.php [new file with mode: 0644]
admin/tool/langimport/classes/output/renderer.php [new file with mode: 0644]
admin/tool/langimport/index.php
admin/tool/langimport/styles.css
admin/tool/langimport/templates/langimport.mustache [new file with mode: 0644]
admin/tool/langimport/tests/behat/manage_langpacks.feature
admin/tool/lp/tests/behat/framework_crud.feature
admin/tool/lp/tests/behat/plan_workflow.feature
admin/tool/lp/tests/behat/user_evidence_crud.feature
badges/mybackpack.php
badges/mybadges.php
badges/tests/behat/award_badge.feature
blocks/activity_results/tests/behat/addblockinactivity.feature
blocks/activity_results/tests/behat/addunconfiguredblock.feature
blocks/activity_results/tests/behat/addunsupportedactivity.feature
blocks/activity_results/tests/behat/highscoreswithoutgroups.feature
blocks/activity_results/tests/behat/highscoreswithscales.feature
blocks/activity_results/tests/behat/highscoreswithscalesandgroups.feature
blocks/activity_results/tests/behat/highscoreswithseperategroups.feature
blocks/activity_results/tests/behat/highscoreswithvisiblegroups.feature
blocks/activity_results/tests/behat/lowscoreswithoutgroups.feature
blocks/activity_results/tests/behat/lowscoreswithscales.feature
blocks/activity_results/tests/behat/lowscoreswithscalesandgroups.feature
blocks/activity_results/tests/behat/lowscoreswithseperategroups.feature
blocks/activity_results/tests/behat/lowscoreswithvisiblegroups.feature
blocks/blog_menu/tests/behat/block_blog_menu_course.feature
blocks/calendar_upcoming/tests/behat/block_calendar_upcoming_dashboard.feature
blocks/completionstatus/tests/behat/block_completionstatus_manual_other.feature
blocks/course_overview/tests/behat/quiz_overview.feature
blocks/glossary_random/tests/behat/glossary_random_frontpage.feature
blocks/html/tests/behat/multiple_instances.feature
blocks/online_users/tests/behat/block_online_users_dashboard.feature
blocks/online_users/tests/behat/block_online_users_frontpage.feature
blocks/private_files/tests/behat/block_private_files_activity.feature
blocks/private_files/tests/behat/block_private_files_course.feature
blocks/private_files/tests/behat/block_private_files_dashboard.feature
blocks/private_files/tests/behat/block_private_files_frontpage.feature
blocks/search_forums/tests/behat/block_search_forums_course.feature
blocks/search_forums/tests/behat/block_search_forums_frontpage.feature
blocks/section_links/tests/behat/block_section_links_course.feature
blog/tests/behat/delete.feature
cache/classes/loaders.php
cache/stores/redis/addinstanceform.php
cache/stores/redis/lang/en/cachestore_redis.php
cache/stores/redis/lib.php
cache/stores/redis/settings.php
cache/tests/cache_test.php
calendar/tests/behat/calendar.feature
cohort/tests/behat/access_visible_cohorts.feature
course/dndupload.js
course/externallib.php
course/format/social/tests/behat/social_adjust_discussion_count.feature
course/tests/behat/category_change_visibility.feature
course/tests/behat/course_search.feature
course/tests/behat/force_group_mode.feature
course/tests/behat/view_subfolders_inline.feature
course/tests/courselib_test.php
course/tests/externallib_test.php
course/upgrade.txt
files/tests/behat/add_custom_file_type.feature
grade/report/grader/tests/behat/ajax_grader.feature
grade/report/user/tests/behat/view_usereport.feature
grade/tests/behat/behat_grade.php
grade/tests/behat/grade_calculated_grade_items.feature
grade/tests/behat/grade_item_validation.feature
grade/tests/behat/grade_letter_boundary_20160518.feature
grade/tests/behat/grade_natural_normalisation.feature
lib/editor/atto/plugins/accessibilityhelper/tests/behat/accessibilityhelper.feature
lib/editor/atto/plugins/align/tests/behat/align.feature
lib/editor/atto/plugins/clear/tests/behat/clear.feature
lib/editor/atto/plugins/collapse/tests/behat/collapse.feature
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
lib/editor/atto/plugins/equation/yui/src/button/js/button.js
lib/editor/atto/plugins/html/tests/behat/html.feature
lib/editor/atto/plugins/link/tests/behat/link.feature
lib/editor/atto/plugins/media/tests/behat/media.feature
lib/editor/atto/plugins/strike/tests/behat/strike.feature
lib/editor/atto/plugins/subscript/tests/behat/subscript.feature
lib/editor/atto/plugins/superscript/tests/behat/superscript.feature
lib/editor/atto/plugins/title/tests/behat/title.feature
lib/editor/atto/plugins/underline/tests/behat/underline.feature
lib/formslib.php
lib/navigationlib.php
lib/tests/behat/behat_deprecated.php
lib/tests/behat/behat_hooks.php
message/tests/behat/manage_contacts.feature
mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature
mod/assign/tests/behat/display_error_message_onbadformat.feature
mod/book/tests/behat/show_hide_chapters.feature
mod/choice/tests/behat/block_editing.feature
mod/data/tests/behat/required_entries.feature
mod/forum/backup/moodle2/restore_forum_stepslib.php
mod/forum/tests/behat/discussion_subscriptions.feature
mod/forum/tests/behat/post_to_multiple_groups.feature
mod/glossary/tests/behat/prevent_duplicate_entries.feature
mod/lesson/tests/behat/import_images.feature
mod/lesson/tests/behat/lesson_edit_cluster.feature
mod/lesson/tests/behat/lesson_group_override.feature
mod/lesson/tests/behat/lesson_practice.feature
mod/lesson/tests/behat/lesson_with_clusters.feature
mod/lesson/tests/behat/lesson_with_subcluster.feature
mod/lti/tests/behat/contentitemregistration.feature
mod/quiz/tests/behat/attempt_basic.feature
mod/quiz/tests/behat/attempt_require_previous.feature
mod/quiz/tests/behat/editing_section_headings.feature
mod/quiz/tests/behat/editing_set_marks_no_attempts.feature
mod/quiz/tests/behat/editing_set_marks_with_attempts.feature
mod/quiz/tests/behat/quiz_reset.feature
mod/scorm/tests/behat/completion_condition_require_status.feature
mod/wiki/tests/behat/collaborative_individual.feature
mod/wiki/tests/behat/wiki_search.feature
mod/workshop/tests/behat/workshop_assessment.feature
npm-shrinkwrap.json
package.json
question/tests/behat/copy_questions.feature
question/type/ddmarker/tests/behat/preview.feature
question/type/description/tests/behat/add.feature
question/type/essay/tests/behat/export.feature
question/type/gapselect/tests/behat/import_test.feature
question/type/shortanswer/tests/behat/preview.feature
question/type/truefalse/tests/behat/add.feature
report/loglive/tests/behat/loglive_report.feature
repository/manage_instances.php
user/files.php
user/tests/behat/view_preferences_page.feature

diff --git a/.gherkin-lintrc b/.gherkin-lintrc
new file mode 100644 (file)
index 0000000..9439956
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "indentation": ["on",{
+    "Feature": 0,
+    "Background": 2,
+    "Scenario": 2,
+    "Step": 4,
+    "given": 4,
+    "and": 4
+  }],
+  "no-dupe-feature-names": "on",
+  "no-dupe-scenario-names": "off",
+  "no-empty-file": "on",
+  "no-files-without-scenarios": "on",
+  "no-multiple-empty-lines": "on",
+  "no-partially-commented-tag-lines": "on",
+  "no-trailing-spaces": "on",
+  "no-unamed-features": "on",
+  "no-unamed-scenarios": "on",
+  "no-scenario-outlines-without-examples": "on"
+}
index 5852cc4..4cb9e9e 100644 (file)
@@ -106,7 +106,6 @@ module.exports = function(grunt) {
         return libs;
     };
 
-
     // Project configuration.
     grunt.initConfig({
         eslint: {
@@ -171,6 +170,10 @@ module.exports = function(grunt) {
                 files: ['**/yui/src/**/*.js'],
                 tasks: ['yui']
             },
+            gherkinlint: {
+                files: ['**/tests/behat/*.feature'],
+                tasks: ['gherkinlint']
+            }
         },
         shifter: {
             options: {
@@ -178,6 +181,11 @@ module.exports = function(grunt) {
                 paths: [cwd]
             }
         },
+        gherkinlint: {
+            options: {
+                files: ['**/tests/behat/*.feature'],
+            }
+        },
         stylelint: {
             less: {
                 options: {
@@ -318,6 +326,22 @@ module.exports = function(grunt) {
         }, done);
     };
 
+    tasks.gherkinlint = function() {
+        var done = this.async(),
+            options = grunt.config('gherkinlint.options');
+
+        var args = grunt.file.expand(options.files);
+        args.unshift(path.normalize(__dirname + '/node_modules/.bin/gherkin-lint'));
+        grunt.util.spawn({
+            cmd: 'node',
+            args: args,
+            opts: {stdio: 'inherit', env: process.env}
+        }, function(error, result, code) {
+            // Propagate the exit code.
+            done(code);
+        });
+    };
+
     tasks.startup = function() {
         // Are we in a YUI directory?
         if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
@@ -329,6 +353,7 @@ module.exports = function(grunt) {
             // Run them all!.
             grunt.task.run('css');
             grunt.task.run('js');
+            grunt.task.run('gherkinlint');
         }
     };
 
@@ -343,6 +368,7 @@ module.exports = function(grunt) {
           grunt.config('uglify.amd.files', [{expand: true, src: files, rename: uglifyRename}]);
           grunt.config('shifter.options.paths', files);
           grunt.config('stylelint.less.src', files);
+          grunt.config('gherkinlint.options.files', files);
           changedFiles = Object.create(null);
     }, 200);
 
@@ -360,6 +386,7 @@ module.exports = function(grunt) {
 
     // Register JS tasks.
     grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
+    grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
     grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
     grunt.registerTask('yui', ['eslint:yui', 'shifter']);
     grunt.registerTask('amd', ['eslint:amd', 'uglify']);
index f9ac3a1..4b467bc 100644 (file)
@@ -125,7 +125,6 @@ Feature: Verify that all form fields values can be get and set
     And I navigate to "Edit settings" node in "Course administration"
     And the field "Course ID number" matches value "Course id number"
 
-
   Scenario: with JS disabled all form fields getters and setters works as expected
 
   @javascript
index 3e4d31e..708a0e7 100644 (file)
@@ -26,4 +26,3 @@ Feature: List the system steps definitions
     Given I set the field "Contains" to "homepage"
     When I press "Filter"
     Then I should see "Opens Moodle homepage."
-
diff --git a/admin/tool/langimport/classes/output/langimport_page.php b/admin/tool/langimport/classes/output/langimport_page.php
new file mode 100644 (file)
index 0000000..97ff743
--- /dev/null
@@ -0,0 +1,110 @@
+<?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/>.
+
+/**
+ * Language import page.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace tool_langimport\output;
+defined('MOODLE_INTERNAL') || die();
+
+use moodle_url;
+use renderable;
+use renderer_base;
+use stdClass;
+use templatable;
+
+/**
+ * Language import page class.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class langimport_page implements renderable, templatable {
+
+    /** @var array Array of currently installed languages. */
+    protected $installedlanguages;
+
+    /** @var array Array of languages that can be installed. */
+    protected $availablelanguages;
+
+    /** @var moodle_url The URL to be used for uninstalling the selected existing language packs. */
+    protected $uninstallurl;
+
+    /** @var moodle_url The URL to be used for updating the installed language packs. */
+    protected $updateurl;
+
+    /** @var moodle_url The URL to be used for installing the selected language packs to be installed. */
+    protected $installurl;
+
+
+    /**
+     * langimport_page constructor.
+     *
+     * @param array $installedlanguages Array of currently installed languages.
+     * @param array $availablelanguages Array of languages that can be installed.
+     * @param moodle_url $uninstallurl The URL to be used for uninstalling the selected existing language packs.
+     * @param moodle_url $updateurl The URL to be used for updating the installed language packs.
+     * @param moodle_url $installurl The URL to be used for installing the selected language packs to be installed.
+     */
+    public function __construct($installedlanguages, $availablelanguages, $uninstallurl, $updateurl, $installurl) {
+        $this->installedlanguages = $installedlanguages;
+        $this->availablelanguages = $availablelanguages;
+        $this->uninstallurl = $uninstallurl;
+        $this->updateurl = $updateurl;
+        $this->installurl = $installurl;
+    }
+
+    /**
+     * Export the data.
+     *
+     * @param renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(renderer_base $output) {
+        $data = new stdClass();
+        $data->uninstallurl = $this->uninstallurl;
+        $data->sesskey = sesskey();
+
+        $data->installedoptions = [];
+        foreach ($this->installedlanguages as $code => $language) {
+            $option = new stdClass();
+            $option->value = $code;
+            $option->text = $language;
+            $data->installedoptions[] = $option;
+        }
+
+        $data->updateurl = $this->updateurl;
+
+        if (!empty($this->availablelanguages)) {
+            $data->toinstalloptions = [];
+            foreach ($this->availablelanguages as $code => $language) {
+                $option = new stdClass();
+                $option->value = $code;
+                $option->text = $language;
+                $data->toinstalloptions[] = $option;
+            }
+            $data->installurl = $this->installurl;
+            $data->caninstall = true;
+        }
+
+        return $data;
+    }
+}
diff --git a/admin/tool/langimport/classes/output/renderer.php b/admin/tool/langimport/classes/output/renderer.php
new file mode 100644 (file)
index 0000000..f74b11e
--- /dev/null
@@ -0,0 +1,50 @@
+<?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/>.
+
+/**
+ * Renderers.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_langimport\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+use plugin_renderer_base;
+
+/**
+ * Renderer class.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class renderer extends plugin_renderer_base {
+
+    /**
+     * Defer to template.
+     *
+     * @param langimport_page $page
+     * @return string
+     */
+    public function render_langimport_page(langimport_page $page) {
+        $data = $page->export_for_template($this);
+        return parent::render_from_template('tool_langimport/langimport', $data);
+    }
+}
index c5f49da..0e98a5d 100644 (file)
@@ -124,23 +124,22 @@ if ($availablelangs = $controller->availablelangs) {
 } else {
     $remote = false;
     $availablelangs = array();
-    echo $OUTPUT->box_start();
     $a = [
         'src' => $controller->lang_pack_url(),
         'dest' => $CFG->dataroot.'/lang/',
     ];
-    print_string('downloadnotavailable', 'tool_langimport', $a);
-    echo $OUTPUT->box_end();
+    $errormessage = get_string('downloadnotavailable', 'tool_langimport', $a);
+    \core\notification::error($errormessage);
 }
 
 if ($controller->info) {
     $info = implode('<br />', $controller->info);
-    echo $OUTPUT->notification($info, 'notifysuccess');
+    \core\notification::success($info);
 }
 
 if ($controller->errors) {
     $info = implode('<br />', $controller->errors);
-    echo $OUTPUT->notification($info, 'notifyproblem');
+    \core\notification::error($info);
 }
 
 if ($missingparents) {
@@ -155,67 +154,29 @@ if ($missingparents) {
             }
         }
         $info = get_string('missinglangparent', 'tool_langimport', $a);
-        echo $OUTPUT->notification($info, 'notifyproblem');
+        \core\notification::error($info);
     }
 }
 
-echo $OUTPUT->box_start();
-
-echo html_writer::start_tag('table');
-echo html_writer::start_tag('tr');
-
-// list of installed languages
-$url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => DELETION_OF_SELECTED_LANG));
-echo html_writer::start_tag('td', array('valign' => 'top'));
-echo html_writer::start_tag('form', array('id' => 'uninstallform', 'action' => $url->out(), 'method' => 'post'));
-echo html_writer::start_tag('fieldset');
-echo html_writer::label(get_string('installedlangs', 'tool_langimport'), 'menuuninstalllang');
-echo html_writer::empty_tag('br');
-echo html_writer::select($installedlangs, 'uninstalllang[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
-echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
-echo html_writer::empty_tag('br');
-echo html_writer::empty_tag('input', array('id' => 'languninstallbutton',
-                                         'type' => 'submit',
-                                         'value' => get_string('uninstall', 'tool_langimport'))
-                            );
-echo html_writer::end_tag('fieldset');
-echo html_writer::end_tag('form');
+$uninstallurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => DELETION_OF_SELECTED_LANG));
+$updateurl = null;
 if ($remote) {
-    $url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => UPDATE_ALL_LANG));
-    echo html_writer::start_tag('form', array('id' => 'updateform', 'action' => $url->out(), 'method' => 'post'));
-    echo html_writer::tag('fieldset', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('updatelangs','tool_langimport'))));
-    echo html_writer::end_tag('form');
+    $updateurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => UPDATE_ALL_LANG));
 }
-echo html_writer::end_tag('td');
+$installurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => INSTALLATION_OF_SELECTED_LANG));
 
-// list of available languages
+// List of available languages.
 $options = array();
 foreach ($availablelangs as $alang) {
     if (!empty($alang[0]) and trim($alang[0]) !== 'en' and !$controller->is_installed_lang($alang[0], $alang[1])) {
         $options[$alang[0]] = $alang[2].' &lrm;('.$alang[0].')&lrm;';
     }
 }
-if (!empty($options)) {
-    echo html_writer::start_tag('td', array('valign' => 'top'));
-    $url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => INSTALLATION_OF_SELECTED_LANG));
-    echo html_writer::start_tag('form', array('id' => 'installform', 'action' => $url->out(), 'method' => 'post'));
-    echo html_writer::start_tag('fieldset');
-    echo html_writer::label(get_string('availablelangs','install'), 'menupack');
-    echo html_writer::empty_tag('br');
-    echo html_writer::select($options, 'pack[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
-    echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
-    echo html_writer::empty_tag('br');
-    echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('install','tool_langimport')));
-    echo html_writer::end_tag('fieldset');
-    echo html_writer::end_tag('form');
-    echo html_writer::end_tag('td');
-}
 
-echo html_writer::end_tag('tr');
-echo html_writer::end_tag('table');
-echo $OUTPUT->box_end();
+$renderable = new \tool_langimport\output\langimport_page($installedlangs, $options, $uninstallurl, $updateurl, $installurl);
+$output = $PAGE->get_renderer('tool_langimport');
+echo $output->render($renderable);
 
-$uninstallurl = new moodle_url('/admin/tool/langimport/index.php');
 $PAGE->requires->strings_for_js(array('uninstallconfirm', 'uninstall', 'selectlangs', 'noenglishuninstall'),
                                 'tool_langimport');
 $PAGE->requires->yui_module('moodle-core-languninstallconfirm',
@@ -223,4 +184,3 @@ $PAGE->requires->yui_module('moodle-core-languninstallconfirm',
                              array(array('uninstallUrl' => $uninstallurl->out()))
                             );
 echo $OUTPUT->footer();
-die();
index 42d8a69..f23c99b 100644 (file)
@@ -1,9 +1,5 @@
-#page-admin-tool-langimport-index .generalbox table {
+#page-admin-tool-langimport-index .langimport {
     margin: auto;
+    float: none;
     width: 100%;
 }
-
-#page-admin-tool-langimport-index .generalbox,
-#page-admin-tool-langimport-index .generalbox table {
-    text-align: center;
-}
diff --git a/admin/tool/langimport/templates/langimport.mustache b/admin/tool/langimport/templates/langimport.mustache
new file mode 100644 (file)
index 0000000..25dc700
--- /dev/null
@@ -0,0 +1,117 @@
+{{!
+    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/>.
+}}
+{{!
+    @template tool_langimport/langimport
+
+    Template for the language import page.
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * sesskey string The session key.
+    * uninstallurl string The URL for the uninstall action.
+    * updateurl string The URL for the update-language-packs action.
+    * installurl string The URL for the install action.
+    * installedoptions array The list of languages installed.
+    * toinstalloptions array The list of languages to be installed.
+    * caninstall boolean Flag to indicate if there are language packs that can be installed.
+
+    Example context (json):
+    {
+        "sesskey": "sesskey",
+        "uninstallurl": "#",
+        "updateurl": "#",
+        "installurl": "#",
+        "installedoptions": [
+            {
+                "value": "en",
+                "text": "English",
+                "selected": true
+            }
+        ],
+        "toinstalloptions": [
+            {
+                "value": "ja",
+                "text": "Japanese"
+            },
+            {
+                "value": "fr",
+                "text": "French"
+            },
+            {
+                "value": "es",
+                "text": "Spanish"
+            }
+        ],
+        "caninstall": true
+    }
+}}
+<div class="container-fluid langimport">
+    <div class="row row-fluid rtl-compatible">
+        <div class="col-md-{{#caninstall}}6{{/caninstall}}{{^caninstall}}12{{/caninstall}} span{{#caninstall}}6{{/caninstall}}{{^caninstall}}12{{/caninstall}} m-b-1">
+            <form id="uninstallform" action="{{uninstallurl}}" method="post">
+                <fieldset>
+                    <div class="form-group">
+                        <label for="menuuninstalllang">{{#str}}installedlangs, tool_langimport{{/str}}</label>
+                        <select size="15" multiple="multiple" id="menuuninstalllang" class="form-control input-block-level" name="uninstalllang[]">
+                            {{#installedoptions}}
+                                <option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{{text}}}‎</option>
+                            {{/installedoptions}}
+                        </select>
+                    </div>
+                    <div class="form-group">
+                        <input type="hidden" name="sesskey" value="{{sesskey}}">
+                        <input id="languninstallbutton" type="submit" value="{{#str}}uninstall, tool_langimport{{/str}}" class="btn btn-default">
+                    </div>
+                </fieldset>
+            </form>
+            {{#updateurl}}
+                <div>
+                    <form id="updateform" action="{{updateurl}}" method="post">
+                        <fieldset>
+                            <input type="submit" value="{{#str}}updatelangs, tool_langimport{{/str}}" class="btn btn-default">
+                        </fieldset>
+                    </form>
+                </div>
+            {{/updateurl}}
+        </div>
+        {{#caninstall}}
+            <div class="col-md-6 span6 m-b-1">
+                <form id="installform" action="{{installurl}}" method="post">
+                    <fieldset>
+                        <div class="form-group">
+                            <label for="menupack">{{#str}}availablelangs, install{{/str}}</label>
+                            <select size="15" multiple="multiple" class="form-control input-block-level" id="menupack" name="pack[]">
+                                {{#toinstalloptions}}
+                                    <option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{{text}}}‎</option>
+                                {{/toinstalloptions}}
+                            </select>
+                        </div>
+                        <div class="form-group">
+                            <input type="hidden" name="sesskey" value="{{sesskey}}">
+                            <input type="submit" value="{{#str}}install, tool_langimport{{/str}}" class="btn btn-default">
+                        </div>
+                    </fieldset>
+                </form>
+            </div>
+        {{/caninstall}}
+    </div>
+</div>
index 6d6f0f0..e1b9170 100644 (file)
@@ -4,7 +4,6 @@ Feature: Manage language packs
   As an administrator
   I need to be able to add, update and remove language packs
 
-
   Background:
     Given remote langimport tests are enabled
 
index bccf5f7..998a950 100644 (file)
@@ -68,7 +68,7 @@ Feature: Manage competency frameworks
     Then I should not see "Science Year-4"
     And I should not see "sc-y-4"
 
-Scenario: Edit a framework with competencies in user competency
+  Scenario: Edit a framework with competencies in user competency
     Given the following lp "frameworks" exist:
       | shortname | idnumber |
       | Science Year-5 | sc-y-5 |
@@ -98,7 +98,7 @@ Scenario: Edit a framework with competencies in user competency
     And I should see "Science Year-5 Edited"
     And I should see "sc-y-5"
 
-Scenario: Edit a framework with competencies in user competency plan
+  Scenario: Edit a framework with competencies in user competency plan
     Given the following lp "frameworks" exist:
       | shortname | idnumber |
       | Science Year-6 | sc-y-6 |
index bfaf1e0..c98314e 100644 (file)
@@ -179,7 +179,7 @@ Feature: Manage plan workflow
     And I should not see "Active"
     And I log out
 
-Scenario: Manager reopen a complete learning plan
+  Scenario: Manager reopen a complete learning plan
     Given  the following lp "plans" exist:
       | name | user | description | status | reviewer |
       | Test-Plan3 | user1 | Description of plan 3 for user 1 | complete | manager1 |
index 6a46e19..35dbd2b 100644 (file)
@@ -78,4 +78,3 @@ Feature: Manage evidence of prior learning
     Then I should see "List of evidence"
     And I should see "Evidence-6"
     And I should not see "Evidence-5"
-
index d9baedd..7343d92 100644 (file)
@@ -50,7 +50,7 @@ $PAGE->set_context($context);
 $title = get_string('backpackdetails', 'badges');
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 
 $backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id));
 $badgescache = cache::make('core', 'externalbadges');
index 0ef4f68..8437ad4 100644 (file)
@@ -89,7 +89,7 @@ $PAGE->set_context($context);
 $title = get_string('badges', 'badges');
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 
 // Include JS files for backpack support.
 badges_setup_backpack_js();
index 92cc5ad..e2f504e 100644 (file)
@@ -357,4 +357,3 @@ Feature: Award badges
     When I press "Revoke badge"
     And I follow "Course Badge"
     Then I should see "Recipients (0)"
-
index 7af21b1..de4a149 100644 (file)
@@ -60,7 +60,7 @@ Feature: The activity results block displays student scores
     And I press "Save changes"
     And I follow "Course 1"
 
-Scenario: Configure the block on a non-graded activity to show 3 high scores
+  Scenario: Configure the block on a non-graded activity to show 3 high scores
     Given I follow "Test page name"
     And I add the "Activity results" block
     When I configure the "Activity results" block
@@ -78,7 +78,7 @@ Scenario: Configure the block on a non-graded activity to show 3 high scores
     And I should see "Student 3" in the "Activity results" "block"
     And I should see "70.00" in the "Activity results" "block"
 
-Scenario: Block should select current activity by default
+  Scenario: Block should select current activity by default
     Given I follow "Test assignment 1"
     When I add the "Activity results" block
     And I configure the "Activity results" block
index def045b..f53d8ea 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block doesn't displays student scores for unconfigured block
   In order to be display student scores
   As a user
   I need to see the activity results block
index 3aa10b9..d3f5c99 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block doesn't display student scores for unsupported activity
   In order to be display student scores
   As a user
   I need to properly configure the activity results block
index 4a2a8bc..620aac1 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays student high scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index 86dee32..d121c97 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores as scales
+Feature: The activity results block displays students high scores in group as scales
   In order to be display student scores as scales
   As a user
   I need to see the activity results block
index 536a00e..6b9c972 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores as scales
+Feature: The activity results block displays student in group high scores as scales
   In order to be display student scores as scales
   As a user
   I need to see the activity results block
index c764e80..0c1ccdd 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays student in separate groups scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index bf10d79..0e64d05 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays student in visible groups scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index a1496c6..e2c8729 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays student low scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index 587f863..5068a7b 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores as scales
+Feature: The activity results block displays student low scores as scales
   In order to be display student scores as scales
   As a user
   I need to see the activity results block
index f43348e..30602ff 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores as scales
+Feature: The activity results block displays students in groups low scores as scales
   In order to be display student scores as scales
   As a user
   I need to see the activity results block
@@ -146,4 +146,3 @@ Feature: The activity results block displays student scores as scales
     And I should see "User" in the "Activity results" "block"
     And I should see "Good" in the "Activity results" "block"
     And I should see "Average" in the "Activity results" "block"
-
index 640517e..5d73692 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays students in separate groups scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index 2010dcd..e137f92 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_activity_results
-Feature: The activity results block displays student scores
+Feature: The activity results block displays student in visible groups low scores
   In order to be display student scores
   As a user
   I need to see the activity results block
index f45f62f..76ceb37 100644 (file)
@@ -1,8 +1,8 @@
 @block @block_blog_menu
-Feature: Enable Block blog menu in a course
-  In order to enable the blog menu in a course
-  As a teacher
-  I can add blog menu block to a course
+Feature: Students can use block blog menu in a course
+  In order students to use the blog menu in a course
+  As a student
+  I view blog menu block in a course
 
   Background:
     Given the following "users" exist:
index ea2bcd1..ceb1898 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_calendar_upcoming
-Feature: View a site event on the dashboard
+Feature: View a upcoming site event on the dashboard
   In order to view a site event
   As a student
   I can view the event in the upcoming events block
index 532950d..7d4c3f6 100644 (file)
@@ -52,7 +52,6 @@ Feature: Enable Block Completion in a course using manual completion by others
     And I follow "More details"
     And I should see "Yes" in the "Marked complete by Teacher" "table_row"
 
-
   Scenario: Add the block to a the course and require multiple roles to mark a student complete.
     Given I log in as "teacher1"
     And I follow "Course 1"
index 238591f..c91c551 100644 (file)
@@ -91,4 +91,3 @@ Feature: View the quiz being due
     And I should not see "Quiz 1B Past deadline" in the "Course overview" "block"
     And I should not see "Quiz 1D Future deadline" in the "Course overview" "block"
     And I should not see "Quiz 2A Future deadline" in the "Course overview" "block"
-
index fc6f19c..db31b91 100644 (file)
@@ -4,24 +4,24 @@ Feature: Random glossary entry block can be added to the frontpage
   As a teacher
   I can add the random glossary entry to the frontpage
 
-Scenario: Admin can add random glossary block to the frontpage
-  Given the following "activities" exist:
-    | activity   | name             | intro                          | course               | idnumber  |
-    | glossary   | Tips and Tricks  | Frontpage glossary description | Acceptance test site | glossary0 |
-  And I log in as "admin"
-  And I am on site homepage
-  And I turn editing mode on
-  And I add the "Random glossary entry" block
-  And I configure the "block_glossary_random" block
-  And I set the following fields to these values:
-    | Title                           | Tip of the day  |
-    | Take entries from this glossary | Tips and Tricks |
-  And I press "Save changes"
-  And I click on "Add a new entry" "link" in the "Tip of the day" "block"
-  And I set the following fields to these values:
-    | Concept    | Never come late               |
-    | Definition | Come in time for your classes |
-  And I press "Save changes"
-  When I log out
-  Then I should see "Never come late" in the "Tip of the day" "block"
-  And I should see "Come in time for your classes" in the "Tip of the day" "block"
+  Scenario: Admin can add random glossary block to the frontpage
+    Given the following "activities" exist:
+      | activity   | name             | intro                          | course               | idnumber  |
+      | glossary   | Tips and Tricks  | Frontpage glossary description | Acceptance test site | glossary0 |
+    And I log in as "admin"
+    And I am on site homepage
+    And I turn editing mode on
+    And I add the "Random glossary entry" block
+    And I configure the "block_glossary_random" block
+    And I set the following fields to these values:
+      | Title                           | Tip of the day  |
+      | Take entries from this glossary | Tips and Tricks |
+    And I press "Save changes"
+    And I click on "Add a new entry" "link" in the "Tip of the day" "block"
+    And I set the following fields to these values:
+      | Concept    | Never come late               |
+      | Definition | Come in time for your classes |
+    And I press "Save changes"
+    When I log out
+    Then I should see "Never come late" in the "Tip of the day" "block"
+    And I should see "Come in time for your classes" in the "Tip of the day" "block"
index 93b58de..a6cad0b 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_html
-Feature: Adding and configuring HTML blocks
+Feature: Adding and configuring multiple HTML blocks
   In order to have one or multiple HTML blocks on a page
   As admin
   I need to be able to create, configure and change HTML blocks
index ecde2a0..7f88d76 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_online_users
-Feature: The online users block allow you to see who is currently online
+Feature: The online users block allow you to see who is currently online on dashboard
   In order to use the online users block on the dashboard
   As a user
   I can view the online users block on my dashboard
index 3e4b56d..5909b1c 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_online_users
-Feature: The online users block allow you to see who is currently online
+Feature: The online users block allow you to see who is currently online on frontpage
   In order to enable the online users block on the front page page
   As an admin
   I can add the online users block to the front page page
index aaf59ff..d857871 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_private_files @_file_upload @javascript
-Feature: The private files block allows users to store files privately in moodle
+Feature: The private files block allows users to store files privately in moodle on activity page
   In order to store a private file in moodle
   As a teacher
   I can upload the file to my private files area using the private files block in an activity
index 43e7b8c..b56c15b 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_private_files @_file_upload @javascript
-Feature: The private files block allows users to store files privately in moodle
+Feature: The private files block allows users to store files privately in moodle on course page
   In order to store a private file in moodle
   As a teacher
   I can upload the file to my private files area using the private files block in a course
index 990cd96..3b6eb5c 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_private_files @_file_upload @javascript
-Feature: The private files block allows users to store files privately in moodle
+Feature: The private files block allows users to store files privately in moodle on dashboard
   In order to store a private file in moodle
   As a user
   I can upload the file to my private files area using the private files block on the dashboard
index ec611bb..7816060 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_private_files @_file_upload
-Feature: The private files block allows users to store files privately in moodle
+Feature: The private files block allows users to store files privately in moodle on front page.
   In order to store a private file in moodle
   As a teacher
   I can upload the file to my private files area using the private files block from the front page
index a52b9ad..dedc8bc 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_search_forums @mod_forum
-Feature: The search forums block allows users to search for forum posts
+Feature: The search forums block allows users to search for forum posts on course page
   In order to search for a forum post
   As a user
   I can use the search forums block
index 4d2aa52..1f76d15 100644 (file)
@@ -1,5 +1,5 @@
 @block @block_search_forums @mod_forum
-Feature: The search forums block allows users to search for forum posts
+Feature: The search forums block allows users to search for forum posts on frontpage
   In order to search for a forum post
   As an administrator
   I can add the search forums block
index 038a966..f43f6fd 100644 (file)
@@ -27,7 +27,6 @@ Feature: The section links block allows users to quickly navigate around a moodl
       | id_coursedisplay | Show one section per page |
     And I press "Save and display"
 
-
   Scenario: Add the section links block to a course.
     Given I add the "Section links" block
     And I turn editing mode off
index d41e9de..950577b 100644 (file)
@@ -48,4 +48,3 @@ Feature: Delete a blog entry
     And I press "Cancel"
     And I should see "Blog post one"
     And I should see "Blog post two"
-
index 7a0adc6..3c5bd42 100644 (file)
@@ -213,7 +213,7 @@ class cache implements cache_loader {
         $this->definition = $definition;
         $this->store = $store;
         $this->storetype = get_class($store);
-        $this->perfdebug = !empty($CFG->perfdebug);
+        $this->perfdebug = (!empty($CFG->perfdebug) and $CFG->perfdebug > 7);
         if ($loader instanceof cache_loader) {
             $this->loader = $loader;
             // Mark the loader as a sub (chained) loader.
index 537cbef..8da4f1e 100644 (file)
@@ -48,5 +48,11 @@ class cachestore_redis_addinstance_form extends cachestore_addinstance_form {
         $form->setType('prefix', PARAM_TEXT); // We set to text but we have a rule to limit to alphanumext.
         $form->addHelpButton('prefix', 'prefix', 'cachestore_redis');
         $form->addRule('prefix', get_string('prefixinvalid', 'cachestore_redis'), 'regex', '#^[a-zA-Z0-9\-_]+$#');
+
+        $serializeroptions = cachestore_redis::config_get_serializer_options();
+        $form->addElement('select', 'serializer', get_string('useserializer', 'cachestore_redis'), $serializeroptions);
+        $form->addHelpButton('serializer', 'useserializer', 'cachestore_redis');
+        $form->setDefault('serializer', Redis::SERIALIZER_PHP);
+        $form->setType('serializer', PARAM_INT);
     }
 }
\ No newline at end of file
index e51e19f..a44a156 100644 (file)
@@ -30,7 +30,15 @@ $string['prefix_help'] = 'This prefix is used for all key names on the Redis ser
 * If you only have one Moodle instance using this server, you can leave this value default.
 * Due to key length restrictions, a maximum of 5 characters is permitted.';
 $string['prefixinvalid'] = 'Invalid prefix. You can only use a-z A-Z 0-9-_.';
+$string['serializer_igbinary'] = 'The igbinary serializer.';
+$string['serializer_php'] = 'The default PHP serializer.';
+$string['server'] = 'Server';
+$string['server_help'] = 'This sets the hostname or IP address of the Redis server to use.';
 $string['test_server'] = 'Test server';
 $string['test_server_desc'] = 'Redis server to use for testing.';
-$string['server'] = 'Server';
-$string['server_help'] = 'This sets the hostname or IP address of the Redis server to use.';
\ No newline at end of file
+$string['test_serializer'] = 'Serializer';
+$string['test_serializer_desc'] = 'Serializer to use for testing.';
+$string['useserializer'] = 'Use serializer';
+$string['useserializer_help'] = 'Specifies the serializer to use for serializing.
+The valid serializers are Redis::SERIALIZER_PHP or Redis::SERIALIZER_IGBINARY.
+The latter is supported only when phpredis is configured with --enable-redis-igbinary option and the igbinary extension is loaded.';
index 16ad4c2..fd19709 100644 (file)
@@ -73,6 +73,13 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
      */
     protected $redis;
 
+    /**
+     * Serializer for this store.
+     *
+     * @var int
+     */
+    protected $serializer = Redis::SERIALIZER_PHP;
+
     /**
      * Determines if the requirements for this type of store are met.
      *
@@ -124,6 +131,9 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
         if (!array_key_exists('server', $configuration) || empty($configuration['server'])) {
             return;
         }
+        if (array_key_exists('serializer', $configuration)) {
+            $this->serializer = (int)$configuration['serializer'];
+        }
         $prefix = !empty($configuration['prefix']) ? $configuration['prefix'] : '';
         $this->redis = $this->new_redis($configuration['server'], $prefix);
     }
@@ -145,7 +155,7 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
             $port = $serverconf[1];
         }
         if ($redis->connect($server, $port)) {
-            $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
+            $redis->setOption(Redis::OPT_SERIALIZER, $this->serializer);
             if (!empty($prefix)) {
                 $redis->setOption(Redis::OPT_PREFIX, $prefix);
             }
@@ -426,7 +436,11 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
      * @return array
      */
     public static function config_get_configuration_array($data) {
-        return array('server' => $data->server, 'prefix' => $data->prefix);
+        return array(
+            'server' => $data->server,
+            'prefix' => $data->prefix,
+            'serializer' => $data->serializer
+        );
     }
 
     /**
@@ -440,6 +454,9 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
         $data = array();
         $data['server'] = $config['server'];
         $data['prefix'] = !empty($config['prefix']) ? $config['prefix'] : '';
+        if (!empty($config['serializer'])) {
+            $data['serializer'] = $config['serializer'];
+        }
         $editform->set_data($data);
     }
 
@@ -458,7 +475,11 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
         if (empty($config->test_server)) {
             return false;
         }
-        $cache = new cachestore_redis('Redis test', ['server' => $config->test_server]);
+        $configuration = array('server' => $config->test_server);
+        if (!empty($config->test_serializer)) {
+            $configuration['serializer'] = $config->test_serializer;
+        }
+        $cache = new cachestore_redis('Redis test', $configuration);
         $cache->initialise($definition);
 
         return $cache;
@@ -491,4 +512,19 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
     public static function ready_to_be_used_for_testing() {
         return defined('TEST_CACHESTORE_REDIS_TESTSERVERS');
     }
+
+    /**
+     * Gets an array of options to use as the serialiser.
+     * @return array
+     */
+    public static function config_get_serializer_options() {
+        $options = array(
+            Redis::SERIALIZER_PHP => get_string('serializer_php', 'cachestore_redis')
+        );
+
+        if (defined('Redis::SERIALIZER_IGBINARY')) {
+            $options[Redis::SERIALIZER_IGBINARY] = get_string('serializer_igbinary', 'cachestore_redis');
+        }
+        return $options;
+    }
 }
index 1d10cf8..3300b23 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $settings->add(
-  new admin_setting_configtext(
-    'cachestore_redis/test_server',
-    get_string('test_server', 'cachestore_redis'),
-    get_string('test_server_desc', 'cachestore_redis'),
-    '',
-    PARAM_TEXT,
-    16
-  )
+    new admin_setting_configtext(
+        'cachestore_redis/test_server',
+        get_string('test_server', 'cachestore_redis'),
+        get_string('test_server_desc', 'cachestore_redis'),
+        '',
+        PARAM_TEXT,
+        16
+    )
 );
+
+if (class_exists('Redis')) { // Only if Redis is available.
+
+    $options = array(Redis::SERIALIZER_PHP => get_string('serializer_php', 'cachestore_redis'));
+
+    if (defined('Redis::SERIALIZER_IGBINARY')) {
+        $options[Redis::SERIALIZER_IGBINARY] = get_string('serializer_igbinary', 'cachestore_redis');
+    }
+
+    $settings->add(new admin_setting_configselect(
+            'cachestore_redis/test_serializer',
+            get_string('test_serializer', 'cachestore_redis'),
+            get_string('test_serializer_desc', 'cachestore_redis'),
+            0,
+            $options
+        )
+    );
+}
index 965a61b..ac6bfed 100644 (file)
@@ -2172,4 +2172,57 @@ class core_cache_testcase extends advanced_testcase {
         $this->assertEquals(0, $endstats[$requestid]['stores']['cachestore_static']['sets'] -
             $startstats[$requestid]['stores']['cachestore_static']['sets']);
     }
+
+    public function test_performance_debug_off() {
+        global $CFG;
+        $this->resetAfterTest(true);
+        $CFG->perfdebug = 7;
+
+        $instance = cache_config_testing::instance();
+        $applicationid = 'phpunit/applicationperfoff';
+        $instance->phpunit_add_definition($applicationid, array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'applicationperfoff'
+        ));
+        $sessionid = 'phpunit/sessionperfoff';
+        $instance->phpunit_add_definition($sessionid, array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'sessionperfoff'
+        ));
+        $requestid = 'phpunit/requestperfoff';
+        $instance->phpunit_add_definition($requestid, array(
+            'mode' => cache_store::MODE_REQUEST,
+            'component' => 'phpunit',
+            'area' => 'requestperfoff'
+        ));
+
+        $application = cache::make('phpunit', 'applicationperfoff');
+        $session = cache::make('phpunit', 'sessionperfoff');
+        $request = cache::make('phpunit', 'requestperfoff');
+
+        // Check that no stats are recorded for these definitions yet.
+        $stats = cache_helper::get_stats();
+        $this->assertArrayNotHasKey($applicationid, $stats);
+        $this->assertArrayNotHasKey($sessionid, $stats);
+        $this->assertArrayNotHasKey($requestid, $stats);
+
+        // Trigger cache misses, cache sets and cache hits.
+        $this->assertFalse($application->get('missMe'));
+        $this->assertTrue($application->set('setMe', 1));
+        $this->assertEquals(1, $application->get('setMe'));
+        $this->assertFalse($session->get('missMe'));
+        $this->assertTrue($session->set('setMe', 3));
+        $this->assertEquals(3, $session->get('setMe'));
+        $this->assertFalse($request->get('missMe'));
+        $this->assertTrue($request->set('setMe', 4));
+        $this->assertEquals(4, $request->get('setMe'));
+
+        // Check that no stats are being recorded for these definitions.
+        $endstats = cache_helper::get_stats();
+        $this->assertArrayNotHasKey($applicationid, $endstats);
+        $this->assertArrayNotHasKey($sessionid, $endstats);
+        $this->assertArrayNotHasKey($requestid, $endstats);
+    }
 }
index d18eae3..c026cfe 100644 (file)
@@ -111,4 +111,3 @@ Feature: Perform basic calendar functionality
       | Description | Wait, this event isn't that great. |
     And I press "Save changes"
     And I should see "Mediocre event"
-
index 899ec2c..e913193 100644 (file)
@@ -125,4 +125,3 @@ Feature: Access visible and hidden cohorts
     And the "Select members from cohort" select box should not contain "Cohort in category 2"
     And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
     And the "Select members from cohort" select box should not contain "System empty cohort"
-
index eb759d8..7c60ee0 100644 (file)
@@ -774,6 +774,10 @@ M.course_dndupload = {
                                 resel.li.outerHTML = unescape(resel.li.outerHTML);
                             }
                             self.add_editing(result.elementid);
+                            // Fire the content updated event.
+                            require(['core/event', 'jquery'], function(event, $) {
+                                event.notifyFilterContentUpdated($(result.fullcontent));
+                            });
                         } else {
                             // Error - remove the dummy element
                             resel.parent.removeChild(resel.li);
index 73277e0..4a57ae5 100644 (file)
@@ -2398,6 +2398,16 @@ class core_course_external extends external_api {
                 'timemodified' => new external_value(PARAM_INT, 'Last time  the course was updated', VALUE_OPTIONAL),
                 'requested' => new external_value(PARAM_INT, 'If is a requested course', VALUE_OPTIONAL),
                 'cacherev' => new external_value(PARAM_INT, 'Cache revision number', VALUE_OPTIONAL),
+                'filters' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'filter'  => new external_value(PARAM_PLUGIN, 'Filter plugin name'),
+                            'localstate' => new external_value(PARAM_INT, 'Filter state: 1 for on, -1 for off, 0 if inherit'),
+                            'inheritedstate' => new external_value(PARAM_INT, '1 or 0 to use when localstate is set to inherit'),
+                        )
+                    ),
+                    'Course filters', VALUE_OPTIONAL
+                ),
             );
             $coursestructure = array_merge($coursestructure, $extra);
         }
@@ -2923,6 +2933,7 @@ class core_course_external extends external_api {
     public static function get_courses_by_field($field = '', $value = '') {
         global $DB, $CFG;
         require_once($CFG->libdir . '/coursecatlib.php');
+        require_once($CFG->libdir . '/filterlib.php');
 
         $params = self::validate_parameters(self::get_courses_by_field_parameters(),
             array(
@@ -2985,6 +2996,9 @@ class core_course_external extends external_api {
                 'groupmode', 'groupmodeforce', 'defaultgroupingid', 'enablecompletion', 'completionnotify', 'lang', 'theme',
                 'sortorder', 'marker');
 
+            // Course filters.
+            $coursesdata[$course->id]['filters'] = filter_get_available_in_context($context);
+
             // Information for managers only.
             if ($canupdatecourse) {
                 $managerfields = array('idnumber', 'legacyfiles', 'calendartype', 'timecreated', 'timemodified', 'requested',
index 2f474b2..4c83c5a 100644 (file)
@@ -4,7 +4,7 @@ Feature: Change number of discussions displayed
   As a teacher
   I need to edit the course and change the number of sections displayed.
 
-Background:
+  Background:
     Given the following "users" exist:
       | username | firstname | lastname | email |
       | teacher1 | Teacher | 1 | teacher1@example.com |
@@ -96,28 +96,28 @@ Background:
     And I wait to be redirected
     And I follow "Course 1"
 
-Scenario: When number of discussions is decreased fewer discussions appear
+  Scenario: When number of discussions is decreased fewer discussions appear
     Given I navigate to "Edit settings" in current page administration
     And I set the following fields to these values:
-    | numdiscussions | 5 |
+      | numdiscussions | 5 |
     When I press "Save and display"
     Then I should see "This is forum post one"
     And I should see "This is forum post five"
     And I should not see "This is forum post six"
 
-Scenario: When number of discussions is decreased to less than 1 only 1 discussion should appear
+  Scenario: When number of discussions is decreased to less than 1 only 1 discussion should appear
     Given I navigate to "Edit settings" in current page administration
     And I set the following fields to these values:
-    | numdiscussions | -1 |
+      | numdiscussions | -1 |
     When I press "Save and display"
     Then I should see "This is forum post one"
     And I should not see "This is forum post two"
     And I should not see "This is forum post ten"
 
-Scenario: When number of discussions is increased more discussions appear
+  Scenario: When number of discussions is increased more discussions appear
     Given I navigate to "Edit settings" in current page administration
     And I set the following fields to these values:
-    | numdiscussions | 9 |
+      | numdiscussions | 9 |
     When I press "Save and display"
     Then I should see "This is forum post one"
     And I should see "This is forum post five"
index 1bb7129..042094c 100644 (file)
@@ -255,64 +255,64 @@ Feature: We can change the visibility of categories in the management interface.
     And course in management listing should be dimmed "C2"
     And course in management listing should be visible "C3"
 
-    @javascript @_cross_browser
-    Scenario: Test courses are hidden when selected category parent is hidden.
-      Given the following "categories" exist:
-        | name | category | idnumber |
-        | Cat 1 | 0 | CAT1 |
-        | Cat 2 | CAT1 | CAT2 |
-        | Cat 3 | CAT2 | CAT3 |
-      And the following "courses" exist:
-        | category | fullname | shortname | idnumber |
-        | CAT3 | Course 1 | Course 1 | C1 |
+  @javascript @_cross_browser
+  Scenario: Test courses are hidden when selected category parent is hidden.
+    Given the following "categories" exist:
+      | name | category | idnumber |
+      | Cat 1 | 0 | CAT1 |
+      | Cat 2 | CAT1 | CAT2 |
+      | Cat 3 | CAT2 | CAT3 |
+    And the following "courses" exist:
+      | category | fullname | shortname | idnumber |
+      | CAT3 | Course 1 | Course 1 | C1 |
 
-      And I log in as "admin"
-      And I go to the courses management page
-      And I start watching to see if a new page loads
-      And I should see the "Course categories and courses" management page
-      And I click on category "Cat 1" in the management interface
-      And a new page should have loaded since I started watching
-      And I start watching to see if a new page loads
-      And I should see the "Course categories and courses" management page
-      And I click on category "Cat 2" in the management interface
-      And a new page should have loaded since I started watching
-      And I start watching to see if a new page loads
-      And I should see the "Course categories and courses" management page
-      And I click on category "Cat 3" in the management interface
-      And a new page should have loaded since I started watching
-      And I start watching to see if a new page loads
-      And I should see the "Course categories and courses" management page
-      And category in management listing should be visible "CAT1"
-      And category in management listing should be visible "CAT2"
-      And category in management listing should be visible "CAT3"
-      And course in management listing should be visible "C1"
-      And I toggle visibility of category "CAT1" in management listing
-      And a new page should not have loaded since I started watching
-      And category in management listing should be dimmed "CAT1"
-      And category in management listing should be dimmed "CAT2"
-      And category in management listing should be dimmed "CAT3"
-      And course in management listing should be dimmed "C1"
-      And I toggle visibility of category "CAT1" in management listing
-      And a new page should not have loaded since I started watching
-      And category in management listing should be visible "CAT1"
-      And category in management listing should be visible "CAT2"
-      And category in management listing should be visible "CAT3"
-      And course in management listing should be visible "C1"
-      And I toggle visibility of course "C1" in management listing
-      And a new page should not have loaded since I started watching
-      And category in management listing should be visible "CAT1"
-      And category in management listing should be visible "CAT2"
-      And category in management listing should be visible "CAT3"
-      And course in management listing should be dimmed "C1"
-      And I toggle visibility of category "CAT1" in management listing
-      And a new page should not have loaded since I started watching
-      And category in management listing should be dimmed "CAT1"
-      And category in management listing should be dimmed "CAT2"
-      And category in management listing should be dimmed "CAT3"
-      And course in management listing should be dimmed "C1"
-      And I toggle visibility of category "CAT1" in management listing
-      And a new page should not have loaded since I started watching
-      And category in management listing should be visible "CAT1"
-      And category in management listing should be visible "CAT2"
-      And category in management listing should be visible "CAT3"
-      And course in management listing should be dimmed "C1"
+    And I log in as "admin"
+    And I go to the courses management page
+    And I start watching to see if a new page loads
+    And I should see the "Course categories and courses" management page
+    And I click on category "Cat 1" in the management interface
+    And a new page should have loaded since I started watching
+    And I start watching to see if a new page loads
+    And I should see the "Course categories and courses" management page
+    And I click on category "Cat 2" in the management interface
+    And a new page should have loaded since I started watching
+    And I start watching to see if a new page loads
+    And I should see the "Course categories and courses" management page
+    And I click on category "Cat 3" in the management interface
+    And a new page should have loaded since I started watching
+    And I start watching to see if a new page loads
+    And I should see the "Course categories and courses" management page
+    And category in management listing should be visible "CAT1"
+    And category in management listing should be visible "CAT2"
+    And category in management listing should be visible "CAT3"
+    And course in management listing should be visible "C1"
+    And I toggle visibility of category "CAT1" in management listing
+    And a new page should not have loaded since I started watching
+    And category in management listing should be dimmed "CAT1"
+    And category in management listing should be dimmed "CAT2"
+    And category in management listing should be dimmed "CAT3"
+    And course in management listing should be dimmed "C1"
+    And I toggle visibility of category "CAT1" in management listing
+    And a new page should not have loaded since I started watching
+    And category in management listing should be visible "CAT1"
+    And category in management listing should be visible "CAT2"
+    And category in management listing should be visible "CAT3"
+    And course in management listing should be visible "C1"
+    And I toggle visibility of course "C1" in management listing
+    And a new page should not have loaded since I started watching
+    And category in management listing should be visible "CAT1"
+    And category in management listing should be visible "CAT2"
+    And category in management listing should be visible "CAT3"
+    And course in management listing should be dimmed "C1"
+    And I toggle visibility of category "CAT1" in management listing
+    And a new page should not have loaded since I started watching
+    And category in management listing should be dimmed "CAT1"
+    And category in management listing should be dimmed "CAT2"
+    And category in management listing should be dimmed "CAT3"
+    And course in management listing should be dimmed "C1"
+    And I toggle visibility of category "CAT1" in management listing
+    And a new page should not have loaded since I started watching
+    And category in management listing should be visible "CAT1"
+    And category in management listing should be visible "CAT2"
+    And category in management listing should be visible "CAT3"
+    And course in management listing should be dimmed "C1"
index 24bfaad..5dfda56 100644 (file)
@@ -5,12 +5,11 @@ Feature: Courses can be searched for and moved in bulk.
   I need to be able to search courses in bulk and move them around
 
   Background:
-     Given the following "categories" exist:
+    Given the following "categories" exist:
       | name | category | idnumber |
       | Science | 0 | SCI |
       | English | 0 | ENG |
       | Miscellaneous | 0 | MISC |
-
     And the following "courses" exist:
       | fullname | shortname | category |
       | Biology Y1 | BIO1 | MISC |
index 07333d1..284a59d 100644 (file)
@@ -48,4 +48,3 @@ Feature: Force group mode in a course
     And I press "Save and display"
     Then "//a/child::img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should not exist
     And "//img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should not exist
-
index 9730e53..14194c0 100644 (file)
@@ -28,40 +28,40 @@ Feature: View subfolders in a course in-line
     And I click on "button.fp-dlg-butcreate" "css_element" in the "div.fp-mkdir-dlg" "css_element"
     And I press "Save changes"
 
-    @javascript
-    Scenario: Add a folder with two subfolders - view on separate page
-      Given I follow "Course 1"
-      And I should not see "Test subfolder 1"
-      And I follow "Test folder"
-      And I should see "Test subfolder 1"
-      And I press "Edit"
-      And I press "Create folder"
-      And I set the field "New folder name" to "Test subfolder 2"
-      And I click on "button.fp-dlg-butcreate" "css_element" in the "div.fp-mkdir-dlg" "css_element"
-      And I press "Save changes"
-      When I follow "Course 1"
-      Then I should not see "Test subfolder 2"
-      And I follow "Test folder"
-      And I should see "Test subfolder 2"
+  @javascript
+  Scenario: Add a folder with two subfolders - view on separate page
+    Given I follow "Course 1"
+    And I should not see "Test subfolder 1"
+    And I follow "Test folder"
+    And I should see "Test subfolder 1"
+    And I press "Edit"
+    And I press "Create folder"
+    And I set the field "New folder name" to "Test subfolder 2"
+    And I click on "button.fp-dlg-butcreate" "css_element" in the "div.fp-mkdir-dlg" "css_element"
+    And I press "Save changes"
+    When I follow "Course 1"
+    Then I should not see "Test subfolder 2"
+    And I follow "Test folder"
+    And I should see "Test subfolder 2"
 
-    @javascript
-    Scenario: Make the subfolders viewable inline on the course page
-      Given I press "Edit"
-      And I click on "div.fp-filename" "css_element" in the "div.fp-filename-field" "css_element"
-      And I press "Create folder"
-      And I set the field "New folder name" to "Test sub subfolder"
-      And I click on "button.fp-dlg-butcreate" "css_element" in the "div.fp-mkdir-dlg" "css_element"
-      And I press "Save changes"
-      And I should see "Test sub subfolder"
-      And I navigate to "Edit settings" in current page administration
-      And I set the field "Display folder contents" to "Inline on a course page"
-      And I set the field "Show subfolders expanded" to ""
-      And I press "Save and return to course"
-      And I should see "Test subfolder 1"
-      And I should not see "Test sub subfolder"
-      And I open "Test folder" actions menu
-      When I click on "Edit settings" "link" in the "Test folder" activity
-      And I set the field "Show subfolders expanded" to "1"
-      And I press "Save and return to course"
-      Then I should see "Test subfolder 1"
-      And I should see "Test sub subfolder"
+  @javascript
+  Scenario: Make the subfolders viewable inline on the course page
+    Given I press "Edit"
+    And I click on "div.fp-filename" "css_element" in the "div.fp-filename-field" "css_element"
+    And I press "Create folder"
+    And I set the field "New folder name" to "Test sub subfolder"
+    And I click on "button.fp-dlg-butcreate" "css_element" in the "div.fp-mkdir-dlg" "css_element"
+    And I press "Save changes"
+    And I should see "Test sub subfolder"
+    And I navigate to "Edit settings" in current page administration
+    And I set the field "Display folder contents" to "Inline on a course page"
+    And I set the field "Show subfolders expanded" to ""
+    And I press "Save and return to course"
+    And I should see "Test subfolder 1"
+    And I should not see "Test sub subfolder"
+    And I open "Test folder" actions menu
+    When I click on "Edit settings" "link" in the "Test folder" activity
+    And I set the field "Show subfolders expanded" to "1"
+    And I press "Save and return to course"
+    Then I should see "Test subfolder 1"
+    And I should see "Test sub subfolder"
index b6a9045..e67ec73 100644 (file)
@@ -2019,7 +2019,7 @@ class core_course_courselib_testcase extends advanced_testcase {
 
         // Create the course with sections.
         $course = $this->getDataGenerator()->create_course(array('numsections' => 10), array('createsections' => true));
-        $sections = $DB->get_records('course_sections', array('course' => $course->id));
+        $sections = $DB->get_records('course_sections', array('course' => $course->id), 'section');
         $coursecontext = context_course::instance($course->id);
         $section = array_pop($sections);
         course_delete_section($course, $section);
index 70d25af..7d732b0 100644 (file)
@@ -1976,16 +1976,16 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(3, $result['courses']);
         // Expect to receive all the fields.
-        $this->assertCount(35, $result['courses'][0]);
-        $this->assertCount(35, $result['courses'][1]);
-        $this->assertCount(35, $result['courses'][2]);
+        $this->assertCount(36, $result['courses'][0]);
+        $this->assertCount(36, $result['courses'][1]);
+        $this->assertCount(36, $result['courses'][2]);
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
         $this->assertEquals($course1->id, $result['courses'][0]['id']);
         // Expect to receive all the fields.
-        $this->assertCount(35, $result['courses'][0]);
+        $this->assertCount(36, $result['courses'][0]);
 
         $result = core_course_external::get_courses_by_field('id', $course2->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
@@ -1996,6 +1996,10 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
 
+        // Check default filters.
+        $this->assertCount(3, $result['courses'][0]['filters']);
+        $this->assertCount(3, $result['courses'][1]['filters']);
+
         $result = core_course_external::get_courses_by_field('category', $category1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
@@ -2015,20 +2019,34 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(0, $result['courses']);
 
+        // Change filter value.
+        filter_set_local_state('mediaplugin', context_course::instance($course1->id)->id, TEXTFILTER_OFF);
+
         self::setUser($student1);
         // All visible courses  (including front page) for normal student.
         $result = core_course_external::get_courses_by_field();
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
-        $this->assertCount(28, $result['courses'][0]);
-        $this->assertCount(28, $result['courses'][1]);
+        $this->assertCount(29, $result['courses'][0]);
+        $this->assertCount(29, $result['courses'][1]);
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
         $this->assertEquals($course1->id, $result['courses'][0]['id']);
         // Expect to receive all the files that a student can see.
-        $this->assertCount(28, $result['courses'][0]);
+        $this->assertCount(29, $result['courses'][0]);
+
+        // Check default filters.
+        $filters = $result['courses'][0]['filters'];
+        $this->assertCount(3, $filters);
+        $found = false;
+        foreach ($filters as $filter) {
+            if ($filter['filter'] == 'mediaplugin' and $filter['localstate'] == TEXTFILTER_OFF) {
+                $found = true;
+            }
+        }
+        $this->assertTrue($found);
 
         // Course 2 is not visible.
         $result = core_course_external::get_courses_by_field('id', $course2->id);
@@ -2062,7 +2080,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = core_course_external::get_courses_by_field();
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
-        $this->assertCount(28, $result['courses'][0]);  // Site course.
+        $this->assertCount(29, $result['courses'][0]);  // Site course.
         $this->assertCount(12, $result['courses'][1]);  // Only public information, not enrolled.
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
index 047e0be..b38361f 100644 (file)
@@ -1,6 +1,10 @@
 This files describes API changes in /course/*,
 information provided here is intended especially for developers.
 
+=== 3.3 ===
+
+ * External function core_course_external::get_courses_by_field now returns the course filters list and status.
+
 === 3.2 ===
 
  * External function core_course_external::get_course_contents now returns the section's number in the course (new section field).
index 03e2e38..0ed9a61 100644 (file)
@@ -4,7 +4,6 @@ Feature: Add a new custom file type
   As an admin
   I need to add a new custom file type
 
-
   @javascript
   Scenario: Add custom file type
     Given the following "courses" exist:
index e274a36..dddab82 100644 (file)
@@ -4,7 +4,6 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
   As a teacher
   I need to be able to update and verify grades
 
-
   Background:
     Given the following "courses" exist:
       | fullname | shortname | category | groupmode |
index c0bebe6..3fc9563 100644 (file)
@@ -8,10 +8,10 @@ Feature: We can use the user report
       | fullname | shortname | category |
       | Course 1 | C1 | 0 |
 
-    Scenario: Verify we can view a user grade report with no users enrolled.
-      Given I log in as "admin"
-      And I am on site homepage
-      And I follow "Course 1"
-      And I navigate to "View > User report" in the course gradebook
-      And I select "All users (0)" from the "Select all or one user" singleselect
-      Then I should see "No students enrolled in this course yet"
+  Scenario: Verify we can view a user grade report with no users enrolled.
+    Given I log in as "admin"
+    And I am on site homepage
+    And I follow "Course 1"
+    And I navigate to "View > User report" in the course gradebook
+    And I select "All users (0)" from the "Select all or one user" singleselect
+    Then I should see "No students enrolled in this course yet"
index 4a1bbe9..bc1f2ea 100644 (file)
@@ -301,16 +301,4 @@ class behat_grade extends behat_base {
 
         $this->select_in_gradebook_tabs($gradepath);
     }
-
-    /**
-     * Navigates to the course gradebook and selects a specified item from the grade navigation tabs.
-     *
-     * @todo MDL-57282 deprecate in Moodle 3.3
-     *
-     * @Given /^I go to "(?P<gradepath_string>(?:[^"]|\\")*)" in the course gradebook$/
-     * @param string $gradepath
-     */
-    public function i_go_to_in_the_course_gradebook($gradepath) {
-        $this->execute('behat_grade::i_navigate_to_in_the_course_gradebook', $gradepath);
-    }
 }
index a8ecfae..5704689 100644 (file)
@@ -52,7 +52,7 @@ Feature: Calculated grade items can be used in the gradebook
 
   @javascript
   Scenario: Changing max grade for a category item with a calculation that has existing grades will display the same points with the new max grade values immediately.
-  Given I press "Add category"
+    Given I press "Add category"
     And I set the following fields to these values:
       | Category name | Calc cat |
     And I press "Save changes"
index fa38d4a..ef381aa 100644 (file)
@@ -1,5 +1,5 @@
 @core_grades
-Feature: Editing a grade item
+Feature: Grade item validation
   In order to ensure validation is provided to the teacher
   As a teacher
   I need to know why I can not add/edit values on the grade item form
index 072c32d..8ec6daf 100644 (file)
@@ -1,5 +1,5 @@
 @core @core_grades
-Feature: We can customise the letter boundary of a course.
+Feature: We can customise the letter boundary of a course in gradebook version 20160518.
   In order to change the letter boundary of a course
   As a teacher
   I need to add assessments to the gradebook.
index 1f10b75..82dbd8d 100644 (file)
@@ -229,39 +229,37 @@ Feature: We can use natural aggregation and weights will be normalised to a tota
 
   @javascript
   Scenario: With one grade item set as extra credit, when I reset the weights for a category they return to the natural weights.
-
-  When I set the following settings for grade item "Test assignment five":
-    | Extra credit | 1 |
-  And I set the field "Override weight of Test assignment six" to "1"
-  And I set the field "Override weight of Test assignment seven" to "1"
-  And I set the field "Weight of Test assignment six" to "55"
-  And I set the field "Weight of Test assignment seven" to "40"
-  And I press "Save changes"
-  And I reset weights for grade category "Sub category 1"
-  Then the field "Weight of Test assignment five" matches value "80.0"
-  And the field "Weight of Test assignment six" matches value "40.0"
-  And the field "Weight of Test assignment seven" matches value "60.0"
+    When I set the following settings for grade item "Test assignment five":
+      | Extra credit | 1 |
+    And I set the field "Override weight of Test assignment six" to "1"
+    And I set the field "Override weight of Test assignment seven" to "1"
+    And I set the field "Weight of Test assignment six" to "55"
+    And I set the field "Weight of Test assignment seven" to "40"
+    And I press "Save changes"
+    And I reset weights for grade category "Sub category 1"
+    Then the field "Weight of Test assignment five" matches value "80.0"
+    And the field "Weight of Test assignment six" matches value "40.0"
+    And the field "Weight of Test assignment seven" matches value "60.0"
 
   @javascript
   Scenario: Overriding a grade item with a negative value results in the value being changed to zero.
-
-  When I set the field "Override weight of Test assignment five" to "1"
-  And I set the field "Weight of Test assignment five" to "-15"
-  And I press "Save changes"
-  Then the field "Weight of Test assignment five" matches value "0.0"
-  And the field "Weight of Test assignment six" matches value "40.0"
-  And the field "Weight of Test assignment seven" matches value "60.0"
-  And I set the field "Override weight of Test assignment six" to "1"
-  And I set the field "Weight of Test assignment six" to "-25"
-  And I press "Save changes"
-  And the field "Weight of Test assignment six" matches value "0.0"
-  And the field "Weight of Test assignment seven" matches value "100.0"
-  And I reset weights for grade category "Sub category 1"
-  And I set the field "Override weight of Test assignment five" to "1"
-  And I set the field "Override weight of Test assignment six" to "1"
-  And I set the field "Weight of Test assignment five" to "-10"
-  And I set the field "Weight of Test assignment six" to "120"
-  And I press "Save changes"
-  And the field "Weight of Test assignment five" matches value "0.0"
-  And the field "Weight of Test assignment six" matches value "100.0"
-  And the field "Weight of Test assignment seven" matches value "0.0"
+    When I set the field "Override weight of Test assignment five" to "1"
+    And I set the field "Weight of Test assignment five" to "-15"
+    And I press "Save changes"
+    Then the field "Weight of Test assignment five" matches value "0.0"
+    And the field "Weight of Test assignment six" matches value "40.0"
+    And the field "Weight of Test assignment seven" matches value "60.0"
+    And I set the field "Override weight of Test assignment six" to "1"
+    And I set the field "Weight of Test assignment six" to "-25"
+    And I press "Save changes"
+    And the field "Weight of Test assignment six" matches value "0.0"
+    And the field "Weight of Test assignment seven" matches value "100.0"
+    And I reset weights for grade category "Sub category 1"
+    And I set the field "Override weight of Test assignment five" to "1"
+    And I set the field "Override weight of Test assignment six" to "1"
+    And I set the field "Weight of Test assignment five" to "-10"
+    And I set the field "Weight of Test assignment six" to "120"
+    And I press "Save changes"
+    And the field "Weight of Test assignment five" matches value "0.0"
+    And the field "Weight of Test assignment six" matches value "100.0"
+    And the field "Weight of Test assignment seven" matches value "0.0"
index 810f999..8d256d3 100644 (file)
@@ -32,4 +32,3 @@ Feature: Atto accessibility helper
     # This shows the current HTML tags applied to the selected text.
     # This is required because they are not always read by a screen reader.
     Then I should see "UL, LI"
-
index 1303890..e6af81b 100644 (file)
@@ -53,4 +53,3 @@ Feature: Atto align text
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "style=\"text-align:center;\""
-
index c458ee6..0e63a89 100644 (file)
@@ -20,4 +20,3 @@ Feature: Atto clear button
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should not see "<i>Pisa"
-
index 88f1aab..f6ff892 100644 (file)
@@ -11,4 +11,3 @@ Feature: Atto collapse button
     Then "Equation editor" "button" should be visible
     And I click on "Show fewer buttons" "button"
     Then "Equation editor" "button" should not be visible
-
index 4afc696..ae1d92c 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js differ
index 5740db9..a5ff287 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js differ
index 0f955ef..f98b58c 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js differ
index 45e90d3..849a967 100644 (file)
@@ -448,13 +448,15 @@ Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.
         while (equation.charAt(currentPos) === '\\' && currentPos >= 0) {
             currentPos -= 1;
         }
-        isChar = /[a-zA-Z\{\}]/;
+        isChar = /[a-zA-Z\{]/;
         if (currentPos !== 0) {
-            // Now match to the end of the line.
-            while (isChar.test(equation.charAt(currentPos)) &&
-                   currentPos < equation.length &&
-                   isChar.test(equation.charAt(currentPos - 1))) {
-                currentPos += 1;
+            if (equation.charAt(currentPos - 1) != '{') {
+                // Now match to the end of the line.
+                while (isChar.test(equation.charAt(currentPos)) &&
+                       currentPos < equation.length &&
+                       isChar.test(equation.charAt(currentPos - 1))) {
+                    currentPos += 1;
+                }
             }
         }
         // Save the cursor position - for insertion from the library.
index 1357cfc..f4a7472 100644 (file)
@@ -11,4 +11,3 @@ Feature: Atto edit HTML
     And I click on "Show more buttons" "button"
     And I click on "HTML" "button"
     Then the field "Description" matches value "<p style=\"color: blue;\">Smurf</p>"
-
index 4d02eb6..f948733 100644 (file)
@@ -24,4 +24,3 @@ Feature: Add links to Atto
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "Super cool</a>"
-
index 60ec2c7..03cc0de 100644 (file)
@@ -3,164 +3,164 @@ Feature: Add media to Atto
   To write rich text - I need to add media.
 
   Background:
-  Given I log in as "admin"
-  And I follow "Manage private files..."
-  And I upload "lib/editor/atto/tests/fixtures/moodle-logo.webm" file to "Files" filemanager
-  And I upload "lib/editor/atto/tests/fixtures/moodle-logo.mp4" file to "Files" filemanager
-  And I upload "lib/editor/atto/tests/fixtures/moodle-logo.png" file to "Files" filemanager
-  And I upload "lib/editor/atto/tests/fixtures/pretty-good-en.vtt" file to "Files" filemanager
-  And I upload "lib/editor/atto/tests/fixtures/pretty-good-sv.vtt" file to "Files" filemanager
-  And I click on "Save changes" "button"
-  And I follow "Profile" in the user menu
-  And I follow "Blog entries"
-  And I follow "Add a new entry"
-  And I set the field "Blog entry body" to "<p>Media test</p>"
-  And I select the text in the "Blog entry body" Atto editor
-  And I set the field "Entry title" to "The best video in the entire world (not really)"
-  And I click on "Media" "button"
+    Given I log in as "admin"
+    And I follow "Manage private files..."
+    And I upload "lib/editor/atto/tests/fixtures/moodle-logo.webm" file to "Files" filemanager
+    And I upload "lib/editor/atto/tests/fixtures/moodle-logo.mp4" file to "Files" filemanager
+    And I upload "lib/editor/atto/tests/fixtures/moodle-logo.png" file to "Files" filemanager
+    And I upload "lib/editor/atto/tests/fixtures/pretty-good-en.vtt" file to "Files" filemanager
+    And I upload "lib/editor/atto/tests/fixtures/pretty-good-sv.vtt" file to "Files" filemanager
+    And I click on "Save changes" "button"
+    And I follow "Profile" in the user menu
+    And I follow "Blog entries"
+    And I follow "Add a new entry"
+    And I set the field "Blog entry body" to "<p>Media test</p>"
+    And I select the text in the "Blog entry body" Atto editor
+    And I set the field "Entry title" to "The best video in the entire world (not really)"
+    And I click on "Media" "button"
 
   @javascript
   Scenario: Insert some media as a link
-  Given I click on "Browse repositories..." "button" in the "#id_summary_editor_link .atto_media_source.atto_media_link_source" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.webm" "link"
-  And I click on "Select this file" "button"
-  And the field "Enter name" matches value "moodle-logo.webm"
-  And I wait until the page is ready
-  And I click on "Insert media" "button"
-  When I click on "Save changes" "button"
-  Then "//a[. = 'moodle-logo.webm']" "xpath_element" should exist
+    Given I click on "Browse repositories..." "button" in the "#id_summary_editor_link .atto_media_source.atto_media_link_source" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.webm" "link"
+    And I click on "Select this file" "button"
+    And the field "Enter name" matches value "moodle-logo.webm"
+    And I wait until the page is ready
+    And I click on "Insert media" "button"
+    When I click on "Save changes" "button"
+    Then "//a[. = 'moodle-logo.webm']" "xpath_element" should exist
 
   @javascript
   Scenario: Insert some media as a plain video
-  Given I click on "Video" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.webm" "link"
-  And I click on "Select this file" "button"
-  And I click on "Add alternative source" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source:nth-of-type(2)" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.mp4" "link"
-  And I click on "Select this file" "button"
-  When I click on "Insert media" "button"
-  Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][descendant::source[contains(@src, 'moodle-logo.mp4')]]" "xpath_element" should exist
+    Given I click on "Video" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.webm" "link"
+    And I click on "Select this file" "button"
+    And I click on "Add alternative source" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source:nth-of-type(2)" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.mp4" "link"
+    And I click on "Select this file" "button"
+    When I click on "Insert media" "button"
+    Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][descendant::source[contains(@src, 'moodle-logo.mp4')]]" "xpath_element" should exist
 
   @javascript
   Scenario: Insert some media as a video with display settings
-  Given I click on "Video" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.webm" "link"
-  And I click on "Select this file" "button"
-  And I click on "Display options" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_poster_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "moodle-logo.png" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I change window size to "large"
-  And I set the field with xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_width_entry ')]" to "420"
-  And I set the field with xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_height_entry ')]" to "69"
-  And I click on "Display options" "link"
-  When I click on "Insert media" "button"
-  Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][contains(@poster, 'moodle-logo.png')][@width=420][@height=69]" "xpath_element" should exist
+    Given I click on "Video" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.webm" "link"
+    And I click on "Select this file" "button"
+    And I click on "Display options" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_poster_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "moodle-logo.png" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I change window size to "large"
+    And I set the field with xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_width_entry ')]" to "420"
+    And I set the field with xpath "//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_height_entry ')]" to "69"
+    And I click on "Display options" "link"
+    When I click on "Insert media" "button"
+    Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][contains(@poster, 'moodle-logo.png')][@width=420][@height=69]" "xpath_element" should exist
 
   @javascript
   Scenario: Insert some media as a video with advanced settings
-  Given I click on "Video" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.webm" "link"
-  And I click on "Select this file" "button"
-  And I click on "Advanced settings" "link"
-  And the field "Show controls" matches value "1"
-  And I set the field "Play automatically" to "1"
-  And I set the field "Muted" to "1"
-  And I set the field "Loop" to "1"
-  When I click on "Insert media" "button"
-  Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][@controls='true'][@loop='true'][@autoplay='true'][@autoplay='true']" "xpath_element" should exist
+    Given I click on "Video" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.webm" "link"
+    And I click on "Select this file" "button"
+    And I click on "Advanced settings" "link"
+    And the field "Show controls" matches value "1"
+    And I set the field "Play automatically" to "1"
+    And I set the field "Muted" to "1"
+    And I set the field "Loop" to "1"
+    When I click on "Insert media" "button"
+    Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][@controls='true'][@loop='true'][@autoplay='true'][@autoplay='true']" "xpath_element" should exist
 
   @javascript
   Scenario: Insert some media as a video with tracks
-  Given I click on "Video" "link"
-  And I change window size to "large"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
-  And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
-  And I click on "moodle-logo.webm" "link"
-  And I click on "Select this file" "button"
-  And I click on "Subtitles and captions" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_subtitles .atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-sv.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And the field "Label" matches value "Swedish"
-  And the field "Language" matches value "sv"
-  And I click on "Add subtitle track" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_subtitles .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-en.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[2]" matches value "English"
-  And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[1]" to "1"
-  And I click on "Captions" "link" in the ".nav-item[data-track-kind='captions']" "css_element"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_captions .atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-sv.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[3]" matches value "Swedish"
-  And I click on "Add caption track" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_captions .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-en.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[4]" matches value "English"
-  And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[4]" to "1"
-  And I click on "Descriptions" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_descriptions .atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And  I click on "pretty-good-sv.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[5]" matches value "Swedish"
-  And I click on "Add description track" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_descriptions .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-en.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[6]" matches value "English"
-  And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[5]" to "1"
-  And I click on "Chapters" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_chapters .atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And  I click on "pretty-good-sv.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[7]" matches value "Swedish"
-  And I click on "Add chapter track" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_chapters .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-en.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[8]" matches value "English"
-  And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[8]" to "1"
-  And I click on "Metadata" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_metadata .atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And  I click on "pretty-good-sv.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[9]" matches value "Swedish"
-  And I click on "Add metadata track" "link"
-  And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_metadata .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
-  And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
-  And I click on "pretty-good-en.vtt" "link"
-  And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
-  And I click on "Overwrite" "button"
-  And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[10]" matches value "English"
-  And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[9]" to "1"
-  When I click on "Insert media" "button"
-  Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='subtitles'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='subtitles'][@label='English'][@srclang='en'][not(@default)]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='captions'][@label='Swedish'][@srclang='sv'][not(@default)]][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='captions'][@label='English'][@srclang='en'][@default='true']][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='descriptions'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='descriptions'][@label='English'][@srclang='en'][not(@default)]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='chapters'][@label='Swedish'][@srclang='sv'][not(@default)]][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='chapters'][@label='English'][@srclang='en'][@default='true']][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='metadata'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='metadata'][@label='English'][@srclang='en'][not(@default)]]" "xpath_element" should exist
+    Given I click on "Video" "link"
+    And I change window size to "large"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video .atto_media_source.atto_media_media_source" "css_element"
+    And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
+    And I click on "moodle-logo.webm" "link"
+    And I click on "Select this file" "button"
+    And I click on "Subtitles and captions" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_subtitles .atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-sv.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And the field "Label" matches value "Swedish"
+    And the field "Language" matches value "sv"
+    And I click on "Add subtitle track" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_subtitles .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-en.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[2]" matches value "English"
+    And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[1]" to "1"
+    And I click on "Captions" "link" in the ".nav-item[data-track-kind='captions']" "css_element"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_captions .atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-sv.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[3]" matches value "Swedish"
+    And I click on "Add caption track" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_captions .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-en.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[4]" matches value "English"
+    And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[4]" to "1"
+    And I click on "Descriptions" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_descriptions .atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And  I click on "pretty-good-sv.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[5]" matches value "Swedish"
+    And I click on "Add description track" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_descriptions .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-en.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[6]" matches value "English"
+    And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[5]" to "1"
+    And I click on "Chapters" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_chapters .atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And  I click on "pretty-good-sv.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[7]" matches value "Swedish"
+    And I click on "Add chapter track" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_chapters .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-en.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[8]" matches value "English"
+    And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[8]" to "1"
+    And I click on "Metadata" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_metadata .atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And  I click on "pretty-good-sv.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[9]" matches value "Swedish"
+    And I click on "Add metadata track" "link"
+    And I click on "Browse repositories..." "button" in the "#id_summary_editor_video_metadata .atto_media_track~.atto_media_track .atto_media_source.atto_media_track_source" "css_element"
+    And I click on "Private files" "link" in the ".moodle-dialogue-base[aria-hidden='false'] .fp-repo-area" "css_element"
+    And I click on "pretty-good-en.vtt" "link"
+    And I click on "Select this file" "button" in the ".moodle-dialogue-base[aria-hidden='false']" "css_element"
+    And I click on "Overwrite" "button"
+    And the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_label_entry ')])[10]" matches value "English"
+    And I set the field with xpath "(//*[contains(concat(' ', normalize-space(@class), ' '), ' atto_media_track_default ')])[9]" to "1"
+    When I click on "Insert media" "button"
+    Then "//video[descendant::source[contains(@src, 'moodle-logo.webm')]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='subtitles'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='subtitles'][@label='English'][@srclang='en'][not(@default)]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='captions'][@label='Swedish'][@srclang='sv'][not(@default)]][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='captions'][@label='English'][@srclang='en'][@default='true']][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='descriptions'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='descriptions'][@label='English'][@srclang='en'][not(@default)]][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='chapters'][@label='Swedish'][@srclang='sv'][not(@default)]][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='chapters'][@label='English'][@srclang='en'][@default='true']][descendant::track[contains(@src, 'pretty-good-sv.vtt')][@kind='metadata'][@label='Swedish'][@srclang='sv'][@default='true']][descendant::track[contains(@src, 'pretty-good-en.vtt')][@kind='metadata'][@label='English'][@srclang='en'][not(@default)]]" "xpath_element" should exist
index 5c38924..26ad2bf 100644 (file)
@@ -18,4 +18,3 @@ Feature: Atto strike button
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "<strike>MUA</strike>"
-
index 8581a8b..ac629ce 100644 (file)
@@ -35,4 +35,3 @@ Feature: Atto subscript button
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "<sub>Submarine</sub>"
-
index 2e3ed49..44dd871 100644 (file)
@@ -35,4 +35,3 @@ Feature: Atto superscript button
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "<sup>Helicopter</sup>"
-
index 527f284..f145be3 100644 (file)
@@ -18,4 +18,3 @@ Feature: Atto title
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "<h3>How The Rock"
-
index c30716c..5733155 100644 (file)
@@ -18,4 +18,3 @@ Feature: Atto underline button
     And I press "Save changes"
     And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should see "<u>Deprecated HTML Tag</u>"
-
index 2c8a3ea..1f7d4f4 100644 (file)
@@ -2165,12 +2165,14 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
                     }
                     //for editor element, [text] is appended to the name.
                     $fullelementname = $elementName;
-                    if ($element->getType() == 'editor') {
-                        $fullelementname .= '[text]';
-                        //Add format to rule as moodleform check which format is supported by browser
-                        //it is not set anywhere... So small hack to make sure we pass it down to quickform
-                        if (is_null($rule['format'])) {
-                            $rule['format'] = $element->getFormat();
+                    if (is_object($element) && $element->getType() == 'editor') {
+                        if ($element->getType() == 'editor') {
+                            $fullelementname .= '[text]';
+                            // Add format to rule as moodleform check which format is supported by browser
+                            // it is not set anywhere... So small hack to make sure we pass it down to quickform.
+                            if (is_null($rule['format'])) {
+                                $rule['format'] = $element->getFormat();
+                            }
                         }
                     }
                     // Fix for bug displaying errors for elements in a group
@@ -2263,7 +2265,12 @@ require(["core/event", "jquery"], function(Event, $) {
                 $elementName);
             $valFunc = 'validate_' . $this->_formName . '_' . $escapedElementName . '(ev.target, \''.$escapedElementName.'\')';
 
-            $js .= '
+            if (!is_array($element)) {
+                $element = [$element];
+            }
+            foreach ($element as $elem) {
+                if (key_exists('id', $elem->_attributes)) {
+                    $js .= '
     function validate_' . $this->_formName . '_' . $escapedElementName . '(element, escapedName) {
       if (undefined == element) {
          //required element was not found, then let form be submitted without client side validation
@@ -2286,13 +2293,15 @@ require(["core/event", "jquery"], function(Event, $) {
       }
     }
 
-    document.getElementById(\'' . $element->_attributes['id'] . '\').addEventListener(\'blur\', function(ev) {
+    document.getElementById(\'' . $elem->_attributes['id'] . '\').addEventListener(\'blur\', function(ev) {
         ' . $valFunc . '
     });
-    document.getElementById(\'' . $element->_attributes['id'] . '\').addEventListener(\'change\', function(ev) {
+    document.getElementById(\'' . $elem->_attributes['id'] . '\').addEventListener(\'change\', function(ev) {
         ' . $valFunc . '
     });
 ';
+                }
+            }
             $validateJS .= '
       ret = validate_' . $this->_formName . '_' . $escapedElementName.'(frm.elements[\''.$elementName.'\'], \''.$escapedElementName.'\') && ret;
       if (!ret && !first_focus) {
index 8d1859c..e5955b4 100644 (file)
@@ -3748,7 +3748,14 @@ class flat_navigation extends navigation_node_collection {
         if ($course->id > 1) {
             // It's a real course.
             $url = new moodle_url('/course/view.php', array('id' => $course->id));
-            $flat = new flat_navigation_node(navigation_node::create($course->shortname, $url), 0);
+
+            $coursecontext = context_course::instance($course->id, MUST_EXIST);
+            // This is the name that will be shown for the course.
+            $coursename = empty($CFG->navshowfullcoursenames) ?
+                format_string($course->shortname, true, array('context' => $coursecontext)) :
+                format_string($course->fullname, true, array('context' => $coursecontext));
+
+            $flat = new flat_navigation_node(navigation_node::create($coursename, $url), 0);
             $flat->key = 'coursehome';
 
             $courseformat = course_get_format($course);
index 46493ea..118d89a 100644 (file)
@@ -297,6 +297,19 @@ class behat_deprecated extends behat_base {
         $this->deprecated_message($alternative, true);
     }
 
+    /**
+     * Navigates to the course gradebook and selects a specified item from the grade navigation tabs.
+     * @Given /^I go to "(?P<gradepath_string>(?:[^"]|\\")*)" in the course gradebook$/
+     * @param string $gradepath
+     * @deprecated since Moodle 3.3 MDL-57282 - please do not use this step any more.
+     */
+    public function i_go_to_in_the_course_gradebook($gradepath) {
+        $alternative = 'I navigate to "' . $this->escape($gradepath) . '"  in the course gradebook';
+        $this->deprecated_message($alternative);
+
+        $this->execute('behat_grade::i_navigate_to_in_the_course_gradebook', $gradepath);
+    }
+
     /**
      * Throws an exception if $CFG->behat_usedeprecated is not allowed.
      *
index d25f29c..239dd99 100644 (file)
@@ -581,11 +581,23 @@ class behat_hooks extends behat_base {
         // The scenario title + the failed step text.
         // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format.
         $filename = $scope->getFeature()->getTitle() . '_' . $scope->getStep()->getText();
-        $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename);
 
-        // File name limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file.
+        // As file name is limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file.
         // extension as we allow .png for images and .html for DOM contents.
-        $filename = substr($filename, 0, 245) . '_' . $scope->getStep()->getLine() . '.' . $filetype;
+        $filenamelen = 245;
+
+        // Suffix suite name to faildump file, if it's not default suite.
+        $suitename = $scope->getSuite()->getName();
+        if ($suitename != 'default') {
+            $suitename = '_' . $suitename;
+            $filenamelen = $filenamelen - strlen($suitename);
+        } else {
+            // No need to append suite name for default.
+            $suitename = '';
+        }
+
+        $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename);
+        $filename = substr($filename, 0, $filenamelen) . $suitename . '_' . $scope->getStep()->getLine() . '.' . $filetype;
 
         return array($dir, $filename);
     }
index 3a3efed..062ed01 100644 (file)
@@ -1,5 +1,5 @@
 @core @message @javascript
-Feature: Search users
+Feature: Manage contacts
   In order to communicate with fellow users
   As a user
   I need to be able to add and remove them from my contacts
index b93403e..f404c23 100644 (file)
@@ -63,4 +63,3 @@ Feature: In an assignment, teacher can view the feedback for a previous attempt.
     And I wait until the page is ready
     And I should see "You are editing the feedback for a previous attempt. This is attempt 1 out of 2."
     And I should see "Page 1 of 3"
-
index 3bc9106..c7d374f 100644 (file)
@@ -63,4 +63,3 @@ Feature: Check that the assignment grade can not be input in a wrong format.
     And I set the field "Grade out of 100" to "50..6"
     And I press "Save changes"
     And I should see "The grade provided could not be understood: 50..6"
-
index 47e45fa..61e97bf 100644 (file)
@@ -74,4 +74,3 @@ Feature: Book activity chapter visibility management
     And I follow "Next"
     And I should see "Fourth chapter" in the ".book_content" "css_element"
     And I follow "Exit book"
-
index 1782157..ea6577b 100644 (file)
@@ -1,5 +1,5 @@
 @mod @mod_choice
-Feature: Add choice activity
+Feature: Editing choice block
   In order to customise choice page
   As a teacher or admin
   I need to add remove block from the choice page
index f10f83d..8ae18dd 100644 (file)
@@ -224,24 +224,24 @@ Feature: Users can be required to specify certain fields when adding entries to
     Then ".alert" "css_element" should exist in the "Required Latlong" "table_row"
     And ".alert" "css_element" should exist in the "Not required Latlong" "table_row"
 
-    Scenario: A student filling in number and text fields with zero will not see an error.
-      Given I log in as "student1"
-      And I follow "Course 1"
-      When I add an entry to "Test database name" database with:
-         | Base Text input               | Some input to allow us to submit the otherwise empty form |
-         | Required Checkbox Option 1    | 1                                                         |
-         | RTOC Option 1                 | 1                                                         |
-         | Latitude                      | 0                                                         |
-         | Longitude                     | 0                                                         |
-         | Required Menu                 | 1                                                         |
-         | Required Number               | 0                                                         |
-         | Required Radio Option 1       | 1                                                         |
-         | Required Text input           | 0                                                         |
-         | Required Text area            | 0                                                         |
-         | Required URL                  | http://example.com/                                       |
-         | Required Multimenu            | 1                                                         |
-         | Required Two-Option Multimenu | 1                                                         |
-      And I press "Save and view"
-      And I follow "View list"
-      Then I should not see "No entries in database"
-      And I should see "Some input to allow us to submit the otherwise empty form"
+  Scenario: A student filling in number and text fields with zero will not see an error.
+    Given I log in as "student1"
+    And I follow "Course 1"
+    When I add an entry to "Test database name" database with:
+       | Base Text input               | Some input to allow us to submit the otherwise empty form |
+       | Required Checkbox Option 1    | 1                                                         |
+       | RTOC Option 1                 | 1                                                         |
+       | Latitude                      | 0                                                         |
+       | Longitude                     | 0                                                         |
+       | Required Menu                 | 1                                                         |
+       | Required Number               | 0                                                         |
+       | Required Radio Option 1       | 1                                                         |
+       | Required Text input           | 0                                                         |
+       | Required Text area            | 0                                                         |
+       | Required URL                  | http://example.com/                                       |
+       | Required Multimenu            | 1                                                         |
+       | Required Two-Option Multimenu | 1                                                         |
+    And I press "Save and view"
+    And I follow "View list"
+    Then I should not see "No entries in database"
+    And I should see "Some input to allow us to submit the otherwise empty form"
index 1ece799..de8b038 100644 (file)
@@ -67,6 +67,11 @@ class restore_forum_activity_structure_step extends restore_activity_structure_s
 
         $newitemid = $DB->insert_record('forum', $data);
         $this->apply_activity_instance($newitemid);
+
+        // Add current enrolled user subscriptions if necessary.
+        $data->id = $newitemid;
+        $ctx = context_module::instance($this->task->get_moduleid());
+        forum_instance_created($ctx, $data);
     }
 
     protected function process_forum_discussion($data) {
index aa8b6d5..540d3b9 100644 (file)
@@ -273,40 +273,40 @@ Feature: A user can control their own subscription preferences for a discussion
     And I follow "Reply"
     And the field "Discussion subscription" matches value "I don't want to be notified of new posts in this discussion"
 
- Scenario: A guest should not be able to subscribe to a discussion
-   Given I am on site homepage
-   And I add a "Forum" to section "1" and I fill the form with:
 Scenario: A guest should not be able to subscribe to a discussion
+    Given I am on site homepage
+    And I add a "Forum" to section "1" and I fill the form with:
      | Forum name        | Test forum name |
      | Forum type        | Standard forum for general use |
      | Description       | Test forum description |
-   And I add a new discussion to "Test forum name" forum with:
+    And I add a new discussion to "Test forum name" forum with:
      | Subject | Test post subject one |
      | Message | Test post message one |
-   And I log out
-   When I log in as "guest"
-   And I follow "Test forum name"
-   Then "You are not subscribed to this discussion. Click to subscribe." "link" should not exist in the "Test post subject one" "table_row"
-   And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist in the "Test post subject one" "table_row"
-   And I follow "Test post subject one"
-   And "You are not subscribed to this discussion. Click to subscribe." "link" should not exist
-   And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist
+    And I log out
+    When I log in as "guest"
+    And I follow "Test forum name"
+    Then "You are not subscribed to this discussion. Click to subscribe." "link" should not exist in the "Test post subject one" "table_row"
+    And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist in the "Test post subject one" "table_row"
+    And I follow "Test post subject one"
+    And "You are not subscribed to this discussion. Click to subscribe." "link" should not exist
+    And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist
 
- Scenario: A user who is not logged in should not be able to subscribe to a discussion
-   Given I am on site homepage
-   And I add a "Forum" to section "1" and I fill the form with:
 Scenario: A user who is not logged in should not be able to subscribe to a discussion
+    Given I am on site homepage
+    And I add a "Forum" to section "1" and I fill the form with:
      | Forum name        | Test forum name |
      | Forum type        | Standard forum for general use |
      | Description       | Test forum description |
-   And I add a new discussion to "Test forum name" forum with:
+    And I add a new discussion to "Test forum name" forum with:
      | Subject | Test post subject one |
      | Message | Test post message one |
-   And I log out
-   When I follow "Test forum name"
-   Then "You are not subscribed to this discussion. Click to subscribe." "link" should not exist in the "Test post subject one" "table_row"
-   And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist in the "Test post subject one" "table_row"
-   And I follow "Test post subject one"
-   And "You are not subscribed to this discussion. Click to subscribe." "link" should not exist
-   And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist
+    And I log out
+    When I follow "Test forum name"
+    Then "You are not subscribed to this discussion. Click to subscribe." "link" should not exist in the "Test post subject one" "table_row"
+    And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist in the "Test post subject one" "table_row"
+    And I follow "Test post subject one"
+    And "You are not subscribed to this discussion. Click to subscribe." "link" should not exist
+    And "You are subscribed to this discussion. Click to unsubscribe." "link" should not exist
 
   Scenario: A user can toggle their subscription preferences when viewing a discussion
     Given I add a "Forum" to section "1" and I fill the form with:
index cfbe9e9..5e3a958 100644 (file)
@@ -4,7 +4,7 @@ Feature: A user with access to multiple groups should be able to post a copy of
   As a user
   I need to have the option to post a copy of a message to all groups
 
-Background:
+  Background:
     Given the following "users" exist:
       | username | firstname | lastname | email |
       | teacher1 | Teacher | 1 | teacher1@example.com |
index 3009725..ade10bf 100644 (file)
@@ -33,4 +33,3 @@ Feature: A teacher can choose whether to allow duplicate entries in a glossary
     And I press "Save changes"
     Then I should see "This concept already exists. No duplicates allowed in this glossary."
     And I press "Cancel"
-
index 9eaf606..723cfd7 100644 (file)
@@ -36,4 +36,3 @@ Feature: In a lesson activity, teacher can import embedded images in questions a
     And "//audio[contains(@title, 'Listen to this greeting:')]/source[contains(@src, 'bonjour.mp3')]" "xpath_element" should exist
     And "//*[contains(@class, 'answeroption')]//img[contains(@src, 'pluginfile.php')]" "xpath_element" should exist
     And "//*[contains(@class, 'answeroption')]//img[contains(@src, 'flag-france.jpg')]" "xpath_element" should exist
-
index 156d3dc..ec7e139 100644 (file)
@@ -64,7 +64,7 @@ Feature: In a lesson activity, teacher can edit a cluster page
     And I press "Save page"
     And I click on "Add an end of cluster" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][5]" "xpath_element"
     And I click on "Add a content page" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][6]" "xpath_element"
-        And I set the following fields to these values:
+    And I set the following fields to these values:
       | Page title | Second page name |
       | Page contents | Content page after cluster |
       | id_answer_editor_0 | Next page |
index 3bf4ddc..8da82f2 100644 (file)
@@ -1,5 +1,5 @@
 @mod @mod_lesson
-Feature: Lesson user override
+Feature: Lesson group override
   In order to grant a student special access to a lesson
   As a teacher
   I need to create an override for that user.
index 6b7f4c9..1489596 100644 (file)
@@ -1,96 +1,96 @@
 @mod @mod_lesson
 Feature: Practice mode in a lesson activity
-    In order to improve my students understanding of a subject
-    As a teacher
-    I need to be able to set ungraded practice lesson activites
+  In order to improve my students understanding of a subject
+  As a teacher
+  I need to be able to set ungraded practice lesson activites
 
-    Background:
-        Given the following "users" exist:
-            | username | firstname | lastname | email |
-            | teacher1 | Teacher | 1 | teacher1@example.com |
-            | student1 | Student | 1 | student1@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 |
-            | student1 | C1 | student |
-        And I log in as "teacher1"
-        And I follow "Course 1"
-        And I turn editing mode on
-        # Setup a basic lesson, we'll adjust it in the scenarios later.
-        And I add a "Lesson" to section "1" and I fill the form with:
-            | Name | Test lesson name |
-            | Description | Lesson description |
-        And I follow "Test lesson name"
-        And I follow "Add a question page"
-        And I set the field "Select a question type" to "True/false"
-        And I press "Add a question page"
-        And I set the following fields to these values:
-            | Page title | True or False |
-            | Page contents | Paper is made from trees. |
-            | id_answer_editor_0 | True |
-            | id_answer_editor_1 | False |
-        And I press "Save page"
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@example.com |
+      | student1 | Student | 1 | student1@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 |
+      | student1 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+      # Setup a basic lesson, we'll adjust it in the scenarios later.
+    And I add a "Lesson" to section "1" and I fill the form with:
+      | Name | Test lesson name |
+      | Description | Lesson description |
+    And I follow "Test lesson name"
+    And I follow "Add a question page"
+    And I set the field "Select a question type" to "True/false"
+    And I press "Add a question page"
+    And I set the following fields to these values:
+      | Page title | True or False |
+      | Page contents | Paper is made from trees. |
+      | id_answer_editor_0 | True |
+      | id_answer_editor_1 | False |
+    And I press "Save page"
 
-    Scenario: Non-practice lesson records grades in the gradebook
-        Given I follow "Test lesson name"
-        And I navigate to "Edit settings" in current page administration
-        And I set the following fields to these values:
-            | Name | Non-practice lesson |
-            | Description | This lesson will affect your course grade |
-            | Practice lesson | No |
-        And I press "Save and display"
-        And I log out
-        When I log in as "student1"
-        And I follow "Course 1"
-        And I follow "Non-practice lesson"
-        And I set the following fields to these values:
-            | True | 1 |
-        And I press "Submit"
-        Then I should see "View grades"
-        And I follow "Grades" in the user menu
-        And I follow "Course 1"
-        And I should see "Non-practice lesson"
+  Scenario: Non-practice lesson records grades in the gradebook
+    Given I follow "Test lesson name"
+    And I navigate to "Edit settings" in current page administration
+    And I set the following fields to these values:
+      | Name | Non-practice lesson |
+      | Description | This lesson will affect your course grade |
+      | Practice lesson | No |
+    And I press "Save and display"
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Non-practice lesson"
+    And I set the following fields to these values:
+      | True | 1 |
+    And I press "Submit"
+    Then I should see "View grades"
+    And I follow "Grades" in the user menu
+    And I follow "Course 1"
+    And I should see "Non-practice lesson"
 
-    Scenario: Practice lesson doesn't record grades in the gradebook
-        Given I follow "Test lesson name"
-        And I navigate to "Edit settings" in current page administration
-        And I set the following fields to these values:
-            | Name | Practice lesson |
-            | Description | This lesson will NOT affect your course grade |
-            | Practice lesson | Yes |
-        And I press "Save and display"
-        And I log out
-        When I log in as "student1"
-        And I follow "Course 1"
-        And I follow "Practice lesson"
-        And I set the following fields to these values:
-            | True | 1 |
-        And I press "Submit"
-        Then I should not see "View grades"
-        And I follow "Grades" in the user menu
-        And I click on "Course 1" "link" in the "Course 1" "table_row"
-        And I should not see "Practice lesson"
+  Scenario: Practice lesson doesn't record grades in the gradebook
+    Given I follow "Test lesson name"
+    And I navigate to "Edit settings" in current page administration
+    And I set the following fields to these values:
+      | Name | Practice lesson |
+      | Description | This lesson will NOT affect your course grade |
+      | Practice lesson | Yes |
+    And I press "Save and display"
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Practice lesson"
+    And I set the following fields to these values:
+      | True | 1 |
+    And I press "Submit"
+    Then I should not see "View grades"
+    And I follow "Grades" in the user menu
+    And I click on "Course 1" "link" in the "Course 1" "table_row"
+    And I should not see "Practice lesson"
 
-    Scenario: Practice lesson with scale doesn't record grades in the gradebook
-        Given I follow "Test lesson name"
-        And I navigate to "Edit settings" in current page administration
-        And I set the following fields to these values:
-            | Name | Practice lesson with scale |
-            | Description | This lesson will NOT affect your course grade |
-            | Practice lesson | Yes |
-            | Type | Scale |
-        And I press "Save and display"
-        And I log out
-        When I log in as "student1"
-        And I follow "Course 1"
-        And I follow "Practice lesson with scale"
-        And I set the following fields to these values:
-            | True | 1 |
-        And I press "Submit"
-        Then I should not see "View grades"
-        And I follow "Grades" in the user menu
-        And I click on "Course 1" "link" in the "Course 1" "table_row"
-        And I should not see "Practice lesson with scale"
+  Scenario: Practice lesson with scale doesn't record grades in the gradebook
+    Given I follow "Test lesson name"
+    And I navigate to "Edit settings" in current page administration
+    And I set the following fields to these values:
+      | Name | Practice lesson with scale |
+      | Description | This lesson will NOT affect your course grade |
+      | Practice lesson | Yes |
+      | Type | Scale |
+    And I press "Save and display"
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Practice lesson with scale"
+    And I set the following fields to these values:
+      | True | 1 |
+    And I press "Submit"
+    Then I should not see "View grades"
+    And I follow "Grades" in the user menu
+    And I click on "Course 1" "link" in the "Course 1" "table_row"
+    And I should not see "Practice lesson with scale"
index 4103858..e2bad1a 100644 (file)
@@ -75,7 +75,7 @@ Feature: In a lesson activity, students can see questions in random order
     And I press "Save page"
     And I click on "Add an end of cluster" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][6]" "xpath_element"
     And I click on "Add a content page" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][7]" "xpath_element"
-        And I set the following fields to these values:
+    And I set the following fields to these values:
       | Page title | Third page name |
       | Page contents | Content page after cluster 1 |
       | id_answer_editor_0 | Next page |
@@ -114,7 +114,7 @@ Feature: In a lesson activity, students can see questions in random order
     And I press "Save page"
     And I click on "Add an end of cluster" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][11]" "xpath_element"
     And I click on "Add a content page" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][12]" "xpath_element"
-        And I set the following fields to these values:
+    And I set the following fields to these values:
       | Page title | Fourth page name |
       | Page contents | Content page after cluster 2 |
       | id_answer_editor_0 | Next page |
index 5c3580e..fc04c53 100644 (file)
@@ -65,7 +65,7 @@ Feature: In a lesson activity, students can see questions in random order and a
       | id_score_1 | 0 |
     And I press "Save page"
     And I click on "Add a content page" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][5]" "xpath_element"
-        And I set the following fields to these values:
+    And I set the following fields to these values:
       | Page title | Second page name |
       | Page contents | This page mark the the beginning of the subcluster it should not be seen by students |
       | id_answer_editor_0 | Next page |
@@ -134,7 +134,7 @@ Feature: In a lesson activity, students can see questions in random order and a
     And I press "Save page"
     And I click on "Add an end of cluster" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][11]" "xpath_element"
     And I click on "Add a content page" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][12]" "xpath_element"
-        And I set the following fields to these values:
+    And I set the following fields to these values:
       | Page title | Third page name |
       | Page contents | Content page after cluster |
       | id_answer_editor_0 | Next page |
index f3d1237..17bd36b 100644 (file)
@@ -1,5 +1,5 @@
 @mod @mod_lti
-Feature: Content-Item support
+Feature: Create/edit tool configuration that has Content-Item support
   In order to provide external tools that support the Content-Item Message type for teachers and learners
   As an admin
   I need to be able to configure external tool registrations that support the Content-Item Message type.
index cd1fcc9..18bd5bf 100644 (file)
@@ -1,5 +1,5 @@
 @mod @mod_quiz
-Feature: Attemp a quiz where some questions require that the previous question has been answered.
+Feature: Attempt a quiz
   As a student
   In order to demonstrate what I know
   I need to be able to attempt quizzes
index e5b37f1..4353d9f 100644 (file)
@@ -1,5 +1,5 @@
 @mod @mod_quiz
-Feature: Attemp a quiz where some questions require that the previous question has been answered.
+Feature: Attempt a quiz where some questions require that the previous question has been answered.
   In order to complete a quiz where questions require previous ones to be complete
   As a student
   I need later questions to appear once earlier ones have been answered.
index f16acc8..fb12326 100644 (file)
@@ -149,7 +149,7 @@ Feature: Edit quiz page - section headings
     And I follow "Remove heading 'Heading 2'"
     And I should see "Are you sure you want to remove the 'Heading 2' section heading?"
     And I click on "Yes" "button" in the "Confirm" "dialogue"
-    And I wait until the page is ready
+    And I wait until "Heading 2" "text" does not exist
     Then I should see "Heading 1"
     And I should not see "Heading 2"
     And I should see "Heading 3"
index a25a765..26d7f1b 100644 (file)
@@ -1,5 +1,6 @@
 @mod @mod_quiz
-Feature: In order to create a quiz that awards marks the way I want
+Feature: Edit quiz marks with no attempts
+  In order to create a quiz that awards marks the way I want
   As a teacher
   I must be able to set the marks I want on the Edit quiz page.
 
index f92b370..2349c93 100644 (file)
@@ -1,5 +1,6 @@
 @mod @mod_quiz
-Feature: In order to create a quiz that awards marks the way I want
+Feature: Edit quiz marks with attempts
+  In order to create a quiz that awards marks the way I want
   As a teacher
   I must be able to set the marks I want on the Edit quiz page (even after the quiz has been attempted).
 
index 6e7434a..e8e073d 100644 (file)
@@ -76,7 +76,7 @@ Feature: Quiz reset
     And I navigate to "User overrides" in current page administration
     Then I should not see "Sam1 Student1"
 
-Scenario: Use course reset to remove group overrides.
+  Scenario: Use course reset to remove group overrides.
     When I log in as "teacher1"
     And I follow "Course 1"
     And I follow "Test quiz name"
index 9fa4437..e6ef3ee 100644 (file)
@@ -47,6 +47,7 @@ Feature: Scorm multi-sco completion
     And I follow "Exit activity"
     And I wait until the page is ready
     Then I should see "Basic Multi-sco SCORM package"
+    And I am on homepage
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
@@ -184,6 +185,7 @@ Feature: Scorm multi-sco completion
     And I follow "Exit activity"
     And I wait until the page is ready
     Then I should see "ADV Multi-sco SCORM package"
+    And I am on homepage
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
index f800f9c..f42e9b1 100644 (file)
@@ -86,5 +86,3 @@ Feature: A teacher can set a wiki to be collaborative or individual
     And I set the field "uid" to "Student 2"
     And I should see "Individual student2 edition"
     And I should not see "Individual teacher1 edition"
-
-
index ef9a5db..059c2cc 100644 (file)
@@ -58,7 +58,6 @@ Feature: Users can search wikis
     And I should see "Collaborative teacher1 page"
     And I log out
 
-
   @javascript
   Scenario: Searching individual wiki
     Given I log in as "teacher1"
index 81637af..c41fb4d 100644 (file)
@@ -152,4 +152,3 @@ Feature: Workshop submission and assessment
 
   @javascript
   Scenario: Add and assess submissions in workshop with javascript enabled
-
index affc9f5..1fd4648 100644 (file)
         }
       }
     },
+    "gherkin": {
+      "version": "4.0.0",
+      "from": "gherkin@4.0.0",
+      "resolved": "https://registry.npmjs.org/gherkin/-/gherkin-4.0.0.tgz"
+    },
+    "gherkin-lint": {
+      "version": "1.1.3",
+      "from": "gherkin-lint@>=1.1.3 <2.0.0",
+      "resolved": "https://registry.npmjs.org/gherkin-lint/-/gherkin-lint-1.1.3.tgz"
+    },
     "glob": {
       "version": "7.0.5",
       "from": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
index 01dc1dc..2a7d142 100644 (file)
@@ -5,6 +5,7 @@
   "devDependencies": {
     "async": "1.5.2",
     "eslint": "3.7.1",
+    "gherkin-lint": "1.1.3",
     "grunt": "1.0.1",
     "grunt-contrib-less": "1.3.0",
     "grunt-contrib-uglify": "1.0.1",
index d6a267c..65fb58a 100644 (file)
@@ -47,4 +47,3 @@ Feature: A teacher can duplicate questions in the question bank
     And I press "Cancel"
     Then I should see "Test question to be copied"
     And the field "Select a category" matches value "Test questions (1)"
-
index dc78535..89425f5 100644 (file)
@@ -1,7 +1,7 @@
 @qtype @qtype_ddmarker @_switch_window
-Feature: Preview a drag-drop onto image question
+Feature: Preview a drag-drop marker question
   As a teacher
-  In order to check my drag-drop onto image questions will work for students
+  In order to check my drag-drop marker questions will work for students
   I need to preview them
 
   Background:
index ce3f32f..50cccc6 100644 (file)
@@ -23,4 +23,4 @@ Feature: Test creating a Description question
       | Question name                      | description-001                                                |
       | Question text                      | Instructions about the following questions.                    |
       | General feedback                   | Why actually the field 'General feedback' used in this qytype? |
-      Then I should see "description-001"
+    Then I should see "description-001"
index 1c56f19..3adfca6 100644 (file)
@@ -22,8 +22,8 @@ Feature: Test exporting Essay questions
       | Test questions   | essay | essay-001 | editor           |
       | Test questions   | essay | essay-002 | editorfilepicker |
       | Test questions   | essay | essay-003 | plain            |
-   And I log in as "teacher1"
-   And I follow "Course 1"
+    And I log in as "teacher1"
+    And I follow "Course 1"
 
   Scenario: Export 3 Essay questions
     When I navigate to "Export" node in "Course administration > Question bank"
index 97a3fd8..83cc4d7 100644 (file)
@@ -5,7 +5,7 @@ Feature: Import and export select missing words questions
   I need to be able to import and export them
 
   Background:
-     Given the following "users" exist:
+    Given the following "users" exist:
       | username | firstname | lastname | email               |
       | teacher1 | T1        | Teacher1 | teacher1@moodle.com |
     And the following "courses" exist:
index b41bdf1..3044107 100644 (file)
@@ -24,7 +24,6 @@ Feature: Preview a Short answer question
     And I follow "Course 1"
     And I navigate to "Question bank" node in "Course administration"
 
-
   @javascript @_switch_window
   Scenario: Preview a Short answer question with correct answer
     When I click on "Preview" "link" in the "shortanswer-001" "table_row"
index 4c09263..ea36b1d 100644 (file)
@@ -27,7 +27,7 @@ Feature: Test creating a True/False question
       | Correct answer                     | False                                      |
       | Feedback for the response 'True'.  | Well done!                                 |
       | Feedback for the response 'False'. | Read more about England.                   |
-      Then I should see "true-false-001"
+    Then I should see "true-false-001"
 
   Scenario: Create a True/False question with Correct answer as True
     When I add a "True/False" question filling the form with:
@@ -38,4 +38,4 @@ Feature: Test creating a True/False question
       | Correct answer                     | True                                   |
       | Feedback for the response 'True'.  | Well done!                             |
       | Feedback for the response 'False'. | Read more about England.               |
-      Then I should see "true-false-002"
+    Then I should see "true-false-002"
index 44daf7b..7820c1e 100644 (file)
@@ -76,4 +76,3 @@ Feature: In a report, admin can see loglive data
     And I wait "8" seconds
     And I should see "Test name2"
     And I log out
-
index bd1f62b..172d050 100644 (file)
@@ -91,7 +91,6 @@ if ($context->contextlevel == CONTEXT_COURSE) {
         print_error('notyourinstances', 'repository');
     }
     $user = $USER;
-    $PAGE->set_pagelayout('mydashboard');
 } else {
     print_error('invalidcontext');
 }
index 5ff6f84..32c99f4 100644 (file)
@@ -48,7 +48,7 @@ $PAGE->set_url('/user/files.php');
 $PAGE->set_context($context);
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 $PAGE->set_pagetype('user-files');
 
 $maxbytes = $CFG->userquota;
index 3c67d27..2271953 100644 (file)
@@ -21,7 +21,7 @@ Feature: Access to preferences page
       | student1 | C1 | student |
       | student2 | C1 | student |
       | teacher1 | C1 | editingteacher |
-   And the following "system role assigns" exist:
+    And the following "system role assigns" exist:
       | user | course | role |
       | manager1 | Acceptance test site | manager |