MDL-79986 course: Create new course/section.php page

The page course/section.php has been created, to display the content of a
single section. This page will only accept sectionid (to get rid of the
legacy sectionnumber).

Some features of this page:
- The General section won't be displayed anymore above the selected
section.
- In the main course page content, regardless of the Course layout ("All
sections on one page" vs "One section per page"), all the section names
will link to the new page (except when editing mode is on).
This commit is contained in:
Sara Arjona
2023-12-01 09:15:48 +01:00
parent d53dc05e9e
commit 6792a40924
27 changed files with 685 additions and 219 deletions
+6 -2
View File
@@ -57,7 +57,11 @@ class block_section_links_renderer extends plugin_renderer_base {
if ($section->highlight) {
$sectiontext = html_writer::tag('strong', $sectiontext);
}
$html .= html_writer::link(course_get_url($course, $section->section), $sectiontext, $attributes);
$html .= html_writer::link(
course_get_url($course, $section->section, ['navigation' => true]),
$sectiontext,
$attributes
);
$html .= html_writer::end_tag('li').' ';
}
$html .= html_writer::end_tag('ol');
@@ -78,4 +82,4 @@ class block_section_links_renderer extends plugin_renderer_base {
return $html;
}
}
}
+17 -7
View File
@@ -711,15 +711,14 @@ abstract class base {
* @param int|stdClass $section Section object from database or just field course_sections.section
* if null the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* 'navigation' (bool) if true and section not empty, the function returns section page; otherwise, it returns course page.
* 'sr' (int) used by course formats to specify to which section to return
* 'expanded' (bool) if true the section will be shown expanded, true by default
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
global $CFG;
$course = $this->get_course();
$url = new moodle_url('/course/view.php', array('id' => $course->id));
$url = new moodle_url('/course/view.php', ['id' => $course->id]);
if (array_key_exists('sr', $options)) {
$sectionno = $options['sr'];
@@ -728,9 +727,10 @@ abstract class base {
} else {
$sectionno = $section;
}
if (empty($CFG->linkcoursesections) && !empty($options['navigation']) && $sectionno !== null) {
// By default assume that sections are never displayed on separate pages.
return null;
if ((!empty($options['navigation']) || array_key_exists('sr', $options)) && $sectionno !== null) {
// Display section on separate page.
$sectioninfo = $this->get_section($sectionno);
return new moodle_url('/course/section.php', ['id' => $sectioninfo->id]);
}
if ($this->uses_sections() && $sectionno !== null) {
// The url includes the parameter to expand the section by default.
@@ -743,6 +743,7 @@ abstract class base {
}
$url->set_anchor('section-'.$sectionno);
}
return $url;
}
@@ -1915,4 +1916,13 @@ abstract class base {
return get_fast_modinfo($course)->get_section_info_by_id($newsection->id);
}
/**
* Get the required javascript files for the course format.
*
* @return array The list of javascript files required by the course format.
*/
public function get_required_jsfiles(): array {
return [];
}
}
@@ -86,12 +86,8 @@ class content implements named_templatable, renderable {
global $PAGE;
$format = $this->format;
// Most formats uses section 0 as a separate section so we remove from the list.
$sections = $this->export_sections($output);
$initialsection = '';
if (!empty($sections)) {
$initialsection = array_shift($sections);
}
$data = (object)[
'title' => $format->page_title(), // This method should be in the course_format class.
@@ -188,7 +184,6 @@ class content implements named_templatable, renderable {
$singlesection = $this->format->get_section_number();
if ($singlesection) {
return [
$modinfo->get_section_info(0),
$modinfo->get_section_info($singlesection),
];
}
@@ -147,7 +147,8 @@ class section implements named_templatable, renderable {
'summary' => $summary->export_for_template($output),
'highlightedlabel' => $format->get_section_highlighted_name(),
'sitehome' => $course->id == SITEID,
'editing' => $PAGE->user_is_editing()
'editing' => $PAGE->user_is_editing(),
'displayonesection' => ($course->id != SITEID && $format->get_section_number() !== 0),
];
$haspartials = [];
@@ -297,9 +297,8 @@ class controlmenu implements named_templatable, renderable {
], $coursecontext)
) {
$sectionlink = new moodle_url(
'/course/view.php',
['id' => $course->id],
"sectionid-{$section->id}-title"
'/course/section.php',
['id' => $section->id]
);
$controls['permalink'] = [
'url' => $sectionlink,
@@ -76,14 +76,28 @@ class header implements named_templatable, renderable {
'id' => $section->id,
];
$data->title = $output->section_title_without_link($section, $course);
$data->editing = $format->show_editor();
if ($course->id == SITEID) {
$data->title = $output->section_title_without_link($section, $course);
$data->sitehome = true;
} else {
if ($format->get_section_number() === 0) {
// All sections are displayed.
if (!$data->editing) {
$data->title = $output->section_title($section, $course);
} else {
$data->title = $output->section_title_without_link($section, $course);
}
} else {
// Only one section is displayed.
$data->displayonesection = true;
$data->title = $output->section_title_without_link($section, $course);
}
}
$coursedisplay = $format->get_course_display();
$data->headerdisplaymultipage = false;
if ($coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$data->headerdisplaymultipage = true;
$data->title = $output->section_title($section, $course);
}
$data->headerdisplaymultipage = ($coursedisplay == COURSE_DISPLAY_MULTIPAGE);
if ($section->section > $format->get_last_section_number()) {
// Stealth sections (orphaned) has special title.
@@ -94,16 +108,8 @@ class header implements named_templatable, renderable {
$data->ishidden = true;
}
if ($course->id == SITEID) {
$data->sitehome = true;
}
$data->editing = $format->show_editor();
if (!$format->show_editor() && $coursedisplay == COURSE_DISPLAY_MULTIPAGE && empty($data->issinglesection)) {
if ($section->uservisible) {
$data->url = course_get_url($course, $section->section);
}
if (!$data->editing && $section->uservisible) {
$data->url = course_get_url($course, $section->section, ['navigation' => true]);
}
$data->name = get_section_name($course, $section);
$data->selecttext = $format->get_format_string('selectsection', $data->name);
@@ -100,7 +100,7 @@ class sectionnavigation implements named_templatable, renderable {
$data->previoushidden = true;
}
$data->previousname = get_section_name($course, $sections[$back]);
$data->previousurl = course_get_url($course, $back);
$data->previousurl = course_get_url($course, $back, ['navigation' => true]);
$data->hasprevious = true;
}
$back--;
@@ -114,7 +114,7 @@ class sectionnavigation implements named_templatable, renderable {
$data->nexthidden = true;
}
$data->nextname = get_section_name($course, $sections[$forward]);
$data->nexturl = course_get_url($course, $forward);
$data->nexturl = course_get_url($course, $forward, ['navigation' => true]);
$data->hasnext = true;
}
$forward++;
@@ -83,7 +83,7 @@ class section implements renderable {
'rawtitle' => $section->name,
'cmlist' => [],
'visible' => !empty($section->visible),
'sectionurl' => course_get_url($course, $section->section)->out(),
'sectionurl' => course_get_url($course, $section->section, ['navigation' => true])->out(),
'current' => $format->is_section_current($section),
'indexcollapsed' => $indexcollapsed,
'contentcollapsed' => $contentcollapsed,
+3 -13
View File
@@ -45,22 +45,12 @@ class format_singleactivity extends core_courseformat\base {
* @param int|stdClass $section Section object from database or just field course_sections.section
* if null the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* 'navigation' (bool) ignored by this format
* 'sr' (int) ignored by this format
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
$sectionnum = $section;
if (is_object($sectionnum)) {
$sectionnum = $section->section;
}
if ($sectionnum == 1) {
return new moodle_url('/course/view.php', array('id' => $this->courseid, 'section' => 1));
}
if (!empty($options['navigation']) && $section !== null) {
return null;
}
return new moodle_url('/course/view.php', array('id' => $this->courseid));
return new moodle_url('/course/view.php', ['id' => $this->courseid]);
}
/**
@@ -0,0 +1,77 @@
<?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/>.
namespace format_singleactivity;
/**
* Single activity course format related unit tests.
*
* @package format_singleactivity
* @copyright 2023 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \format_singleactivity
*/
class format_singleactivity_test extends \advanced_testcase {
/**
* Test for get_view_url().
*
* @covers ::get_view_url
*/
public function test_get_view_url(): void {
global $CFG;
$this->resetAfterTest();
// Generate a course with two sections (0 and 1) and two modules.
$generator = $this->getDataGenerator();
$course1 = $generator->create_course(['format' => 'singleactivity']);
course_create_sections_if_missing($course1, [0, 1]);
$data = (object)['id' => $course1->id];
$format = course_get_format($course1);
$format->update_course_format_options($data);
// In page.
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
// Navigation.
$this->assertStringContainsString('course/view.php', $format->get_view_url(0));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['sr' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['sr' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['sr' => 0]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['sr' => 0]));
}
/**
* Test get_required_jsfiles().
*
* @covers ::get_required_jsfiles
*/
public function test_get_required_jsfiles(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course(['format' => 'singleactivity']);
$format = course_get_format($course);
$this->assertEmpty($format->get_required_jsfiles());
}
}
+3 -6
View File
@@ -41,15 +41,12 @@ class format_social extends core_courseformat\base {
* @param int|stdClass $section Section object from database or just field course_sections.section
* if null the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* 'navigation' (bool) ignored by this format
* 'sr' (int) ignored by this format
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
if (!empty($options['navigation']) && $section !== null) {
return null;
}
return new moodle_url('/course/view.php', array('id' => $this->courseid));
return new moodle_url('/course/view.php', ['id' => $this->courseid]);
}
/**
@@ -0,0 +1,77 @@
<?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/>.
namespace format_social;
/**
* Social course format related unit tests.
*
* @package format_social
* @copyright 2023 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \format_social
*/
class format_social_test extends \advanced_testcase {
/**
* Test for get_view_url().
*
* @covers ::get_view_url
*/
public function test_get_view_url(): void {
global $CFG;
$this->resetAfterTest();
// Generate a course with two sections (0 and 1) and two modules.
$generator = $this->getDataGenerator();
$course1 = $generator->create_course(['format' => 'social']);
course_create_sections_if_missing($course1, [0, 1]);
$data = (object)['id' => $course1->id];
$format = course_get_format($course1);
$format->update_course_format_options($data);
// In page.
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
// Navigation.
$this->assertStringContainsString('course/view.php', $format->get_view_url(0));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['sr' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['sr' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0, ['sr' => 0]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1, ['sr' => 0]));
}
/**
* Test get_required_jsfiles().
*
* @covers ::get_required_jsfiles
*/
public function test_get_required_jsfiles(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course(['format' => 'social']);
$format = course_get_format($course);
$this->assertEmpty($format->get_required_jsfiles());
}
}
@@ -148,7 +148,7 @@
{{/header}}
</div>
<div id="coursecontentcollapse{{num}}"
class="content {{^iscoursedisplaymultipage}}{{^sitehome}}course-content-item-content collapse {{^contentcollapsed}}show{{/contentcollapsed}}{{/sitehome}}{{/iscoursedisplaymultipage}}">
class="content {{^iscoursedisplaymultipage}}{{^sitehome}}{{^displayonesection}}course-content-item-content collapse {{^contentcollapsed}}show{{/contentcollapsed}}{{/displayonesection}}{{/sitehome}}{{/iscoursedisplaymultipage}}">
<div class="{{#hasavailability}}description{{/hasavailability}} my-3" data-for="sectioninfo">
{{#summary}}
{{$ core_courseformat/local/content/section/summary }}
@@ -47,30 +47,36 @@
</h2>
{{/sitehome}}
{{^sitehome}}
<div class="d-flex align-items-start position-relative">
<a role="button"
data-toggle="collapse"
data-for="sectiontoggler"
href="#coursecontentcollapse{{num}}"
id="collapssesection{{num}}"
aria-expanded="{{^contentcollapsed}}true{{/contentcollapsed}}{{#contentcollapsed}}false{{/contentcollapsed}}"
aria-controls="coursecontentcollapse{{num}}"
class="btn btn-icon mr-1 icons-collapse-expand justify-content-center
{{^editing}} stretched-link {{/editing}}
{{#contentcollapsed}} collapsed {{/contentcollapsed}}"
aria-label="{{name}}">
<span class="expanded-icon icon-no-margin p-2" title="{{#str}} collapse, core {{/str}}">
{{#pix}} t/expandedchevron, core {{/pix}}
</span>
<span class="collapsed-icon icon-no-margin p-2" title="{{#str}} expand, core {{/str}}">
<span class="dir-rtl-hide">{{#pix}} t/collapsedchevron, core {{/pix}}</span>
<span class="dir-ltr-hide">{{#pix}} t/collapsedchevron_rtl, core {{/pix}}</span>
</span>
</a>
<h3 class="sectionname course-content-item d-flex align-self-stretch align-items-center mb-0"
id="sectionid-{{id}}-title" data-for="section_title" data-id="{{id}}" data-number="{{num}}">
{{#displayonesection}}
<h3 id="sectionid-{{id}}-title" class="sectionname">
{{{title}}}
</h3>
</div>
{{/displayonesection}}
{{^displayonesection}}
<div class="d-flex align-items-start position-relative">
<a role="button"
data-toggle="collapse"
data-for="sectiontoggler"
href="#coursecontentcollapse{{num}}"
id="collapssesection{{num}}"
aria-expanded="{{^contentcollapsed}}true{{/contentcollapsed}}{{#contentcollapsed}}false{{/contentcollapsed}}"
aria-controls="coursecontentcollapse{{num}}"
class="btn btn-icon mr-1 icons-collapse-expand justify-content-center
{{#contentcollapsed}} collapsed {{/contentcollapsed}}"
aria-label="{{name}}">
<span class="expanded-icon icon-no-margin p-2" title="{{#str}} collapse, core {{/str}}">
{{#pix}} t/expandedchevron, core {{/pix}}
</span>
<span class="collapsed-icon icon-no-margin p-2" title="{{#str}} expand, core {{/str}}">
<span class="dir-rtl-hide">{{#pix}} t/collapsedchevron, core {{/pix}}</span>
<span class="dir-ltr-hide">{{#pix}} t/collapsedchevron_rtl, core {{/pix}}</span>
</span>
</a>
<h3 class="sectionname course-content-item d-flex align-self-stretch align-items-center mb-0"
id="sectionid-{{id}}-title" data-for="section_title" data-id="{{id}}" data-number="{{num}}">
{{{title}}}
</h3>
</div>
{{/displayonesection}}
{{/sitehome}}
{{/headerdisplaymultipage}}
+29 -15
View File
@@ -20,6 +20,7 @@
* @package core_course
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_courseformat\base
* @coversDefaultClass \core_courseformat\base
*/
class base_test extends advanced_testcase {
@@ -199,14 +200,14 @@ class base_test extends advanced_testcase {
}
/**
* Test for get_view_url() to ensure that the url is only given for the correct cases
* Test for get_view_url().
*
* @covers ::get_view_url
*/
public function test_get_view_url() {
public function test_get_view_url(): void {
global $CFG;
$this->resetAfterTest();
$linkcoursesections = $CFG->linkcoursesections;
// Generate a course with two sections (0 and 1) and two modules. Course format is set to 'testformat'.
// This will allow us to test the default implementation of get_view_url.
$generator = $this->getDataGenerator();
@@ -218,22 +219,20 @@ class base_test extends advanced_testcase {
$format->update_course_format_options($data);
// In page.
$CFG->linkcoursesections = 0;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
// Navigation.
$CFG->linkcoursesections = 0;
$this->assertNull($format->get_view_url(1, ['navigation' => 1]));
$this->assertNull($format->get_view_url(0, ['navigation' => 1]));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(1, ['navigation' => 1]));
$this->assertNotEmpty($format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['navigation' => 1]));
// When sr parameter is defined, the section.php page should be returned.
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 0]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 0]));
// Expand section.
// The current course format $format uses the format 'testformat' which does not use sections.
@@ -756,6 +755,21 @@ class base_test extends advanced_testcase {
],
];
}
/**
* Test get_required_jsfiles().
*
* @covers ::get_required_jsfiles
*/
public function test_get_required_jsfiles(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course(['format' => 'testformat']);
$format = course_get_format($course);
$this->assertEmpty($format->get_required_jsfiles());
}
}
/**
@@ -1,5 +1,5 @@
@core @core_courseformat @core_course @show_editor @javascript
Feature: Bulk course section actions one section per page.
Feature: Bulk course section actions one section per page
In order to edit the course section in one section per page setting
As a teacher
I need to be able to edit sections in bulk in both display modes.
@@ -33,8 +33,10 @@ Feature: Bulk course section actions one section per page.
Scenario: Bulk section edit is only available when multiple sections are displayed
Given I click on "Select topic Topic 1" "checkbox"
And I should see "1 selected" in the "sticky-footer" "region"
And I click on "Close bulk actions" "button" in the "sticky-footer" "region"
# Move to single topic page.
When I click on "Topic 1" "link" in the "region-main" "region"
And I open section "1" edit menu
When I click on "View" "link" in the "Topic 1" "section"
And I click on "Bulk actions" "button"
Then "Select topic Topic 1" "checkbox" should not exist
@@ -1,5 +1,5 @@
@core @core_courseformat @show_editor
Feature: Verify edit utils availability.
Feature: Verify edit utils availability
In order to edit the course activities
As a student with capability 'moodle/course:manageactivities'
I need to be able to use the edit utils.
@@ -49,16 +49,17 @@ Feature: Verify edit utils availability.
Then I should not see "Edit mode"
@javascript
Scenario: Edit tools should be available to students with the capability 'moodle/course:manageactivities',
but should not be allowed to add and edit sections without having 'moodle/course:update'
Scenario: Edit tools should be available to students with manageactivities capability but not allowed to add sections without course:update
Given I log in as "author1"
When I am on "Course 1" course homepage
And I turn editing mode on
Then I should see "Add an activity or resource"
And I should not see "Add topic"
But I should not see "Add topic"
And I open "Activity sample 1" actions menu
And I should see "Edit settings"
And ".section_action_menu" "css_element" should not exist in the "Topic 1" "section"
And I open section "1" edit menu
And I should not see "Edit settings"
And I should see "View"
@javascript
Scenario: Section adding should be available to students if they also have the capability 'moodle/course:update'.
@@ -0,0 +1,82 @@
@core @core_courseformat
Feature: Single section course page
In order to improve the course page
As a user
I need to be able to see a section in a single page
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
| category | 0 |
| numsections | 3 |
And the following "activities" exist:
| activity | name | course | idnumber | section |
| assign | Activity sample 0.1 | C1 | sample1 | 0 |
| assign | Activity sample 1.1 | C1 | sample1 | 1 |
| assign | Activity sample 1.2 | C1 | sample2 | 1 |
| assign | Activity sample 1.3 | C1 | sample3 | 1 |
| assign | Activity sample 2.1 | C1 | sample3 | 2 |
| assign | Activity sample 2.2 | C1 | sample3 | 2 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
Given I am on the "C1" "Course" page logged in as "teacher1"
@javascript
Scenario: Collapsed sections are always expanded in the single section page
Given I press "Collapse all"
And I should not see "Activity sample 1.1" in the "region-main" "region"
When I click on "Topic 1" "link" in the "region-main" "region"
Then I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
And I should see "Activity sample 1.3"
And I should not see "Activity sample 2.1" in the "region-main" "region"
And I should not see "Activity sample 2.1" in the "region-main" "region"
Scenario: General section is not displayed in the single section page
When I click on "Topic 1" "link" in the "region-main" "region"
Then I should not see "General" in the "region-main" "region"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
And I should see "Activity sample 1.3"
And I should not see "Activity sample 2.1" in the "region-main" "region"
And I should not see "Activity sample 2.1" in the "region-main" "region"
@javascript
Scenario: The view action for sections displays the single section page
Given I turn editing mode on
And I open section "1" edit menu
When I click on "View" "link" in the "Topic 1" "section"
Then I should not see "General" in the "region-main" "region"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
And I should see "Activity sample 1.3"
And I should not see "Activity sample 2.1" in the "region-main" "region"
And I should not see "Activity sample 2.1" in the "region-main" "region"
And I am on "Course 1" course homepage
And I open section "2" edit menu
And I click on "View" "link" in the "Topic 2" "section"
And I should not see "General" in the "region-main" "region"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should not see "Activity sample 1.1"
And I should not see "Activity sample 1.2"
And I should not see "Activity sample 1.3"
And I should see "Activity sample 2.1" in the "region-main" "region"
And I should see "Activity sample 2.1" in the "region-main" "region"
# The following steps will need to be changed in MDL-80248, when the General section will be displayed in isolation.
But I am on "Course 1" course homepage
And I open section "0" edit menu
And I click on "View" "link" in the "General" "section"
And I should see "General" in the "region-main" "region"
And I should see "Activity sample 0.1" in the "region-main" "region"
And I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
And I should see "Activity sample 1.3"
And I should see "Activity sample 2.1" in the "region-main" "region"
And I should see "Activity sample 2.1" in the "region-main" "region"
+19 -29
View File
@@ -108,45 +108,26 @@ class format_topics extends core_courseformat\base {
* @param int|stdClass $section Section object from database or just field course_sections.section
* if omitted the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* 'navigation' (bool) if true and section not empty, the function returns section page; otherwise, it returns course page.
* 'sr' (int) used by course formats to specify to which section to return
* @return null|moodle_url
*/
public function get_view_url($section, $options = []) {
global $CFG;
$course = $this->get_course();
$url = new moodle_url('/course/view.php', ['id' => $course->id]);
$sr = null;
if (array_key_exists('sr', $options)) {
$sr = $options['sr'];
}
if (is_object($section)) {
$sectionno = $options['sr'];
} else if (is_object($section)) {
$sectionno = $section->section;
} else {
$sectionno = $section;
}
if ($sectionno !== null) {
if ($sr !== null) {
if ($sr) {
$usercoursedisplay = COURSE_DISPLAY_MULTIPAGE;
$sectionno = $sr;
} else {
$usercoursedisplay = COURSE_DISPLAY_SINGLEPAGE;
}
} else {
$usercoursedisplay = $course->coursedisplay ?? COURSE_DISPLAY_SINGLEPAGE;
}
if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$url->param('section', $sectionno);
} else {
if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
return null;
}
$url->set_anchor('section-'.$sectionno);
}
if ((!empty($options['navigation']) || array_key_exists('sr', $options)) && $sectionno !== null) {
// Display section on separate page.
$sectioninfo = $this->get_section($sectionno);
return new moodle_url('/course/section.php', ['id' => $sectioninfo->id]);
}
return $url;
return new moodle_url('/course/view.php', ['id' => $course->id]);
}
/**
@@ -457,6 +438,15 @@ class format_topics extends core_courseformat\base {
$formatoptions['indentation'] = get_config('format_topics', 'indentation');
return $formatoptions;
}
/**
* Get the required javascript files for the course format.
*
* @return array The list of javascript files required by the course format.
*/
public function get_required_jsfiles(): array {
return ['/course/format/topics/format.js'];
}
}
/**
@@ -29,6 +29,7 @@ require_once($CFG->dirroot . '/course/lib.php');
* @package format_topics
* @copyright 2015 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \format_topics
*/
class format_topics_test extends \advanced_testcase {
@@ -232,16 +233,14 @@ class format_topics_test extends \advanced_testcase {
}
/**
* Test for get_view_url() to ensure that the url is only given for the correct cases.
* Test for get_view_url().
*
* @return void
* @covers ::get_view_url
*/
public function test_get_view_url() {
public function test_get_view_url(): void {
global $CFG;
$this->resetAfterTest();
$linkcoursesections = $CFG->linkcoursesections;
// Generate a course with two sections (0 and 1) and two modules.
$generator = $this->getDataGenerator();
$course1 = $generator->create_course(['format' => 'topics']);
@@ -252,21 +251,34 @@ class format_topics_test extends \advanced_testcase {
$format->update_course_format_options($data);
// In page.
$CFG->linkcoursesections = 0;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
// Navigation.
$CFG->linkcoursesections = 0;
$this->assertNull($format->get_view_url(1, ['navigation' => 1]));
$this->assertNull($format->get_view_url(0, ['navigation' => 1]));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(1, ['navigation' => 1]));
$this->assertNotEmpty($format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['navigation' => 1]));
// When sr parameter is defined, the section.php page should be returned.
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 0]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 0]));
}
/**
* Test get_required_jsfiles().
*
* @covers ::get_required_jsfiles
*/
public function test_get_required_jsfiles(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course(['format' => 'topics']);
$format = course_get_format($course);
$this->assertNotEmpty($format->get_required_jsfiles());
}
}
+19 -29
View File
@@ -118,45 +118,26 @@ class format_weeks extends core_courseformat\base {
* @param int|stdClass $section Section object from database or just field course_sections.section
* if omitted the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* 'navigation' (bool) if true and section not empty, the function returns section page; otherwise, it returns course page.
* 'sr' (int) used by course formats to specify to which section to return
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
global $CFG;
$course = $this->get_course();
$url = new moodle_url('/course/view.php', array('id' => $course->id));
$sr = null;
if (array_key_exists('sr', $options)) {
$sr = $options['sr'];
}
if (is_object($section)) {
$sectionno = $options['sr'];
} else if (is_object($section)) {
$sectionno = $section->section;
} else {
$sectionno = $section;
}
if ($sectionno !== null) {
if ($sr !== null) {
if ($sr) {
$usercoursedisplay = COURSE_DISPLAY_MULTIPAGE;
$sectionno = $sr;
} else {
$usercoursedisplay = COURSE_DISPLAY_SINGLEPAGE;
}
} else {
$usercoursedisplay = $course->coursedisplay ?? COURSE_DISPLAY_SINGLEPAGE;
}
if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$url->param('section', $sectionno);
} else {
if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
return null;
}
$url->set_anchor('section-'.$sectionno);
}
if ((!empty($options['navigation']) || array_key_exists('sr', $options)) && $sectionno !== null) {
// Display section on separate page.
$sectioninfo = $this->get_section($sectionno);
return new moodle_url('/course/section.php', ['id' => $sectioninfo->id]);
}
return $url;
return new moodle_url('/course/view.php', ['id' => $course->id]);
}
/**
@@ -631,6 +612,15 @@ class format_weeks extends core_courseformat\base {
$formatoptions['indentation'] = get_config('format_weeks', 'indentation');
return $formatoptions;
}
/**
* Get the required javascript files for the course format.
*
* @return array The list of javascript files required by the course format.
*/
public function get_required_jsfiles(): array {
return ['/course/format/weeks/format.js'];
}
}
/**
+28 -15
View File
@@ -29,6 +29,7 @@ require_once($CFG->dirroot . '/course/lib.php');
* @package format_weeks
* @copyright 2015 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \format_weeks
*/
class format_weeks_test extends \advanced_testcase {
@@ -229,14 +230,14 @@ class format_weeks_test extends \advanced_testcase {
}
/**
* Test for get_view_url() to ensure that the url is only given for the correct cases
* Test for get_view_url().
*
* @covers ::get_view_url
*/
public function test_get_view_url() {
public function test_get_view_url(): void {
global $CFG;
$this->resetAfterTest();
$linkcoursesections = $CFG->linkcoursesections;
// Generate a course with two sections (0 and 1) and two modules.
$generator = $this->getDataGenerator();
$course1 = $generator->create_course(array('format' => 'weeks'));
@@ -247,22 +248,34 @@ class format_weeks_test extends \advanced_testcase {
$format->update_course_format_options($data);
// In page.
$CFG->linkcoursesections = 0;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(null));
$this->assertNotEmpty($format->get_view_url(0));
$this->assertNotEmpty($format->get_view_url(1));
// Navigation.
$CFG->linkcoursesections = 0;
$this->assertNull($format->get_view_url(1, ['navigation' => 1]));
$this->assertNull($format->get_view_url(0, ['navigation' => 1]));
$CFG->linkcoursesections = 1;
$this->assertNotEmpty($format->get_view_url(1, ['navigation' => 1]));
$this->assertNotEmpty($format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/view.php', $format->get_view_url(0));
$this->assertStringContainsString('course/view.php', $format->get_view_url(1));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['navigation' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['navigation' => 1]));
// When sr parameter is defined, the section.php page should be returned.
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 1]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(0, ['sr' => 0]));
$this->assertStringContainsString('course/section.php', $format->get_view_url(1, ['sr' => 0]));
}
/**
* Test get_required_jsfiles().
*
* @covers ::get_required_jsfiles
*/
public function test_get_required_jsfiles(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course(['format' => 'weeks']);
$format = course_get_format($course);
$this->assertNotEmpty($format->get_required_jsfiles());
}
}
+193
View File
@@ -0,0 +1,193 @@
<?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/>.
/**
* Display a course section.
*
* @package core_course
* @copyright 2023 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once('lib.php');
require_once($CFG->libdir.'/completionlib.php');
redirect_if_major_upgrade_required();
$sectionid = required_param('id', PARAM_INT);
// This parameter is used by the classic theme to force editing on.
$edit = optional_param('edit', -1, PARAM_BOOL);
$section = $DB->get_record('course_sections', ['id' => $sectionid], '*', MUST_EXIST);
// Defined here to avoid notices on errors.
$PAGE->set_url('/course/section.php', ['id' => $sectionid]);
if ($section->course == SITEID) {
// The home page is not a real course.
redirect($CFG->wwwroot .'/?redirect=0');
}
$course = get_course($section->course);
// Fix course format if it is no longer installed.
$format = course_get_format($course);
$course->format = $format->get_format();
// When the course format doesn't support sections, redirect to course page.
if (!course_format_uses_sections($course->format)) {
redirect(new moodle_url('/course/view.php', ['id' => $course->id]));
}
// Prevent caching of this page to stop confusion when changing page after making AJAX changes.
$PAGE->set_cacheable(false);
context_helper::preload_course($course->id);
$context = context_course::instance($course->id, MUST_EXIST);
require_login($course);
// Must set layout before getting section info. See MDL-47555.
$PAGE->set_pagelayout('course');
$PAGE->add_body_class('limitedwidth');
// Get section details and check it exists.
$modinfo = get_fast_modinfo($course);
$coursesections = $modinfo->get_section_info($section->section, MUST_EXIST);
// Check user is allowed to see it.
if (!$coursesections->uservisible) {
// Check if coursesection has conditions affecting availability and if
// so, output availability info.
if ($coursesections->visible && $coursesections->availableinfo) {
$sectionname = get_section_name($course, $coursesections);
$message = get_string('notavailablecourse', '', $sectionname);
redirect(course_get_url($course), $message, null, \core\output\notification::NOTIFY_ERROR);
} else {
// Note: We actually already know they don't have this capability
// or uservisible would have been true; this is just to get the
// correct error message shown.
require_capability('moodle/course:viewhiddensections', $context);
}
}
$PAGE->set_pagetype('course-view-' . $course->format);
$PAGE->set_other_editing_capability('moodle/course:update');
$PAGE->set_other_editing_capability('moodle/course:manageactivities');
$PAGE->set_other_editing_capability('moodle/course:activityvisibility');
$PAGE->set_other_editing_capability('moodle/course:sectionvisibility');
$PAGE->set_other_editing_capability('moodle/course:movesections');
$renderer = $PAGE->get_renderer('format_' . $course->format);
// This is used by the Classic theme to change the editing mode based on the 'edit' parameter value.
if (!isset($USER->editing)) {
$USER->editing = 0;
}
if ($PAGE->user_allowed_editing()) {
if (($edit == 1) && confirm_sesskey()) {
$USER->editing = 1;
$url = new moodle_url($PAGE->url, ['notifyeditingon' => 1]);
redirect($url);
} else if (($edit == 0) && confirm_sesskey()) {
$USER->editing = 0;
if (!empty($USER->activitycopy) && $USER->activitycopycourse == $course->id) {
$USER->activitycopy = false;
$USER->activitycopycourse = null;
}
redirect($PAGE->url);
}
}
// This is used by the Classic theme, to display the Turn editing on/off button.
// We are currently keeping the button here from 1.x to help new teachers figure out what to do, even though the link also appears
// in the course admin block. It also means you can back out of a situation where you removed the admin block.
if ($PAGE->user_allowed_editing()) {
$buttons = $OUTPUT->edit_button($PAGE->url);
$PAGE->set_button($buttons);
}
// Make the title more specific when editing, for accessibility reasons.
$editingtitle = '';
if ($PAGE->user_is_editing()) {
$editingtitle = 'editing';
}
$sectionname = get_string('sectionname', "format_$course->format");
$sectiontitle = get_section_name($course, $section);
$PAGE->set_title(
get_string(
'coursesectiontitle' . $editingtitle,
'moodle',
['course' => $course->fullname, 'sectiontitle' => $sectiontitle, 'sectionname' => $sectionname]
)
);
// Add bulk editing control.
$bulkbutton = $renderer->bulk_editing_button($format);
if (!empty($bulkbutton)) {
$PAGE->add_header_action($bulkbutton);
}
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
// Show communication room status notification.
if (core_communication\api::is_available() && has_capability('moodle/course:update', $context)) {
$communication = \core_communication\api::load_by_instance(
$context,
'core_course',
'coursecommunication',
$course->id
);
$communication->show_communication_room_status_notification();
}
// Display a warning if asynchronous backups are pending for this course.
if ($PAGE->user_is_editing()) {
require_once($CFG->dirroot . '/backup/util/helper/async_helper.class.php');
if (async_helper::is_async_pending($course->id, 'course', 'backup')) {
echo $OUTPUT->notification(get_string('pendingasyncedit', 'backup'), 'warning');
}
}
echo $renderer->container_start('course-content');
// Include course AJAX.
include_course_ajax($course, $modinfo->get_used_module_names());
$format->set_section_number($section->section);
$outputclass = $format->get_output_classname('content');
$widget = new $outputclass($format);
echo $renderer->render($widget);
// Include course format javascript files.
$jsfiles = $format->get_required_jsfiles();
foreach ($jsfiles as $jsfile) {
$PAGE->requires->js($jsfile);
}
echo $renderer->container_end();
// Trigger course viewed event.
course_view($context, $section->section);
// Load the view JS module if completion tracking is enabled for this course.
$completion = new completion_info($course);
if ($completion->is_enabled()) {
$PAGE->requires->js_call_amd('core_course/view', 'init');
}
echo $OUTPUT->footer();
@@ -31,7 +31,7 @@ Feature: Delete activity and resource works correctly
And I open "Glossary 1" actions menu
And I click on "Delete" "link" in the "Glossary 1" activity
And I click on "Delete" "button" in the "Delete activity?" "dialogue"
# Confirm that glossary is successfully deleted
# Confirm that glossary is successfully deleted.
And I should not see "Glossary 1"
# Reload the page and confirm that both the label and glossary are really deleted
And I reload the page
+18 -18
View File
@@ -16,7 +16,7 @@ Feature: Course activity controls works as expected
# * Course controls with paged mode in a section's page
@javascript @_cross_browser
Scenario Outline: General activities course controls using topics and weeks formats, and paged mode and not paged mode works as expected
Scenario Outline: Check activities using topics and weeks formats, and paged mode and not paged mode
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
@@ -30,15 +30,14 @@ Feature: Course activity controls works as expected
| activity | course | section | name |
| forum | C1 | 1 | Test forum name 1 |
| forum | C1 | 1 | Test forum name 2 |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I am on the "Course 1" course page logged in as "teacher1"
When I click on <targetpage> "link" in the "region-main" "region"
And I turn editing mode on
And I add the "Recent activity" block
And I open the action menu in "Recent activity" "block"
And I click on "Delete Recent activity block" "link"
And I click on "Delete" "button" in the "Delete block?" "dialogue"
And <belowpage> "section" <should_see_other_sections> exist
And <belowpage> "section" <should_see_other_sections> exist
And I open "Test forum name 1" actions menu
And I click on "Edit settings" "link" in the "Test forum name 1" activity
And I should see "Updating Forum"
@@ -76,14 +75,16 @@ Feature: Course activity controls works as expected
Examples:
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links | belowpage |
| topics | 0 | "General" | should | should | "Topic 2" |
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
| topics | 0 | "General" | should | should not | "Topic 2" |
| topics | 1 | "General" | should | should not | "Topic 2" |
| weeks | 0 | "General" | should | should | "8 January - 14 January" |
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
| topics | 0 | "Topic 1" | should not | should not | "Topic 2" |
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
| weeks | 0 | "General" | should | should not | "8 January - 14 January" |
| weeks | 1 | "General" | should | should not | "8 January - 14 January" |
| weeks | 0 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
Scenario Outline: General activities course controls using topics and weeks formats, and paged mode and not paged mode works as expected without javascript
Scenario Outline: Check, without javascript, activities using topics and weeks formats, and paged mode and not paged mode
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
@@ -97,9 +98,9 @@ Feature: Course activity controls works as expected
| activity | name | course | idnumber | section |
| forum | Test forum name 1 | C1 | 0001 | 1 |
| forum | Test forum name 2 | C1 | 0002 | 1 |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I am on the "Course 1" course page logged in as "teacher1"
When I click on <targetpage> "link" in the "region-main" "region"
And I turn editing mode on
And I add the "Recent activity" block
And I open the action menu in "Recent activity" "block"
And I click on "Delete Recent activity block" "link"
@@ -121,28 +122,27 @@ Feature: Course activity controls works as expected
And I should see "Test forum name 2"
And I should see "Edited test forum name 2"
And I hide section "1"
And <belowpage> "section" <should_see_other_sections> exist
And section "1" should be hidden
And all activities in section "1" should be hidden
And I show section "1"
And <belowpage> "section" <should_see_other_sections> exist
And section "1" should be visible
And the following config values are set as admin:
| unaddableblocks | | theme_boost|
And I add the "Section links" block
And <belowpage> "section" <should_see_other_sections> exist
And I should see "1 2 3 4 5" in the "Section links" "block"
And I click on "2" "link" in the "Section links" "block"
And I <should_see_other_sections_following_block_sections_links> see "Test forum name 2"
Examples:
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links | belowpage |
| topics | 0 | "General" | should | should | "Topic 2" |
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
| topics | 0 | "General" | should | should not | "Topic 2" |
| topics | 1 | "General" | should | should not | "Topic 2" |
| weeks | 0 | "General" | should | should | "8 January - 14 January" |
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
| topics | 0 | "Topic 1" | should not | should not | "Topic 2" |
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
| weeks | 0 | "General" | should | should not | "8 January - 14 January" |
| weeks | 1 | "General" | should | should not | "8 January - 14 January" |
| weeks | 0 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
@javascript
Scenario Outline: Indentation should allow one level only
+11 -5
View File
@@ -17,17 +17,19 @@ Feature: Sections can be moved
And the following "activities" exist:
| activity | name | course | idnumber | section |
| forum | Test forum name | C1 | forum1 | 1 |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
Scenario: Move up and down a section with Javascript disabled in a single page course
Given I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
When I move down section "1"
Then I should see "Test forum name" in the "Topic 2" "section"
And I move up section "2"
And I should see "Test forum name" in the "Topic 1" "section"
Scenario: Move up and down a section with Javascript disabled in the course home of a course using paged mode
Given I navigate to "Settings" in current page administration
Given I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Course layout | Show one section per page |
And I press "Save and display"
@@ -37,11 +39,13 @@ Feature: Sections can be moved
And I should see "Test forum name" in the "Topic 1" "section"
Scenario: Sections can not be moved with Javascript disabled in a section page of a course using paged mode
Given I navigate to "Settings" in current page administration
Given I am on the "Course 1" course page logged in as "teacher1"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Course layout | Show one section per page |
And I press "Save and display"
When I follow "Topic 2"
When I click on "Topic 2" "link" in the "region-main" "region"
And I turn editing mode on
Then "Topic 1" "section" should not exist
And "Topic 3" "section" should not exist
And "Move down" "link" should not exist
@@ -49,6 +53,8 @@ Feature: Sections can be moved
@javascript
Scenario: Move section with javascript
Given I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
When I open section "1" edit menu
And I click on "Move" "link" in the "Topic 1" "section"
And I click on "Topic 3" "link" in the ".modal-body" "css_element"
@@ -48,7 +48,8 @@ Feature: Course paged mode
| chat | C1 | Chat room |
When I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
And I click on <section1> "link" in the <section1> "section"
And I open section <sectionnumber1> edit menu
And I click on "View" "link" in the <section1> "section"
And I should see <section1> in the "div.single-section" "css_element"
And I should see <section2> in the ".single-section div.nextsection" "css_element"
And I should not see <prevunexistingsection> in the ".single-section" "css_element"
@@ -57,9 +58,9 @@ Feature: Course paged mode
And I should not see <prevunexistingsection> in the ".single-section" "css_element"
Examples:
| courseformat | section1 | section2 | prevunexistingsection |
| topics | "Topic 1" | "Topic 2" | "Topic 0" |
| weeks | "1 January - 7 January" | "8 January - 14 January" | "25 December - 31 December" |
| courseformat | section1 | sectionnumber1 | section2 | prevunexistingsection |
| topics | "Topic 1" | "1" | "Topic 2" | "Topic 0" |
| weeks | "1 January - 7 January" | "1" | "8 January - 14 January" | "25 December - 31 December" |
Scenario Outline: Weekly and topics course formats with Javascript disabled
Given the following "courses" exist: