From 8683437a05ff0fc30cb21958e919cd4cc91de835 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Thu, 9 May 2019 11:56:54 -0600 Subject: [PATCH 1/8] fix(tests): fix test for Safari, run Safari in CricleCI --- .circleci/config.yml | 16 ++++++++++ Gruntfile.js | 8 ++++- build/tasks/test-webdriver.js | 30 ++++++++++++++++--- lib/commons/color/contrast.js | 8 ++++- lib/commons/color/get-background-color.js | 9 ++++++ test/checks/keyboard/page-no-duplicate.js | 4 +-- test/commons/text/form-control-value.js | 7 +++++ .../rule-matches/landmark-has-body-context.js | 13 ++++---- 8 files changed, 82 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 56b4978cbf..91d765528d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -65,6 +65,16 @@ jobs: - <<: *restore_dependency_cache - run: npm run test:examples + test_macos: + macos: + xcode: "10.0" + steps: + - checkout + - run: npm install + - run: npm install -g grunt-cli + - run: npm run build + - run: grunt connect test-webdriver:safari + # Release a "next" version next_release: <<: *defaults @@ -117,12 +127,16 @@ workflows: - test_examples: requires: - test + - test_macos: + requires: + - test # Hold for approval - hold: type: approval requires: - test - test_examples + - test_macos filters: # We only want to hold on these two branches, as PR review acts as approval for PRs branches: @@ -135,6 +149,7 @@ workflows: - dependencies - test - test_examples + - test_macos filters: branches: only: develop @@ -144,6 +159,7 @@ workflows: - dependencies - test - test_examples + - test_macos - hold filters: branches: diff --git a/Gruntfile.js b/Gruntfile.js index f6df5e8266..9c007ecadc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,7 +34,13 @@ module.exports = function(grunt) { langs = ['']; } - var webDriverTestBrowsers = ['firefox', 'chrome', 'ie', 'chrome-mobile']; + var webDriverTestBrowsers = [ + 'firefox', + 'chrome', + 'ie', + 'chrome-mobile', + 'safari' + ]; process.env.NODE_NO_HTTP2 = 1; // to hide node warning - (node:18740) ExperimentalWarning: The http2 module is an experimental API. diff --git a/build/tasks/test-webdriver.js b/build/tasks/test-webdriver.js index ccc009b300..99af6b126b 100644 --- a/build/tasks/test-webdriver.js +++ b/build/tasks/test-webdriver.js @@ -87,7 +87,7 @@ module.exports = function(grunt) { /* * Build web driver depends whether REMOTE_SELENIUM_URL is set */ - function buildWebDriver(browser) { + async function buildWebDriver(browser) { var webdriver, capabilities; var mobileBrowser = browser.split('-mobile'); if (mobileBrowser.length > 1) { @@ -106,7 +106,29 @@ module.exports = function(grunt) { }; } - if (process.env.REMOTE_SELENIUM_URL) { + // @see https://github.com/SeleniumHQ/selenium/issues/6026 + if (browser === 'safari') { + var safari = require('selenium-webdriver/safari'); + var server = await new safari.ServiceBuilder() + .addArguments('--legacy') + .build() + .start(); + + if (process.env.REMOTE_SELENIUM_URL) { + webdriver = new WebDriver.Builder() + .usingServer(server) + .forBrowser('safari') + .withCapabilities(capabilities) + .usingServer(process.env.REMOTE_SELENIUM_URL) + .build(); + } else { + webdriver = new WebDriver.Builder() + .usingServer(server) + .withCapabilities(capabilities) + .forBrowser('safari') + .build(); + } + } else if (process.env.REMOTE_SELENIUM_URL) { webdriver = new WebDriver.Builder() .forBrowser(browser) .withCapabilities(capabilities) @@ -131,7 +153,7 @@ module.exports = function(grunt) { grunt.registerMultiTask( 'test-webdriver', 'Task for launching Webdriver with options and running tests against options URLs', - function() { + async function() { var driver; var isMobile = false; var done = this.async(); @@ -160,7 +182,7 @@ module.exports = function(grunt) { // try to load the browser try { - var webDriver = buildWebDriver(options.browser); + var webDriver = await buildWebDriver(options.browser); driver = webDriver.driver; isMobile = webDriver.isMobile; // If load fails, warn user and move to the next task diff --git a/lib/commons/color/contrast.js b/lib/commons/color/contrast.js index 1b467a26ec..fead29d509 100644 --- a/lib/commons/color/contrast.js +++ b/lib/commons/color/contrast.js @@ -74,7 +74,13 @@ color.Color = function(red, green, blue, alpha) { this.red = parseInt(match[1], 10); this.green = parseInt(match[2], 10); this.blue = parseInt(match[3], 10); - this.alpha = parseFloat(match[4]); + + // alpha values can be between 0 and 1, with browsers having + // different floating point precision. for example, + // 'rgba(0,0,0,0.5)' results in 'rgba(0,0,0,0.498039)' in Safari + // when getting the computed style background-color property. to + // fix this, we'll round all alpha values to 2 decimal points. + this.alpha = Math.round(parseFloat(match[4]) * 100) / 100; return; } }; diff --git a/lib/commons/color/get-background-color.js b/lib/commons/color/get-background-color.js index ef5b7f481f..d22925f362 100644 --- a/lib/commons/color/get-background-color.js +++ b/lib/commons/color/get-background-color.js @@ -118,6 +118,15 @@ color.filteredRectStack = function filteredRectStack(elm) { const boundingStack = rectStack.shift(); let isSame; + // Safari v12.1 does not include labels as part of elementsFromPoint() + // if they wrap an input element (UNLESS the label has a background + // color). this results in two different rectStacks (since + // elm.getClientRects() returns two rects for the element) which + // returns null as isSame is false. we can fix this by adding in the + // missing label to the boundingStack before checking for isSame + // @see https://bugs.webkit.org/show_bug.cgi?id=197743 + includeMissingElements(boundingStack, elm); + // iterating over arrays of DOMRects rectStack.forEach((rectList, index) => { if (index === 0) { diff --git a/test/checks/keyboard/page-no-duplicate.js b/test/checks/keyboard/page-no-duplicate.js index 556f55b4c0..8a7ec034d1 100644 --- a/test/checks/keyboard/page-no-duplicate.js +++ b/test/checks/keyboard/page-no-duplicate.js @@ -108,11 +108,11 @@ describe('page-no-duplicate', function() { function() { var options = { selector: 'footer', - nativeScopeFilter: 'main' + nativeScopeFilter: 'header' }; var div = document.createElement('div'); - div.innerHTML = '
'; + div.innerHTML = '
'; div.querySelector('#shadow').attachShadow({ mode: 'open' }).innerHTML = ''; axe.testUtils.fixtureSetup(div); diff --git a/test/commons/text/form-control-value.js b/test/commons/text/form-control-value.js index af6dbc98ca..0366fe8580 100644 --- a/test/commons/text/form-control-value.js +++ b/test/commons/text/form-control-value.js @@ -139,6 +139,13 @@ describe('text.formControlValue', function() { axe.utils .querySelectorAll(axe._tree[0], '#fixture input') .forEach(function(target) { + // Safari and IE11 do not support the color input type + // and thus treat them as text inputs. ignore fallback + // inputs + if (target.actualNode.type === 'text') { + return; + } + assert.equal( nativeTextboxValue(target), '', diff --git a/test/rule-matches/landmark-has-body-context.js b/test/rule-matches/landmark-has-body-context.js index 42b817b180..cc0f9aedb6 100644 --- a/test/rule-matches/landmark-has-body-context.js +++ b/test/rule-matches/landmark-has-body-context.js @@ -34,11 +34,14 @@ describe('landmark-has-body-context', function() { (shadowSupport ? it : xit)( 'returns false for elements contained in a landmark in a shadow DOM tree', function() { - var main = document.createElement('main'); - var shadow = main.attachShadow({ mode: 'open' }); - shadow.innerHTML = '