Skip to content

Commit

Permalink
Add jasmine tests and refactor to allow better testing
Browse files Browse the repository at this point in the history
Throw errors separately from the main testing to ease testing
  • Loading branch information
NickColley committed Aug 22, 2017
1 parent cc124f8 commit 8ab3503
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
(function (window, document, axe) {
// Cut the mustard at IE9+ since aXe only works with those browsers.
// http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
if (!document.addEventListener) return

function throwUncaughtError (error) {
// aXe swallows throw errors so we pass it through a setTimeout
// so that it's not in aXe's context
setTimeout(function () {
throw new Error(error)
}, 0)
}
window.GOVUK = window.GOVUK || {}

function renderNode (node) {
return (
' Check the HTML: \n' +
' `' + node.html + '`\n' +
' found with the selector: \n' +
' "' + node.target.join(', ') + '"'
)
}
function AccessibilityTest (selector, callback) {
if (typeof callback !== 'function') {
return
}

document.addEventListener('DOMContentLoaded', function () {
if (!document.querySelector('.js-test-a11y')) return
if (!document.querySelector(selector)) {
return callback('No selector "' + selector + '" found')
}

var axeOptions = {
restoreScroll: true,
include: ['.js-test-a11y']
include: [selector]
}
axe.run(axeOptions, function (err, results, blah, boo) {
if (err) {
throwUncaughtError(err)
callback('aXe Error: ' + err)
}

var violations = (typeof results === 'undefined') ? [] : results.violations

if (violations.length === 0) return
if (violations.length === 0) {
return callback('No accessibility issues found')
}

var errorText = (
'\n' + 'Accessibility issues at ' +
results.url + '\n\n' +
violations.map(function (violation) {
var help = 'Problem: ' + violation.help
var helpUrl = 'Try fixing it with this help: ' + violation.helpUrl
var htmlAndTarget = violation.nodes.map(renderNode).join('\n\n')
var htmlAndTarget = violation.nodes.map(_renderNode).join('\n\n')

return [
help,
Expand All @@ -51,7 +40,39 @@
].join('\n\n\n')
}).join('\n\n- - -\n\n')
)
throwUncaughtError(errorText)
callback(undefined, errorText)
})
})
}

var _renderNode = function (node) {
return (
' Check the HTML:\n' +
' `' + node.html + '`\n' +
' found with the selector:\n' +
' "' + node.target.join(', ') + '"'
)
}

var _throwUncaughtError = function (error) {
// aXe swallows throw errors so we pass it through a setTimeout
// so that it's not in aXe's context
setTimeout(function () {
throw new Error(error)
}, 0)
}

window.GOVUK.AccessibilityTest = AccessibilityTest

// Cut the mustard at IE9+ since aXe only works with those browsers.
// http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', function () {
AccessibilityTest('.js-test-a11y', function (err, results) {
if (err) {
return
}
_throwUncaughtError(results)
})
})
}
})(window, document, window.axe)
131 changes: 127 additions & 4 deletions spec/javascripts/govuk_publishing_components/AccessibilityTestSpec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,134 @@
/* global describe, beforeEach, it, expect */
/* global jasmine, describe, afterEach, beforeEach, it, expect */

var AccessibilityTest = window.GOVUK.AccessibilityTest

function addToDom (html) {
var div = document.createElement('div')
div.innerHTML = '<div class="js-test-a11y">' + html + '</div>'
document.getElementsByTagName('body')[0].appendChild(div)
}

function removeFromDom (selector) {
var nodeToRemove = document.querySelector(selector)
if (nodeToRemove) {
nodeToRemove.parentNode.removeChild(nodeToRemove)
}
}

function renderErrorMessage (option) {
var url = window.location.href
var message = ''
if (!option.skipHeader) {
message += '\nAccessibility issues at ' + url + '\n\n'
}
message += (
'Problem: ' + option.problem + '\n' +
'\n' +
'\n' +
' Check the HTML:\n' +
' `' + option.html + '`\n' +
' found with the selector:\n' +
' "' + option.selector + '"\n' +
'\n' +
'\n' +
'Try fixing it with this help: ' + option.helpUrl
)
return message
}

