From 257903fe15e0746a7671f43b68b2018d132a7b35 Mon Sep 17 00:00:00 2001 From: Chris Rodriguez Date: Thu, 12 May 2016 13:17:37 -0400 Subject: [PATCH] AC-414 adding headings as first child to sections --- .../pages/lms/instructor_dashboard.py | 26 ++--- .../tests/discussion/test_discussion.py | 16 +-- .../tests/lms/test_account_settings.py | 2 +- .../tests/lms/test_learner_profile.py | 6 +- common/test/acceptance/tests/lms/test_lms.py | 2 +- .../tests/lms/test_lms_courseware.py | 2 +- .../tests/lms/test_lms_dashboard.py | 2 +- .../lms/test_lms_instructor_dashboard.py | 99 +++++++++++++++++++ .../tests/lms/test_problem_types.py | 40 ++++---- .../acceptance/tests/lms/test_programs.py | 6 +- .../tests/studio/test_studio_library.py | 2 +- .../tests/studio/test_studio_settings.py | 4 +- .../tests/video/test_studio_video_module.py | 2 +- .../tests/video/test_video_module.py | 2 +- .../tests/views/test_instructor_dashboard.py | 4 +- .../instructor/views/instructor_dashboard.py | 4 +- .../js/instructor_dashboard/proctoring.js | 4 +- lms/static/sass/_build-course.scss | 4 +- .../sass/{xmodule => base}/_headings.scss | 52 +++++----- .../sass/course/instructor/_instructor_2.scss | 5 - lms/templates/ccx/coach_dashboard.html | 16 +-- lms/templates/ccx/enrollment.html | 2 +- lms/templates/ccx/grading_policy.html | 4 +- lms/templates/ccx/schedule.html | 11 ++- lms/templates/ccx/student_admin.html | 13 +-- lms/templates/file-upload.underscore | 4 +- .../add_coupon_modal.html | 5 +- .../certificate-bulk-white-list.underscore | 2 +- .../certificate-white-list-editor.underscore | 2 +- .../certificate-white-list.underscore | 2 +- .../instructor_dashboard_2/certificates.html | 23 +++-- .../cohort-discussions-course-wide.underscore | 4 +- .../cohort-discussions-inline.underscore | 2 +- .../cohort-editor.underscore | 2 +- .../cohort-form.underscore | 2 +- .../cohort-group-header.underscore | 2 +- .../instructor_dashboard_2/course_info.html | 30 +++--- .../instructor_dashboard_2/data_download.html | 22 +++-- .../instructor_dashboard_2/e-commerce.html | 36 ++++--- .../edit_coupon_modal.html | 7 +- .../instructor_dashboard_2/extensions.html | 13 +-- .../generate_registarion_codes_modal.html | 5 +- .../instructor_dashboard_2.html | 13 +-- .../invalidate_registration_code_modal.html | 5 +- .../instructor_dashboard_2/membership.html | 22 ++--- .../instructor_dashboard_2/metrics.html | 4 +- .../notification.underscore | 4 +- .../instructor_dashboard_2/send_email.html | 5 +- .../set_course_mode_price_modal.html | 5 +- .../instructor_dashboard_2/special_exams.html | 6 +- .../instructor_dashboard_2/student_admin.html | 13 ++- lms/templates/widgets/html-edit.html | 6 +- 52 files changed, 343 insertions(+), 233 deletions(-) rename lms/static/sass/{xmodule => base}/_headings.scss (79%) diff --git a/common/test/acceptance/pages/lms/instructor_dashboard.py b/common/test/acceptance/pages/lms/instructor_dashboard.py index e73941691c..d056e82262 100644 --- a/common/test/acceptance/pages/lms/instructor_dashboard.py +++ b/common/test/acceptance/pages/lms/instructor_dashboard.py @@ -23,7 +23,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the membership tab and returns the MembershipSection """ - self.q(css='a[data-section=membership]').first.click() + self.q(css='[data-section=membership]').first.click() membership_section = MembershipPage(self.browser) membership_section.wait_for_page() return membership_section @@ -32,7 +32,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the cohort management tab and returns the CohortManagementSection """ - self.q(css='a[data-section=cohort_management]').first.click() + self.q(css='[data-section=cohort_management]').first.click() cohort_management_section = CohortManagementSection(self.browser) # The first time cohort management is selected, an ajax call is made. cohort_management_section.wait_for_ajax() @@ -43,7 +43,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the data download tab and returns a DataDownloadPage. """ - self.q(css='a[data-section=data_download]').first.click() + self.q(css='[data-section=data_download]').first.click() data_download_section = DataDownloadPage(self.browser) data_download_section.wait_for_page() return data_download_section @@ -52,7 +52,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the student admin tab and returns the MembershipSection """ - self.q(css='a[data-section=student_admin]').first.click() + self.q(css='[data-section=student_admin]').first.click() student_admin_section = StudentAdminPage(self.browser) student_admin_section.wait_for_page() return student_admin_section @@ -61,7 +61,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the certificates tab and returns the CertificatesSection """ - self.q(css='a[data-section=certificates]').first.click() + self.q(css='[data-section=certificates]').first.click() certificates_section = CertificatesPage(self.browser) certificates_section.wait_for_page() return certificates_section @@ -70,7 +70,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the timed exam tab and returns the Special Exams Section """ - self.q(css='a[data-section=special_exams]').first.click() + self.q(css='[data-section=special_exams]').first.click() timed_exam_section = SpecialExamsPage(self.browser) timed_exam_section.wait_for_page() return timed_exam_section @@ -79,7 +79,7 @@ class InstructorDashboardPage(CoursePage): """ Selects the email tab and returns the bulk email section """ - self.q(css='a[data-section=send_email]').first.click() + self.q(css='[data-section=send_email]').first.click() email_section = BulkEmailPage(self.browser) email_section.wait_for_page() return email_section @@ -115,7 +115,7 @@ class BulkEmailPage(PageObject): url = None def is_browser_on_page(self): - return self.q(css='a[data-section=send_email].active-section').present + return self.q(css='[data-section=send_email].active-section').present def _bounded_selector(self, selector): """ @@ -169,7 +169,7 @@ class MembershipPage(PageObject): url = None def is_browser_on_page(self): - return self.q(css='a[data-section=membership].active-section').present + return self.q(css='[data-section=membership].active-section').present def select_auto_enroll_section(self): """ @@ -185,7 +185,7 @@ class SpecialExamsPage(PageObject): url = None def is_browser_on_page(self): - return self.q(css='a[data-section=special_exams].active-section').present + return self.q(css='[data-section=special_exams].active-section').present def select_allowance_section(self): """ @@ -954,7 +954,7 @@ class DataDownloadPage(PageObject): url = None def is_browser_on_page(self): - return self.q(css='a[data-section=data_download].active-section').present + return self.q(css='[data-section=data_download].active-section').present @property def generate_student_report_button(self): @@ -1017,7 +1017,7 @@ class StudentAdminPage(PageObject): """ Confirms student admin section is present """ - return self.q(css='a[data-section=student_admin].active-section').present + return self.q(css='[data-section=student_admin].active-section').present @property def student_email_input(self): @@ -1177,7 +1177,7 @@ class CertificatesPage(PageObject): self.wait_for_page() def is_browser_on_page(self): - return self.q(css='a[data-section=certificates].active-section').present + return self.q(css='[data-section=certificates].active-section').present def get_selector(self, css_selector): """ diff --git a/common/test/acceptance/tests/discussion/test_discussion.py b/common/test/acceptance/tests/discussion/test_discussion.py index 02e4081ac6..dfe30c79a1 100644 --- a/common/test/acceptance/tests/discussion/test_discussion.py +++ b/common/test/acceptance/tests/discussion/test_discussion.py @@ -208,7 +208,7 @@ class DiscussionHomePageTest(UniqueCourseTest): def test_page_accessibility(self): self.page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'color-contrast', # TNL-4635 'link-href', # TNL-4636 'icon-aria-hidden', # TNL-4637 @@ -348,7 +348,7 @@ class DiscussionTabMultipleThreadTest(BaseDiscussionTestCase): def test_page_accessibility(self): self.thread_page_1.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4638 'color-contrast', # TNL-4639 'link-href', # TNL-4640 @@ -360,7 +360,7 @@ class DiscussionTabMultipleThreadTest(BaseDiscussionTestCase): self.thread_page_2.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4638 'color-contrast', # TNL-4639 'link-href', # TNL-4640 @@ -424,7 +424,7 @@ class DiscussionOpenClosedThreadTest(BaseDiscussionTestCase): page = self.setup_openclosed_thread_page() page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4643 'color-contrast', # TNL-4644 'link-href', # TNL-4640 @@ -436,7 +436,7 @@ class DiscussionOpenClosedThreadTest(BaseDiscussionTestCase): page = self.setup_openclosed_thread_page(True) page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4643 'color-contrast', # TNL-4644 'link-href', # TNL-4640 @@ -725,7 +725,7 @@ class DiscussionResponseEditTest(BaseDiscussionTestCase): page = self.create_single_thread_page("response_edit_test_thread") page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4638 'color-contrast', # TNL-4644 'link-href', # TNL-4640 @@ -827,7 +827,7 @@ class DiscussionCommentEditTest(BaseDiscussionTestCase): page.visit() page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr-value', # TNL-4643 'color-contrast', # TNL-4644 'link-href', # TNL-4640 @@ -1202,7 +1202,7 @@ class DiscussionSearchAlertTest(UniqueCourseTest): def test_page_accessibility(self): self.page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'color-contrast', # TNL-4639 'link-href', # TNL-4640 'icon-aria-hidden', # TNL-4641 diff --git a/common/test/acceptance/tests/lms/test_account_settings.py b/common/test/acceptance/tests/lms/test_account_settings.py index 02b8c84889..7579a84e68 100644 --- a/common/test/acceptance/tests/lms/test_account_settings.py +++ b/common/test/acceptance/tests/lms/test_account_settings.py @@ -481,7 +481,7 @@ class AccountSettingsA11yTest(AccountSettingsTestMixin, WebAppTest): self.visit_account_settings_page() self.account_settings_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'link-href', # TODO: AC-233 ], }) diff --git a/common/test/acceptance/tests/lms/test_learner_profile.py b/common/test/acceptance/tests/lms/test_learner_profile.py index 72f1f402b3..13ab9b7e95 100644 --- a/common/test/acceptance/tests/lms/test_learner_profile.py +++ b/common/test/acceptance/tests/lms/test_learner_profile.py @@ -779,7 +779,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest): profile_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'link-href', # TODO: AC-231 ], }) @@ -807,7 +807,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest): profile_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'link-href', # TODO: AC-231 ], }) @@ -824,7 +824,7 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest): profile_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'link-href', # TODO: AC-231 ], }) diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index 2f95b9d712..7ac29a342d 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -1349,7 +1349,7 @@ class CourseInfoA11yTest(UniqueCourseTest): self.course_info_page.visit() self.course_info_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.course_info_page.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/lms/test_lms_courseware.py b/common/test/acceptance/tests/lms/test_lms_courseware.py index 4c1ae24642..f5775f0d07 100644 --- a/common/test/acceptance/tests/lms/test_lms_courseware.py +++ b/common/test/acceptance/tests/lms/test_lms_courseware.py @@ -621,7 +621,7 @@ class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin): include=['div.sequence-nav']) self.courseware_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ], }) self.courseware_page.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/lms/test_lms_dashboard.py b/common/test/acceptance/tests/lms/test_lms_dashboard.py index 4521f28582..b2a647b5e2 100644 --- a/common/test/acceptance/tests/lms/test_lms_dashboard.py +++ b/common/test/acceptance/tests/lms/test_lms_dashboard.py @@ -234,7 +234,7 @@ class LmsDashboardA11yTest(BaseLmsDashboardTest): self.assertEqual(len(course_listings), 1) self.dashboard_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.dashboard_page.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/lms/test_lms_instructor_dashboard.py b/common/test/acceptance/tests/lms/test_lms_instructor_dashboard.py index a83d43963b..5390a23d97 100644 --- a/common/test/acceptance/tests/lms/test_lms_instructor_dashboard.py +++ b/common/test/acceptance/tests/lms/test_lms_instructor_dashboard.py @@ -46,6 +46,27 @@ class BaseInstructorDashboardTest(EventsTestMixin, UniqueCourseTest): return instructor_dashboard_page +@attr('a11y') +class LMSInstructorDashboardA11yTest(BaseInstructorDashboardTest): + """ + Instructor dashboard base accessibility test. + """ + def setUp(self): + super(LMSInstructorDashboardA11yTest, self).setUp() + self.course_fixture = CourseFixture(**self.course_info).install() + self.log_in_as_instructor() + self.instructor_dashboard_page = self.visit_instructor_dashboard() + + def test_instructor_dashboard_a11y(self): + self.instructor_dashboard_page.a11y_audit.config.set_rules({ + "ignore": [ + 'link-href', # TODO: AC-491 + 'data-table', # TODO: AC-491 + ] + }) + self.instructor_dashboard_page.a11y_audit.check_for_accessibility_errors() + + @ddt.ddt class BulkEmailTest(BaseInstructorDashboardTest): """ @@ -64,6 +85,23 @@ class BulkEmailTest(BaseInstructorDashboardTest): self.send_email_page.send_message(recipient) self.send_email_page.verify_message_queued_successfully() + @attr('a11y') + def test_bulk_email_a11y(self): + """ + Bulk email accessibility tests + """ + self.send_email_page.a11y_audit.config.set_scope([ + '#section-send-email' + ]) + self.send_email_page.a11y_audit.config.set_rules({ + "ignore": [ + 'button-name', # TODO: AC-491 + 'list', # TODO: AC-491, + 'color-contrast', # TODO: AC-491 + ] + }) + self.send_email_page.a11y_audit.check_for_accessibility_errors() + @attr('shard_7') class AutoEnrollmentWithCSVTest(BaseInstructorDashboardTest): @@ -172,6 +210,16 @@ class AutoEnrollmentWithCSVTest(BaseInstructorDashboardTest): self.assertTrue(self.auto_enroll_section.is_notification_displayed(section_type=self.auto_enroll_section.NOTIFICATION_ERROR)) self.assertEqual(self.auto_enroll_section.first_notification_message(section_type=self.auto_enroll_section.NOTIFICATION_ERROR), "Make sure that the file you upload is in CSV format with no extraneous characters or rows.") + @attr('a11y') + def test_auto_enroll_csv_a11y(self): + """ + Auto-enrollment with CSV accessibility tests + """ + self.auto_enroll_section.a11y_audit.config.set_scope([ + '#member-list-widget-template' + ]) + self.auto_enroll_section.a11y_audit.check_for_accessibility_errors() + @attr('shard_7') class ProctoredExamsTest(BaseInstructorDashboardTest): @@ -668,6 +716,16 @@ class DataDownloadsTest(BaseInstructorDashboardTest): self.data_download_section.wait_for_available_report() self.verify_report_download(report_name) + @attr('a11y') + def test_data_download_a11y(self): + """ + Data download page accessibility tests + """ + self.data_download_section.a11y_audit.config.set_scope([ + '.data-download-container' + ]) + self.data_download_section.a11y_audit.check_for_accessibility_errors() + @attr('shard_7') @ddt.ddt @@ -956,6 +1014,26 @@ class CertificatesTest(BaseInstructorDashboardTest): self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text) self.assertIn(expected_notes, self.certificates_section.last_certificate_exception.text) + @attr('a11y') + def test_certificates_a11y(self): + """ + Certificates page accessibility tests + """ + self.certificates_section.a11y_audit.config.set_scope([ + '.certificates-wrapper' + ]) + self.certificates_section.a11y_audit.config.set_rules({ + "ignore": [ + 'aria-valid-attr-value', # TODO: AC-491 + 'checkboxgroup', # TODO: AC-491 + 'color-contrast', # TODO: AC-491 + 'duplicate-id', # TODO: AC-491 + 'label', # TODO: AC-491 + 'radiogroup', # TODO: AC-491 + ] + }) + self.certificates_section.a11y_audit.check_for_accessibility_errors() + @attr('shard_7') class CertificateInvalidationTest(BaseInstructorDashboardTest): @@ -1154,3 +1232,24 @@ class CertificateInvalidationTest(BaseInstructorDashboardTest): u"{user} is not enrolled in this course. Please check your spelling and retry.".format(user=new_user), self.certificates_section.certificate_invalidation_message.text ) + + @attr('a11y') + def test_invalidate_certificates_a11y(self): + """ + Certificate invalidation accessibility tests + """ + self.certificates_section.a11y_audit.config.set_scope([ + '.certificates-wrapper' + ]) + self.certificates_section.a11y_audit.config.set_rules({ + "ignore": [ + 'data-table', # TODO: AC-491 + 'aria-valid-attr-value', # TODO: AC-491 + 'checkboxgroup', # TODO: AC-491 + 'color-contrast', # TODO: AC-491 + 'duplicate-id', # TODO: AC-491 + 'label', # TODO: AC-491 + 'radiogroup', # TODO: AC-491 + ] + }) + self.certificates_section.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/lms/test_problem_types.py b/common/test/acceptance/tests/lms/test_problem_types.py index 09a0facf88..44cc05c6ff 100644 --- a/common/test/acceptance/tests/lms/test_problem_types.py +++ b/common/test/acceptance/tests/lms/test_problem_types.py @@ -247,14 +247,14 @@ class ProblemTypeTestMixin(object): self.problem_page.a11y_audit.config.set_rules({ "ignore": [ - 'aria-allowed-attr', # TODO: wcag2aa - 'aria-valid-attr', # TODO: wcag2aa - 'aria-roles', # TODO: wcag2aa - 'checkboxgroup', # TODO: wcag2aa - 'radiogroup', # TODO: wcag2aa - 'color-contrast', # TODO: wcag2aa - 'section', # TODO: wcag2aa - 'label', # TODO: wcag2aa + 'aria-allowed-attr', # TODO: AC-491 + 'aria-valid-attr', # TODO: AC-491 + 'aria-roles', # TODO: AC-491 + 'checkboxgroup', # TODO: AC-491 + 'radiogroup', # TODO: AC-491 + 'color-contrast', # TODO: AC-491 + 'section', # TODO: AC-491 + 'label', # TODO: AC-491 ] }) @@ -335,7 +335,7 @@ class CheckboxProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(CheckboxProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-allowed-attr', # TODO: AC-251 'aria-valid-attr', # TODO: AC-251 'aria-roles', # TODO: AC-251 @@ -381,7 +381,7 @@ class MultipleChoiceProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(MultipleChoiceProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr', # TODO: AC-251 'radiogroup', # TODO: AC-251 ] @@ -425,7 +425,7 @@ class RadioProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(RadioProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'aria-valid-attr', # TODO: AC-292 'radiogroup', # TODO: AC-292 ] @@ -463,7 +463,7 @@ class DropDownProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(DropDownProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-291 ] }) @@ -506,7 +506,7 @@ class StringProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(StringProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-290 ] }) @@ -548,7 +548,7 @@ class NumericalProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(NumericalProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-289 ] }) @@ -592,7 +592,7 @@ class FormulaProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(FormulaProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-288 ] }) @@ -643,7 +643,7 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(ScriptProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-287 ] }) @@ -693,7 +693,7 @@ class CodeProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(CodeProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'color-contrast', # TODO: AC-286 'label', # TODO: AC-286 ] @@ -802,7 +802,7 @@ class RadioTextProblemTypeTest(ChoiceTextProbelmTypeTestBase, ProblemTypeTestMix super(RadioTextProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-285 'radiogroup', # TODO: AC-285 ] @@ -835,7 +835,7 @@ class CheckboxTextProblemTypeTest(ChoiceTextProbelmTypeTestBase, ProblemTypeTest super(CheckboxTextProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-284 'checkboxgroup', # TODO: AC-284 ] @@ -899,7 +899,7 @@ class SymbolicProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): super(SymbolicProblemTypeTest, self).setUp(*args, **kwargs) self.problem_page.a11y_audit.config.set_rules({ 'ignore': [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'label', # TODO: AC-294 ] }) diff --git a/common/test/acceptance/tests/lms/test_programs.py b/common/test/acceptance/tests/lms/test_programs.py index b57b1ddbc1..e44a069885 100644 --- a/common/test/acceptance/tests/lms/test_programs.py +++ b/common/test/acceptance/tests/lms/test_programs.py @@ -125,7 +125,7 @@ class ProgramListingPageA11yTest(ProgramPageBase): self.listing_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.listing_page.a11y_audit.check_for_accessibility_errors() @@ -140,7 +140,7 @@ class ProgramListingPageA11yTest(ProgramPageBase): self.listing_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.listing_page.a11y_audit.check_for_accessibility_errors() @@ -164,7 +164,7 @@ class ProgramDetailsPageA11yTest(ProgramPageBase): self.details_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.details_page.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/studio/test_studio_library.py b/common/test/acceptance/tests/studio/test_studio_library.py index f4ea81738d..545ca0754c 100644 --- a/common/test/acceptance/tests/studio/test_studio_library.py +++ b/common/test/acceptance/tests/studio/test_studio_library.py @@ -656,7 +656,7 @@ class StudioLibraryA11yTest(StudioLibraryTest): # we will ignore this error in the test until we fix them. lib_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'color-contrast', # TODO: AC-225 'link-href', # TODO: AC-226 'nav-aria-label', # TODO: AC-227 diff --git a/common/test/acceptance/tests/studio/test_studio_settings.py b/common/test/acceptance/tests/studio/test_studio_settings.py index 2e15599446..ad5266123d 100644 --- a/common/test/acceptance/tests/studio/test_studio_settings.py +++ b/common/test/acceptance/tests/studio/test_studio_settings.py @@ -503,7 +503,7 @@ class StudioSettingsA11yTest(StudioCourseTest): # we will ignore this error in the test until we fix them. self.settings_page.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 'color-contrast', # TODO: AC-225 'link-href', # TODO: AC-226 'nav-aria-label', # TODO: AC-227 @@ -582,7 +582,7 @@ class StudioSubsectionSettingsA11yTest(StudioCourseTest): ) self.course_outline.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.course_outline.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/video/test_studio_video_module.py b/common/test/acceptance/tests/video/test_studio_video_module.py index 8bdecddc04..547b74951a 100644 --- a/common/test/acceptance/tests/video/test_studio_video_module.py +++ b/common/test/acceptance/tests/video/test_studio_video_module.py @@ -360,7 +360,7 @@ class CMSVideoA11yTest(CMSVideoBaseTest): ) self.outline.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.outline.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/video/test_video_module.py b/common/test/acceptance/tests/video/test_video_module.py index 48fe1a3c2c..a7bcc21730 100644 --- a/common/test/acceptance/tests/video/test_video_module.py +++ b/common/test/acceptance/tests/video/test_video_module.py @@ -1274,7 +1274,7 @@ class LMSVideoModuleA11yTest(VideoBaseTest): ) self.video.a11y_audit.config.set_rules({ "ignore": [ - 'section', # TODO: wcag2aa + 'section', # TODO: AC-491 ] }) self.video.a11y_audit.check_for_accessibility_errors() diff --git a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py index e23b655378..bee4d6a9bf 100644 --- a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py +++ b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py @@ -137,7 +137,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT """ response = self.client.get(self.url) # no enrollment information should be visible - self.assertFalse('

