Skip to content

Commit

Permalink
add agnostic-axe code
Browse files Browse the repository at this point in the history
  • Loading branch information
Juliette Pretot committed Nov 19, 2019
1 parent 20ee29d commit 147dc2b
Showing 1 changed file with 151 additions and 1 deletion.
152 changes: 151 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1 +1,151 @@
// noop
import axe from 'axe-core'

// If requestIdleCallback is not supported, we fallback to setTimeout
// Ref: https://developers.google.com/web/updates/2015/08/using-requestidlecallback
const requestIdleCallback =
window.requestIdleCallback ||
function(callback) {
setTimeout(callback, 1)
}

class AxeReporter {
constructor(
targetNode = document.body,
analyseTimeout = 1000,
axeConfig = {
checks: [
{
id: 'color-contrast',
options: {
noScroll: true
}
}
]
}
) {
this._auditTargetNode = this._auditTargetNode.bind(this)

axe.configure(axeConfig)

this._alreadyReportedIncidents = new Set()

this._mutationObserver = new window.MutationObserver(() => {
requestIdleCallback(this._auditTargetNode, { timeout: analyseTimeout })
})

this._mutationObserver.observe(targetNode, {
attributes: true,
subtree: true
})
}
async _auditTargetNode() {
const response = await axe.run()

const violationsToReport = response.violations.filter(violation => {
const filteredNodes = violation.nodes.filter(node => {
const key = node.target.toString() + violation.id

const wasAlreadyReported = this._alreadyReportedIncidents.has(key)

if (wasAlreadyReported) {
// filter out this violation for this node
return false
} else {
// add to alreadyReportedIncidents as we'll report it now
this._alreadyReportedIncidents.add(key)
return true
}
})

return filteredNodes.length > 0
})

const hasViolationsToReport = violationsToReport.length > 0

if (hasViolationsToReport) {
AxeReporter.reportViolations(violationsToReport)
}
}
static REPORT_STYLES = {
critical: 'color:red; font-weight:bold;',
serious: 'color:red; font-weight:normal;',
moderate: 'color:orange; font-weight:bold;',
minor: 'color:orange; font-weight:normal;',
elementLog: 'font-weight:bold; font-family:Courier;',
defaultReset: 'font-color:black; font-weight:normal;'
}
static reportViolations(violations) {
console.group('%cNew aXe issues', AxeReporter.REPORT_STYLES.serious)
violations.forEach(violation => {
const format =
AxeReporter.REPORT_STYLES[violation.impact] ||
AxeReporter.REPORT_STYLES.minor
console.groupCollapsed(
'%c%s: %c%s %s',
format,
violation.impact,
AxeReporter.REPORT_STYLES.defaultReset,
violation.help,
violation.helpUrl
)
console.groupEnd()
violation.nodes.forEach(node => {
AxeReporter.reportFailureSummary(node, 'any')
AxeReporter.reportFailureSummary(node, 'none')
})
})
console.groupEnd()
}
static reportFailureSummary(node, key) {
// This method based off react-axe's failureSummary
// Ref: https://github.com/dequelabs/react-axe
function logElement(node, logFn) {
const elementInDocument = document.querySelector(node.target.toString())
if (!elementInDocument) {
logFn(
'Selector: %c%s',
AxeReporter.REPORT_STYLES.elementLog,
node.target.toString()
)
} else {
logFn('Element: %o', elementInDocument)
}
}

function logHtml(node) {
console.log('HTML: %c%s', AxeReporter.REPORT_STYLES.elementLog, node.html)
}

function logFailureMessage(node, key) {
const message = axe._audit.data.failureSummaries[key].failureMessage(
node[key].map(check => check.message || '')
)

console.error(message)
}

if (node[key].length > 0) {
logElement(node, console.groupCollapsed)
logHtml(node)
logFailureMessage(node, key)

const relatedNodes = node[key].reduce(
(accumulator, check) => [...accumulator, ...check.relatedNodes],
[]
)

if (relatedNodes.length > 0) {
console.groupCollapsed('Related nodes')
relatedNodes.forEach(function(relatedNode) {
logElement(relatedNode, console.log)
logHtml(relatedNode)
})
console.groupEnd()
}

console.groupEnd()
}
}
}

export default AxeReporter

0 comments on commit 147dc2b

Please sign in to comment.