Merge branch 'MDL-70829-402' of https://github.com/junpataleta/moodle into MOODLE_402_STABLE

This commit is contained in:
Andrew Nicols
2024-04-12 11:59:20 +08:00
34 changed files with 198 additions and 70 deletions
@@ -49,7 +49,7 @@
}
}}
<span>
<img height="12" src="{{profileimageurlsmall}}" alt="" role="presentation">
<img height="12" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
{{#hasidentity}}
<span><small>{{identity}}</small></span>
@@ -49,7 +49,7 @@
<p>
<ul class="inline list-inline">
{{#coursemodules}}
<li class="list-inline-item"><a href="{{url}}"><img class="icon" src="{{iconurl}}"> {{name}} </a></li>
<li class="list-inline-item"><a href="{{url}}"><img class="icon" src="{{iconurl}}" alt=""> {{name}} </a></li>
{{/coursemodules}}
{{^coursemodules}}
<li class="list-inline-item"><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
@@ -50,7 +50,7 @@
}}
<span>
<a href="{{profileurl}}" title="{{#str}}viewprofile{{/str}}">
<img height="18" src="{{profileimageurlsmall}}" alt="" role="presentation">
<img height="18" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
{{#hasidentity}}
<span><small>{{identity}}</small></span>
@@ -51,8 +51,7 @@
<div class="text-xs-center text-center mt-3" data-region="empty-message">
<img class="empty-placeholder-image-lg mt-1"
src="{{nocoursesimg}}"
alt="{{{ title }}}"
role="presentation"
alt=""
>
<h5 class="h5 mt-3 mb-0">{{{ title }}}</h5>
<p class="mt-3 mb-0">{{{ intro }}}</p>
@@ -70,3 +70,8 @@ Feature: Zero state on my overview block
And "Create course" "button" should exist
And I click on "Create course" "button"
And I should see "Add a new course"
@accessibility
Scenario: Evaluate the accessibility of the My courses (zero state)
When I am on the "My courses" page logged in as "manager"
Then the page should meet accessibility standards
@@ -27,9 +27,8 @@
<div class="text-xs-center text-center mt-4" data-region="empty-message">
<img
src="{{noitemsimgurl}}"
alt="{{#str}} noitems, block_recentlyaccesseditems {{/str}}"
role="presentation"
alt=""
style="height: 70px; width: 70px;"
>
<p class="text-muted mt-3 mb-0">{{#str}} noitems, block_recentlyaccesseditems {{/str}}</p>
</div>
</div>
@@ -42,19 +42,21 @@
<div class="card-deck dashboard-card-deck one-row" data-region="items-list" role="list">
{{#items}}
<a class="card dashboard-card mb-1" href="{{{viewurl}}}" title="{{{name}}}" role="listitem">
<div class="card-body p-2 m-1">
<div class="d-flex text-truncate">
<div class="d-flex align-self-center activityiconcontainer {{purpose}}">
{{{icon}}}
</div>
<div class="w-100 line-height-3 text-truncate ml-2">
<h6 class="mb-0 text-truncate"><span class="clickable">{{{name}}}</span></h6>
<small class="text-truncate mb-0">{{{coursename}}}</small>
<div class="card dashboard-card" role="listitem">
<a class="mb-1" href="{{{viewurl}}}" title="{{{name}}}">
<div class="card-body p-2 m-1">
<div class="d-flex text-truncate">
<div class="d-flex align-self-center activityiconcontainer {{purpose}}">
{{{icon}}}
</div>
<div class="w-100 line-height-3 text-truncate ml-2">
<h6 class="mb-0 text-truncate"><span class="clickable">{{{name}}}</span></h6>
<small class="text-truncate mb-0">{{{coursename}}}</small>
</div>
</div>
</div>
</div>
</a>
</a>
</div>
{{/items}}
</div>
{{#hasmoreitems}}
@@ -23,15 +23,19 @@ Feature: The recently accessed items block allows users to easily access their m
| name | Test forum name |
And I log in as "student1"
@accessibility
Scenario: User has not accessed any item
Then I should see "No recent items" in the "Recently accessed items" "block"
And the page should meet accessibility standards
@accessibility
Scenario: User has accessed some items
Given I change window size to "large"
When I am on the "Test forum name" "forum activity" page
And I follow "Dashboard"
Then I should see "Test forum name" in the "Recently accessed items" "block"
And I should not see "Show more items" in the "Recently accessed items" "block"
And the page should meet accessibility standards
Scenario: User has accessed more than 3 items
Given the following "activities" exist:
@@ -0,0 +1,42 @@
@block_starredcourses
Feature: Starred courses
In order for me to quickly navigate to my favourite courses
As a user
I must be able to add them to the Starred courses block
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| shortname | fullname |
| C1 | Course 1 |
| C2 | Course 2 |
| C3 | Course 3 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| student1 | C2 | student |
| student1 | C3 | student |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| starredcourses | User | student1 | my-index | content |
@accessibility @javascript
Scenario: User has no starred courses
Given I log in as "student1"
Then I should see "No starred courses"
And the page should meet accessibility standards
@accessibility @javascript
Scenario: User has starred courses
Given I am on the "My courses" page logged in as "student1"
And I click on "Actions for course Course 1" "button"
And I click on "Star for Course 1" "link"
And I click on "Actions for course Course 3" "button"
And I click on "Star for Course 3" "link"
When I follow "Dashboard"
Then the page should meet accessibility standards
And I should see "Course 1" in the "Starred courses" "block"
And I should see "Course 3" in the "Starred courses" "block"
But I should not see "Course 2" in the "Starred courses" "block"
@@ -86,3 +86,10 @@ Feature: Allow teachers to bulk edit activity completion rules in a course.
And I should see "With conditions" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' row ')][.//*[text() = 'Test assignment two']]" "xpath_element"
And I should see "Student must receive a passing grade to complete this activity" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' row ')][.//*[text() = 'Test assignment two']]" "xpath_element"
And I should not see "Completion expected on" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' row ')][.//*[text() = 'Test assignment two']]" "xpath_element"
@accessibility
Scenario: Evaluate the accessibility of the bulk edit activity completion page
Given I am on the "Course 1" course page logged in as "teacher1"
When I navigate to "Course completion" in current page administration
And I set the field "Course completion tertiary navigation" to "Bulk edit activity completion"
And the page should meet "wcag21aa" accessibility standards
@@ -82,3 +82,19 @@ Feature: Allow teachers to edit the default activity completion rules in a cours
And I click on "Save changes" "button"
Then I should see "Changes saved"
And I should see "Student must achieve at least one of the following statuses: Completed"
@javascript @accessibility
Scenario: Evaluate the accessibility of the default activity completion page
Given the following "courses" exist:
| fullname | shortname | category | enablecompletion |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | First | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I am on the "Course 1" course page logged in as teacher1
When I navigate to "Course completion" in current page administration
And I select "Default activity completion" from the "Course completion tertiary navigation" singleselect
And the page should meet accessibility standards
+2 -3
View File
@@ -697,8 +697,7 @@ class core_course_renderer extends plugin_renderer_base {
// Display link itself.
$instancename = html_writer::tag('span', $instancename . $altname, ['class' => 'instancename ml-1']);
$imageicon = html_writer::empty_tag('img', ['src' => $mod->get_icon_url(),
'class' => 'activityicon', 'alt' => '', 'role' => 'presentation', 'aria-hidden' => 'true']);
$imageicon = html_writer::empty_tag('img', ['src' => $mod->get_icon_url(), 'class' => 'activityicon', 'alt' => '']);
$imageicon = html_writer::tag('span', $imageicon, ['class' => 'activityiconcontainer courseicon']);
$activitylink = $imageicon . $instancename;
@@ -907,7 +906,7 @@ class core_course_renderer extends plugin_renderer_base {
$altname = get_accesshide(' ' . $cm->modfullname);
$name = html_writer::empty_tag('img', array('src' => $cm->get_icon_url(),
'class' => 'iconlarge activityicon', 'alt' => ' ', 'role' => 'presentation')) .
'class' => 'iconlarge activityicon', 'alt' => '')) .
html_writer::tag('span', ' '.$cm->get_formatted_name() . $altname, array('class' => 'instancename'));
$formattedinfo = \core_availability\info::format_info($cm->availableinfo, $cm->get_course());
return html_writer::div($name, 'activityinstance-error') .
+1 -1
View File
@@ -42,7 +42,7 @@
<input type="checkbox" id="selectactivity_{{cmid}}" class="mr-1" name="cmid[]" data-section="{{sectionnumber}}" value="{{cmid}}" aria-label="{{#str}}checkactivity, completion, {{{modname}}}{{/str}}">
{{/canmanage}}
<a href="{{url}}">
<img src="{{icon}}" class="iconlarge activityicon" alt=" " role="presentation" />
<img src="{{icon}}" class="iconlarge activityicon" alt="">
<span class="instancename">{{{modname}}}</span>
</a>
</div>
@@ -47,8 +47,10 @@
</div>
<div class="row mb-1">
<div class="col-6">
<input type="checkbox" class="mastercheck mr-1" aria-label="{{#str}}checkall, completion{{/str}}">
<label class="font-weight-bold">{{#str}}activitieslabel, core_completion{{/str}}</label>
<label class="font-weight-bold">
<input type="checkbox" class="mastercheck mr-1" aria-label="{{#str}}checkall, completion{{/str}}">
{{#str}}activitieslabel, core_completion{{/str}}
</label>
</div>
<div class="col-6">
<label class="font-weight-bold">{{#str}}completion, core_completion{{/str}}</label>
@@ -62,10 +64,11 @@
<div class="mb-1">
<div class="row mb-1">
<div class="col-6">
<label class="accesshide" for="modtype_{{id}}">{{#str}}select, core_completion{{/str}} {{formattedname}}</label>
<input id="modtype_{{id}}" type="checkbox" class="mr-1" name="modids[]" value="{{id}}" aria-label="{{#str}}checkactivity, completion, {{{formattedname}}}{{/str}}">
<img class="iconlarge activityicon" src="{{icon}}" alt=" " role="presentation" />
<span>{{{formattedname}}}</span>
<label for="modtype_{{id}}">
<input id="modtype_{{id}}" type="checkbox" class="mr-1" name="modids[]" value="{{id}}" aria-label="{{#str}}checkactivity, completion, {{{formattedname}}}{{/str}}">
<img class="iconlarge activityicon" src="{{icon}}" alt="" />
<span>{{{formattedname}}}</span>
</label>
</div>
<div class="activity-completionstatus col-6">
<div class="col-sm-1 pl-0">
@@ -38,7 +38,7 @@
<div class="row mb-1">
{{#modules}}
<div class="col-sm-2">
<img src="{{icon}}" class="mr-1 mb-1" alt=" " role="presentation" />
<img src="{{icon}}" class="mr-1 mb-1" alt="">
<span>{{{formattedname}}}</span>
</div>
{{/modules}}
+2 -3
View File
@@ -28,10 +28,9 @@
<div class="text-xs-center text-center mt-3" data-region="empty-message">
<img class="empty-placeholder-image-lg mt-1"
src="{{nocoursesimg}}"
alt="{{$nocoursestring}}{{#str}} nocourses, core {{/str}}{{/nocoursestring}}"
role="presentation">
alt="">
<p class="text-muted mt-3">{{$nocoursestring}}{{#str}} nocourses, core {{/str}}{{/nocoursestring}}</p>
{{#newcourseurl}}
<a href="{{{newcourseurl}}}" class="nocourseslink">{{#str}} createnewcourse, core {{/str}}</a>
{{/newcourseurl}}
</div>
</div>
@@ -49,7 +49,7 @@
}
}}
<span>
<img height="12" src="{{profileimageurlsmall}}" alt="" role="presentation">
<img height="12" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
{{#hasidentity}}
<span><small>{{identity}}</small></span>
+1 -1
View File
@@ -10915,7 +10915,7 @@ class admin_setting_php_extension_enabled extends admin_setting {
$o = '';
if (!extension_loaded($this->extension)) {
$warning = $OUTPUT->pix_icon('i/warning', '', '', array('role' => 'presentation')) . ' ' . $this->description;
$warning = $OUTPUT->pix_icon('i/warning', '') . ' ' . $this->description;
$o .= format_admin_setting($this, $this->visiblename, $warning);
}
+9 -1
View File
@@ -1830,7 +1830,15 @@ class html_writer {
public static function img($src, $alt, array $attributes = null) {
$attributes = (array)$attributes;
$attributes['src'] = $src;
$attributes['alt'] = $alt;
// In case a null alt text is provided, set it to an empty string.
$attributes['alt'] = $alt ?? '';
if (array_key_exists('role', $attributes) && core_text::strtolower($attributes['role']) === 'presentation') {
// A presentation role is not necessary for the img tag.
// If a non-empty alt text is provided, the presentation role will conflict with the alt text.
// An empty alt text denotes a decorative image. The presence of a presentation role is redundant.
unset($attributes['role']);
debugging('The presentation role is not necessary for an img tag.', DEBUG_DEVELOPER);
}
return self::empty_tag('img', $attributes);
}
+10 -6
View File
@@ -2049,14 +2049,19 @@ class core_renderer extends renderer_base {
$attributes['class'] = 'action-icon';
}
$icon = $this->render($pixicon);
if ($linktext) {
$text = $pixicon->attributes['alt'];
// Set the icon as a decorative image if we're displaying the action text.
// Otherwise, the action name will be read twice by assistive technologies.
$pixicon->attributes['alt'] = '';
$pixicon->attributes['title'] = '';
$pixicon->attributes['aria-hidden'] = 'true';
} else {
$text = '';
}
$icon = $this->render($pixicon);
return $this->action_link($url, $text.$icon, $action, $attributes);
}
@@ -2294,7 +2299,7 @@ class core_renderer extends renderer_base {
public function doc_link($path, $text = '', $forcepopup = false, array $attributes = []) {
global $CFG;
$icon = $this->pix_icon('book', '', 'moodle', array('class' => 'iconhelp icon-pre', 'role' => 'presentation'));
$icon = $this->pix_icon('book', '', 'moodle', array('class' => 'iconhelp icon-pre'));
$attributes['href'] = new moodle_url(get_docs_url($path));
$newwindowicon = '';
@@ -4528,15 +4533,14 @@ EOD;
if ($button['buttontype'] === 'message') {
\core_message\helper::messageuser_requirejs();
}
$image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
$image = $this->pix_icon($button['formattedimage'], '', 'moodle', array(
'class' => 'iconsmall',
'role' => 'presentation'
));
$image .= html_writer::span($button['title'], 'header-button-title');
} else {
$image = html_writer::empty_tag('img', array(
'src' => $button['formattedimage'],
'role' => 'presentation'
'alt' => $button['title'],
));
}
$html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
+2 -2
View File
@@ -1186,9 +1186,9 @@ EXPECTED;
$url1 = "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999999/test1.jpg";
$url2 = "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999998/test2.jpg";
$html = "<p>This is a test.</p><p><img src=\"{$url1}\" alt=\"\" role=\"presentation\"></p>
$html = "<p>This is a test.</p><p><img src=\"{$url1}\" alt=\"\"></p>
<br>Test content.<p></p><p><img src=\"{$url2}\" alt=\"\" width=\"2048\" height=\"1536\"
role=\"presentation\" class=\"img-fluid atto_image_button_text-bottom\"><br></p>";
class=\"img-fluid atto_image_button_text-bottom\"><br></p>";
$draftareas = array(
array(
'urlbase' => 'draftfile.php',
@@ -28,7 +28,12 @@
}
}}
<span>
{{#pix}} t/addcontact, core, {{#str}} addtoyourcontacts, message {{/str}} {{/pix}}
{{#displaytextlabel}}<span class="header-button-title">{{#str}} addtoyourcontacts, message {{/str}}</span>{{/displaytextlabel}}
{{^displaytextlabel}}
{{#pix}} t/addcontact, core, {{#str}} addtoyourcontacts, message {{/str}} {{/pix}}
{{/displaytextlabel}}
{{#displaytextlabel}}
{{#pix}} t/addcontact, core {{/pix}}
<span class="header-button-title">{{#str}} addtoyourcontacts, message {{/str}}</span>
{{/displaytextlabel}}
</span>
{{> core/loading }}
@@ -28,7 +28,12 @@
}
}}
<span>
{{#pix}} t/removecontact, core, {{#str}} removefromyourcontacts, message {{/str}} {{/pix}}
{{#displaytextlabel}}<span class="header-button-title">{{#str}} removefromyourcontacts, message {{/str}}</span>{{/displaytextlabel}}
{{^displaytextlabel}}
{{#pix}} t/removecontact, core, {{#str}} removefromyourcontacts, message {{/str}} {{/pix}}
{{/displaytextlabel}}
{{#displaytextlabel}}
{{#pix}} t/removecontact, core {{/pix}}
<span class="header-button-title">{{#str}} removefromyourcontacts, message {{/str}}</span>
{{/displaytextlabel}}
</span>
{{> core/loading }}
@@ -61,7 +61,7 @@ Feature: Self conversation
Given I log in as "student1"
When I follow "Profile" in the user menu
Then I should see "Message"
And I click on "Message" "icon"
And I press "Message"
And I send "Hi!" message in the message area
And I should see "Hi!" in the "Student 1" "core_message > Message conversation"
And I should see "##today##%d %B##" in the "Student 1" "core_message > Message conversation"
+1 -7
View File
@@ -55,14 +55,8 @@
}
}}
<div class="text-xs-center text-center mt-4" data-region="empty-message">
<img
src="{{noitemsimgurl}}"
alt="{{#str}} norecords, mod_data {{/str}}"
role="presentation"
style="height: 70px; width: 70px;"
>
<img src="{{noitemsimgurl}}" alt="" style="height: 70px; width: 70px;">
<h5 class="h5 mt-3 mb-0">{{#str}} norecords, mod_data {{/str}}</h5>
<div class="mt-5 mb-0" id="action_bar">
{{#importentriesbutton}}
{{> core/single_button }}
+1 -6
View File
@@ -71,12 +71,7 @@
}
}}
<div class="text-xs-center text-center mt-4" data-region="empty-message">
<img
src="{{noitemsimgurl}}"
alt="{{{ title }}}"
role="presentation"
style="height: 70px; width: 70px;"
>
<img src="{{noitemsimgurl}}" alt="" style="height: 70px; width: 70px;">
<h5 class="h5 mt-3 mb-0">{{{ title }}}</h5>
{{#intro}}
<p class="mt-3 mb-0">{{{ intro }}}</p>
+15
View File
@@ -191,3 +191,18 @@ Feature: Users can view and search database entries
| param1 | param3 | autolink |
| 0 | 0 | should not |
| 1 | 1 | should |
@javascript @accessibility
Scenario: Check the accessibility of the database entries page (zero state)
When I am on the "Test database name" "data activity" page logged in as "teacher1"
Then I should see "No entries yet"
And the page should meet accessibility standards
@javascript @accessibility
Scenario: Check the accessibility of the database entries page
Given the following "mod_data > entries" exist:
| database | user | Test field name | Test field 2 name | Test field 3 name |
| data1 | student1 | Student entry 1 | Some student content 1 | http://moodle.com |
| data1 | teacher1 | Teacher entry 2 | Some teacher content 2 | http://moodle.com |
When I am on the "Test database name" "data activity" page logged in as teacher1
Then the page should meet accessibility standards
+6
View File
@@ -65,3 +65,9 @@ Feature: Zero state page (no fields created)
Then I click on "Use this preset" "button"
And I should not see "Field mappings"
And I should see "Image" in the "image" "table_row"
@javascript @accessibility
Scenario: Check the accessibility of the database activity zero state
When I am on the "Test database name" "data activity" page logged in as "teacher1"
Then I should see "Start building your activity"
And the page should meet accessibility standards
+2 -3
View File
@@ -1035,7 +1035,7 @@ class edit_renderer extends \plugin_renderer_base {
$namestr = $qtype->local_name();
$icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), ['title' => $namestr,
'class' => 'activityicon', 'alt' => ' ', 'role' => 'presentation']);
'class' => 'activityicon', 'alt' => $namestr]);
$editicon = $this->pix_icon('t/edit', '', 'moodle', ['title' => '']);
@@ -1073,8 +1073,7 @@ class edit_renderer extends \plugin_renderer_base {
$configuretitle = get_string('configurerandomquestion', 'quiz');
$qtype = \question_bank::get_qtype($question->qtype, false);
$namestr = $qtype->local_name();
$icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), ['title' => $namestr,
'class' => 'icon activityicon', 'alt' => ' ', 'role' => 'presentation']);
$icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), ['class' => 'icon activityicon']);
$editicon = $this->pix_icon('t/edit', $configuretitle, 'moodle', ['title' => '']);
$qbankurlparams = [
+16
View File
@@ -242,3 +242,19 @@ Feature: Edit quiz page - adding things
And I should see "Essay 02" on quiz page "3"
And I should see "Random" on quiz page "4"
And I should see "Essay for page 4" on quiz page "4"
@accessibility @javascript
Scenario: Check the accessibility of the quiz questions page
Given the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question |
| Test questions | truefalse | Other question | Answer the first question |
And quiz "Quiz 1" contains the following questions:
| question | page |
| First question | 1 |
When I reload the page
Then I should see "First question"
And the page should meet accessibility standards
+1 -1
View File
@@ -308,7 +308,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
if ($phase->active) {
// Mark the section as the current one.
$icon = $this->output->pix_icon('i/marked', '', 'moodle', ['role' => 'presentation']);
$icon = $this->output->pix_icon('i/marked', '');
$actions .= get_string('userplancurrentphase', 'workshop').' '.$icon;
} else {
@@ -65,3 +65,10 @@ Feature: See the competencies for an activity
And I click on "PageName1" "autocomplete_selection"
And I should see "Test-Comp1"
And I should see "Test-Comp2"
@accessibility
Scenario: Evaluate the accessibility of the user competency summary dialogue
Given I navigate to "Reports" in current page administration
When I click on "Competency breakdown" "link"
And I click on "Not rated" "link"
And the page should meet accessibility standards
@@ -36,6 +36,6 @@
}
}}
<span>
<img height="12" src="{{profileimageurlsmall}}" alt="" role="presentation">
<img height="12" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
</span>
+2 -3
View File
@@ -224,15 +224,14 @@ class core_renderer extends \core_renderer {
if ($button['buttontype'] === 'message') {
\core_message\helper::messageuser_requirejs();
}
$image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
$image = $this->pix_icon($button['formattedimage'], '', 'moodle', array(
'class' => 'iconsmall',
'role' => 'presentation'
));
$image .= html_writer::span($button['title'], 'header-button-title');
} else {
$image = html_writer::empty_tag('img', array(
'src' => $button['formattedimage'],
'role' => 'presentation'
'alt' => $button['title'],
));
}
$html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);