Enrollment Information

' in response.content) + self.assertNotIn('

Enrollment Information

', response.content) @patch.dict(settings.FEATURES, {'DISPLAY_ANALYTICS_ENROLLMENTS': True}) @override_settings(ANALYTICS_DASHBOARD_URL='') @@ -148,7 +148,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT response = self.client.get(self.url) # enrollment information visible - self.assertTrue('

Enrollment Information

' in response.content) + self.assertIn('

Enrollment Information

', response.content) self.assertTrue('Verified' in response.content) self.assertTrue('Audit' in response.content) self.assertTrue('Honor' in response.content) diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index c54d28da6b..514d625711 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -422,8 +422,10 @@ def _section_course_info(course, access): section_data['enrollment_count'] = CourseEnrollment.objects.enrollment_counts(course_key) if settings.ANALYTICS_DASHBOARD_URL: + # dashboard_link is already made safe in _get_dashboard_link dashboard_link = _get_dashboard_link(course_key) - message = _("Enrollment data is now available in {dashboard_link}.").format(dashboard_link=dashboard_link) + # so we can use Text() here so it's not double-escaped and rendering HTML on the front-end + message = Text(_("Enrollment data is now available in {dashboard_link}.")).format(dashboard_link=dashboard_link) section_data['enrollment_message'] = message if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'): diff --git a/lms/static/js/instructor_dashboard/proctoring.js b/lms/static/js/instructor_dashboard/proctoring.js index 01bcbeb6c6..5b0a2d49d1 100644 --- a/lms/static/js/instructor_dashboard/proctoring.js +++ b/lms/static/js/instructor_dashboard/proctoring.js @@ -13,10 +13,10 @@ $(function() { $.cookie('saved_index', active); }, animate: 400, - header: "> div.wrap >h2", + header: "> .wrap > .hd", icons: icons, active: isNaN(parseInt($.cookie('saved_index'))) ? 0 : parseInt($.cookie('saved_index')), collapsible: true } ); -}); \ No newline at end of file +}); diff --git a/lms/static/sass/_build-course.scss b/lms/static/sass/_build-course.scss index f671ab71c6..368d089952 100644 --- a/lms/static/sass/_build-course.scss +++ b/lms/static/sass/_build-course.scss @@ -4,6 +4,7 @@ // About: Sass compile for the LMS Courseware Elements that are shared between LTR and RTL UI. Configuration and vendor specific imports happen before this shared set of imports are compiled in the lms-course-*.scss files. @import 'base/base'; +@import 'base/headings'; @import 'base/extends'; @import 'base/animations'; @import 'shared/tooltips'; @@ -66,6 +67,3 @@ // responsive @import 'base/layouts'; // temporary spot for responsive course - -// xmodule -@import 'xmodule/headings'; diff --git a/lms/static/sass/xmodule/_headings.scss b/lms/static/sass/base/_headings.scss similarity index 79% rename from lms/static/sass/xmodule/_headings.scss rename to lms/static/sass/base/_headings.scss index b6db2e5f39..08d811c406 100644 --- a/lms/static/sass/xmodule/_headings.scss +++ b/lms/static/sass/base/_headings.scss @@ -3,9 +3,9 @@ * The UXPL isn't available retroactively, so this shims * the headings from the UXPL with what we're using in * the platform to better sync things up in the meantime. - * It is scoped to #seq_content, specifically for xblock. + * These are available to entire LMS. * - * Once the UXPl is fitted retroactively, this can be removed. + * Once the UXPL is fitted retroactively (if ever then), this can be removed. */ $headings-count: 8; @@ -88,30 +88,34 @@ $headings-base-color: $gray-d2; letter-spacing: 1px; } +// let's make these classnames available to the entire LMS! + +.hd-1, +.hd-2, +.hd-3, +.hd-4, +.hd-5, +.hd-6, +.hd-7, +.hd-8 { + @extend %reset-headings; +} + + +// ---------------------------- +// #CANNED +// ---------------------------- +// canned heading classes +@for $i from 1 through $headings-count { + .hd-#{$i} { + @extend %hd-#{$i}; + } +} + +// H3 was problematic in xblocks, we so we'll keep it as it was + .xblock .xblock { - .hd-1, - .hd-2, - .hd-3, - .hd-4, - .hd-5, - .hd-6, - .hd-7, - .hd-8 { - @extend %reset-headings; - } - - - // ---------------------------- - // #CANNED - // ---------------------------- - // canned heading classes - @for $i from 1 through $headings-count { - .hd-#{$i} { - @extend %hd-#{$i}; - } - } - h3 { @extend %hd-2; font-weight: $headings-font-weight-normal; diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss index 196b158bf2..5260176c79 100644 --- a/lms/static/sass/course/instructor/_instructor_2.scss +++ b/lms/static/sass/course/instructor/_instructor_2.scss @@ -406,11 +406,6 @@ // view - bulk email // -------------------- .instructor-dashboard-wrapper-2 section.idash-section#send_email { - h2 { - // override forced uppercase - text-transform: none; - } - // form fields .list-fields { list-style: none; diff --git a/lms/templates/ccx/coach_dashboard.html b/lms/templates/ccx/coach_dashboard.html index c980f154a7..fb043fbe76 100644 --- a/lms/templates/ccx/coach_dashboard.html +++ b/lms/templates/ccx/coach_dashboard.html @@ -23,8 +23,8 @@ from openedx.core.djangolib.js_utils import (
-
-