describe('AccessibilityTest', function () {
var selector = '.js-test-a11y'

beforeEach(function () {
// beforeEach
jasmine.DEFAULT_TIMEOUT_INTERVAL = 11000
})

afterEach(function () {
removeFromDom(selector)
})

it('default', function () {
expect(true).toBe(true)
it('should do nothing if no callback is specified', function () {
AccessibilityTest(selector)
})

it('should error if no selector is found', function (done) {
AccessibilityTest(selector, function (err, result) {
expect(result).toBe(undefined)
expect(err).toBe('No selector "' + selector + '" found')
done()
})
})

it('should throw if there\'s a contrast issue', function (done) {
addToDom('<a href="#" style="background: white; color: #ddd">Low contrast</a>')

AccessibilityTest(selector, function (err, result) {
if (err) {
throw err
}

var errorMessage = renderErrorMessage({
problem: 'Elements must have sufficient color contrast',
html: '<a href="#" style="background-color: white; color: rgb(221, 221, 221); background-position: initial initial; background-repeat: initial initial;">Low contrast</a>',
selector: '.js-test-a11y > a',
helpUrl: 'https://dequeuniversity.com/rules/axe/3.0.0-alpha/color-contrast?application=axeAPI'
})

expect(result).toBe(errorMessage)

done()
})
})

it('should throw if there\'s a alt tag issue', function (done) {
addToDom('<img src="">')

AccessibilityTest(selector, function (err, result) {
if (err) {
throw err
}

var errorMessage = renderErrorMessage({
problem: 'Images must have alternate text',
html: '<img src="">',
selector: '.js-test-a11y > img',
helpUrl: 'https://dequeuniversity.com/rules/axe/3.0.0-alpha/image-alt?application=axeAPI'
})

expect(result).toBe(errorMessage)

done()
})
})

it('should throw on multiple issues', function (done) {
addToDom('<img src=""><a href="#" style="background: white; color: #ddd">Low contrast</a>')

AccessibilityTest(selector, function (err, result) {
if (err) {
throw err
}

var errorMessage = (
renderErrorMessage({
problem: 'Elements must have sufficient color contrast',
html: '<a href="#" style="background-color: white; color: rgb(221, 221, 221); background-position: initial initial; background-repeat: initial initial;">Low contrast</a>',
selector: '.js-test-a11y > a',
helpUrl: 'https://dequeuniversity.com/rules/axe/3.0.0-alpha/color-contrast?application=axeAPI'
}) +
'\n\n- - -\n\n' +
renderErrorMessage({
skipHeader: true,
problem: 'Images must have alternate text',
html: '<img src="">',
selector: '.js-test-a11y > img',
helpUrl: 'https://dequeuniversity.com/rules/axe/3.0.0-alpha/image-alt?application=axeAPI'
})
)

expect(result).toBe(errorMessage)

done()
})
})
})
Empty file removed spec/javascripts/helpers/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions spec/javascripts/support/jasmine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#
src_files:
- app/assets/javascripts/govuk_publishing_components/vendor/*.js
- app/assets/javascripts/govuk_publishing_components/accessibility-test.js
- app/assets/javascripts/govuk_publishing_components/application.js

# stylesheets
Expand Down
11 changes: 5 additions & 6 deletions spec/javascripts/support/jasmine_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
# config.boot_dir = '/absolute/path/to/boot_dir'
# config.boot_files = lambda { ['/absolute/path/to/boot_dir/file.js'] }
#end
#
#Example: prevent PhantomJS auto install, uses PhantomJS already on your path.
#Jasmine.configure do |config|
# config.prevent_phantom_js_auto_install = true
#end
#

# Prevent PhantomJS auto install, uses PhantomJS already on your path.
Jasmine.configure do |config|
config.prevent_phantom_js_auto_install = true
end

0 comments on commit 8ab3503

Please sign in to comment.