diff --git a/common/test/acceptance/tests/lms/test_account_settings.py b/common/test/acceptance/tests/lms/test_account_settings.py index 4b6b3a30a0..dc00718b53 100644 --- a/common/test/acceptance/tests/lms/test_account_settings.py +++ b/common/test/acceptance/tests/lms/test_account_settings.py @@ -14,7 +14,6 @@ from ...pages.lms.dashboard import DashboardPage from ..helpers import EventsTestMixin -@attr('shard_5') class AccountSettingsTestMixin(EventsTestMixin, WebAppTest): """ Mixin with helper methods to test the account settings page. @@ -460,4 +459,10 @@ class AccountSettingsA11yTest(AccountSettingsTestMixin, WebAppTest): """ self.log_in_as_unique_user() self.visit_account_settings_page() + self.account_settings_page.a11y_audit.config.set_rules({ + 'ignore': [ + 'link-href', # TODO: AC-233, AC-230 + 'skip-link', # TODO: AC-179 + ], + }) self.account_settings_page.a11y_audit.check_for_accessibility_errors() diff --git a/common/test/acceptance/tests/lms/test_learner_profile.py b/common/test/acceptance/tests/lms/test_learner_profile.py index 207a7e7bef..d32a489451 100644 --- a/common/test/acceptance/tests/lms/test_learner_profile.py +++ b/common/test/acceptance/tests/lms/test_learner_profile.py @@ -765,10 +765,12 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest): username, _ = self.log_in_as_unique_user() profile_page = self.visit_profile_page(username) - # TODO: There are several existing color contrast errors on this page, - # we will ignore this error in the test until we fix them. profile_page.a11y_audit.config.set_rules({ - "ignore": ['color-contrast'], + "ignore": [ + 'color-contrast', # TODO: AC-232 + 'skip-link', # TODO: AC-179 + 'link-href', # TODO: AC-231 + ], }) profile_page.a11y_audit.check_for_accessibility_errors() @@ -791,4 +793,12 @@ class LearnerProfileA11yTest(LearnerProfileTestMixin, WebAppTest): different_username, _ = self.initialize_different_user(privacy=self.PRIVACY_PUBLIC) self.log_in_as_unique_user() profile_page = self.visit_profile_page(different_username) + + profile_page.a11y_audit.config.set_rules({ + "ignore": [ + 'skip-link', # TODO: AC-179 + 'link-href', # TODO: AC-231 + ], + }) + profile_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 4e8cbf599c..ec13ddfc41 100644 --- a/common/test/acceptance/tests/lms/test_lms_dashboard.py +++ b/common/test/acceptance/tests/lms/test_lms_dashboard.py @@ -233,10 +233,11 @@ class LmsDashboardA11yTest(BaseLmsDashboardTest): course_listings = self.dashboard_page.get_course_listings() self.assertEqual(len(course_listings), 1) - # There are several existing color contrast errors on this page, - # we will ignore this error in the test until we fix them. self.dashboard_page.a11y_audit.config.set_rules({ - "ignore": ['color-contrast'], + "ignore": [ + 'skip-link', # TODO: AC-179 + 'link-href', # TODO: AC-230 + ], }) self.dashboard_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 fed2f5b8cf..facd11b6d6 100644 --- a/common/test/acceptance/tests/studio/test_studio_library.py +++ b/common/test/acceptance/tests/studio/test_studio_library.py @@ -656,7 +656,13 @@ class StudioLibraryA11yTest(StudioLibraryTest): # There are several existing color contrast errors on this page, # we will ignore this error in the test until we fix them. lib_page.a11y_audit.config.set_rules({ - "ignore": ['color-contrast'], + "ignore": [ + 'color-contrast', # TODO: AC-225 + 'link-href', # TODO: AC-226 + 'nav-aria-label', # TODO: AC-227 + 'skip-link', # TODO: AC-228 + 'icon-aria-hidden', # TODO: AC-229 + ], }) lib_page.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 ff067e9fc7..ac9dde7f8e 100644 --- a/common/test/acceptance/tests/video/test_studio_video_module.py +++ b/common/test/acceptance/tests/video/test_studio_video_module.py @@ -344,6 +344,11 @@ class CMSVideoA11yTest(CMSVideoBaseTest): def test_video_player_a11y(self): # Limit the scope of the audit to the video player only. self.outline.a11y_audit.config.set_scope(include=["div.video"]) + self.outline.a11y_audit.config.set_rules({ + "ignore": [ + 'link-href', # TODO: AC-223 + ], + }) self._create_course_unit() 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 825a37e6c2..fb2c1fc6e9 100644 --- a/common/test/acceptance/tests/video/test_video_module.py +++ b/common/test/acceptance/tests/video/test_video_module.py @@ -3,6 +3,9 @@ """ Acceptance tests for Video. """ +import os + +from mock import patch from nose.plugins.attrib import attr from unittest import skipIf, skip from ..helpers import UniqueCourseTest, is_youtube_available, YouTubeStubConfig @@ -30,7 +33,6 @@ HTML5_SOURCES_INCORRECT = [ ] -@attr('shard_4') @skipIf(is_youtube_available() is False, 'YouTube is not available!') class VideoBaseTest(UniqueCourseTest): """ @@ -192,6 +194,7 @@ class VideoBaseTest(UniqueCourseTest): self.video.wait_for_video_player_render() +@attr('shard_4') class YouTubeVideoTest(VideoBaseTest): """ Test YouTube Video Player """ @@ -849,6 +852,7 @@ class YouTubeVideoTest(VideoBaseTest): execute_video_steps(tab1_video_names) +@attr('shard_4') class YouTubeHtml5VideoTest(VideoBaseTest): """ Test YouTube HTML5 Video Player """ @@ -870,6 +874,7 @@ class YouTubeHtml5VideoTest(VideoBaseTest): self.assertTrue(self.video.is_video_rendered('youtube')) +@attr('shard_4') class Html5VideoTest(VideoBaseTest): """ Test HTML5 Video Player """ @@ -1055,6 +1060,7 @@ class Html5VideoTest(VideoBaseTest): self.assertTrue(all([source in HTML5_SOURCES for source in self.video.sources])) +@attr('shard_4') class YouTubeQualityTest(VideoBaseTest): """ Test YouTube Video Quality Button """ @@ -1099,3 +1105,36 @@ class YouTubeQualityTest(VideoBaseTest): self.video.click_player_button('quality') self.assertTrue(self.video.is_quality_button_active) + + +@attr('a11y') +class LMSVideoModuleA11yTest(VideoBaseTest): + """ + LMS Video Accessibility Test Class + """ + + def setUp(self): + browser = os.environ.get('SELENIUM_BROWSER', 'firefox') + + # the a11y tests run in CI under phantomjs which doesn't + # support html5 video or flash player, so the video tests + # don't work in it. We still want to be able to run these + # tests in CI, so override the browser setting if it is + # phantomjs. + if browser == 'phantomjs': + browser = 'firefox' + + with patch.dict(os.environ, {'SELENIUM_BROWSER': browser}): + super(LMSVideoModuleA11yTest, self).setUp() + + def test_video_player_a11y(self): + self.navigate_to_video() + + # Limit the scope of the audit to the video player only. + self.video.a11y_audit.config.set_scope(include=["div.video"]) + self.video.a11y_audit.config.set_rules({ + "ignore": [ + 'link-href', # TODO: AC-223 + ], + }) + self.video.a11y_audit.check_for_accessibility_errors() diff --git a/package.json b/package.json index 876b169897..c7f7232cb4 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "uglify-js": "2.4.24" }, "devDependencies": { - "jshint": "^2.7.0" + "jshint": "^2.7.0", + "edx-custom-a11y-rules": "edx/edx-custom-a11y-rules" } } diff --git a/pavelib/paver_tests/test_paver_bok_choy_cmds.py b/pavelib/paver_tests/test_paver_bok_choy_cmds.py index 9df04d09e9..87a0969cd6 100644 --- a/pavelib/paver_tests/test_paver_bok_choy_cmds.py +++ b/pavelib/paver_tests/test_paver_bok_choy_cmds.py @@ -25,6 +25,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): "DEFAULT_STORE={default_store} " "SCREENSHOT_DIR='{repo_dir}/test_root/log{shard_str}' " "BOK_CHOY_HAR_DIR='{repo_dir}/test_root/log{shard_str}/hars' " + "BOKCHOY_A11Y_CUSTOM_RULES_FILE='{repo_dir}/{a11y_custom_file}' " "SELENIUM_DRIVER_LOG_DIR='{repo_dir}/test_root/log{shard_str}' " "nosetests {repo_dir}/common/test/acceptance/{exp_text} " "--with-xunit " @@ -35,6 +36,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): repo_dir=REPO_DIR, shard_str='/shard_' + self.shard if self.shard else '', exp_text=name, + a11y_custom_file='node_modules/edx-custom-a11y-rules/lib/custom_a11y_rules.js', ) return expected_statement diff --git a/pavelib/utils/envs.py b/pavelib/utils/envs.py index ac5b5be565..7fef62016f 100644 --- a/pavelib/utils/envs.py +++ b/pavelib/utils/envs.py @@ -32,6 +32,10 @@ class Env(object): BOK_CHOY_A11Y_REPORT_DIR = REPORT_DIR / "a11y" BOK_CHOY_COVERAGERC = BOK_CHOY_DIR / ".coveragerc" BOK_CHOY_A11Y_COVERAGERC = BOK_CHOY_DIR / ".a11ycoveragerc" + BOK_CHOY_A11Y_CUSTOM_RULES_FILE = ( + REPO_ROOT / "node_modules" / "edx-custom-a11y-rules" / + "lib" / "custom_a11y_rules.js" + ) # If set, put reports for run in "unique" directories. # The main purpose of this is to ensure that the reports can be 'slurped' diff --git a/pavelib/utils/test/suites/bokchoy_suite.py b/pavelib/utils/test/suites/bokchoy_suite.py index 7e87b15c33..2c73597a9b 100644 --- a/pavelib/utils/test/suites/bokchoy_suite.py +++ b/pavelib/utils/test/suites/bokchoy_suite.py @@ -55,6 +55,7 @@ class BokChoyTestSuite(TestSuite): self.num_processes = kwargs.get('num_processes', DEFAULT_NUM_PROCESSES) self.extra_args = kwargs.get('extra_args', '') self.har_dir = self.log_dir / 'hars' + self.a11y_file = Env.BOK_CHOY_A11Y_CUSTOM_RULES_FILE self.imports_dir = kwargs.get('imports_dir', None) self.coveragerc = kwargs.get('coveragerc', None) @@ -205,6 +206,7 @@ class BokChoyTestSuite(TestSuite): "DEFAULT_STORE={}".format(self.default_store), "SCREENSHOT_DIR='{}'".format(self.log_dir), "BOK_CHOY_HAR_DIR='{}'".format(self.har_dir), + "BOKCHOY_A11Y_CUSTOM_RULES_FILE='{}'".format(self.a11y_file), "SELENIUM_DRIVER_LOG_DIR='{}'".format(self.log_dir), "nosetests", test_spec,