${_("CCX Coach Dashboard")}

+
+

${_("CCX Coach Dashboard")}

%if not ccx: % if messages: @@ -38,7 +38,7 @@ from openedx.core.djangolib.js_utils import ( % endfor % endif -
+

@@ -50,7 +50,7 @@ from openedx.core.djangolib.js_utils import (
-
+
%endif %if ccx: @@ -68,16 +68,16 @@ from openedx.core.djangolib.js_utils import ( ${_("Grading Policy")} -
+
<%include file="enrollment.html" args="" />
-
+
<%include file="schedule.html" args="" />
-
+
<%include file="student_admin.html" args="" />
-
+
<%include file="grading_policy.html" args="" />
%endif diff --git a/lms/templates/ccx/enrollment.html b/lms/templates/ccx/enrollment.html index d9b422f4df..33cf9d943d 100644 --- a/lms/templates/ccx/enrollment.html +++ b/lms/templates/ccx/enrollment.html @@ -4,10 +4,10 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.markup import HTML, Text %> +

${_("Batch Enrollment")}

-

${_("Batch Enrollment")}

${_("Enter email addresses and/or usernames separated by new lines or commas.")} diff --git a/lms/templates/ccx/grading_policy.html b/lms/templates/ccx/grading_policy.html index d71ea5b800..05e0e42492 100644 --- a/lms/templates/ccx/grading_policy.html +++ b/lms/templates/ccx/grading_policy.html @@ -1,6 +1,8 @@ <%page expression_filter="h"/> <%! from django.utils.translation import ugettext as _ %> +

${_("Grading Policy")}

+
@@ -14,8 +16,6 @@
-

${_("Grading Policy")}

- - + ${_("Enter the reason why the students are to be manually enrolled or unenrolled.")} + ${_("This cannot be left blank and will be recorded and presented in Enrollment Reports.")} + ${_("Therefore, please give enough detail to account for this action.")} + + %endif