GithubHelp home page GithubHelp logo

isabella232 / jest-a11y-scanner Goto Github PK

View Code? Open in Web Editor NEW

This project forked from dequelabs/jest-a11y-scanner

0.0 0.0 0.0 386 KB

Custom Jest matcher for aXe for testing accessibility โ™ฟ๏ธ๐Ÿƒ

License: MIT License

JavaScript 100.00%

jest-a11y-scanner's Introduction

jest-a11y-scanner

Installation

Add the jest-a11y-scanner-4.3.0.tgz file to the root of your project in the same folder as your package.json

Install using the command below:

npm install --save-dev jest-a11y-scanner-4.3.0.tgz

Usage

Refer to this link when adding any a11y tests to your testing suite: https://github.com/telus/reference-architecture/blob/master/testing/functional/unit.md

Note: This will only work on components that will already be rendered when the axe scan is run. Also ensure that you are not over-engineering your components for accessibillity. For example, having a link that has inner text and an aria-label which causes redundancy for the purpose of having accessible test.

Running toHaveNoViolations with no additional options will use the default options. These are: emitting error on test failure, verbose output, and writing results to a "jest-a11y-reports" directory when complete.

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage', async () => {
  const render = () => '<img src="#"/>'

  // pass anything that outputs html to axe
  const html = render()

  expect(await axe(html)).toHaveNoViolations()
})

Screenshot of the resulting output from the usage example

Note, you can also require 'jest-a11y-scanner/extend-expect' which will call expect.extend for you. This is especially helpful when using the jest setupTestFrameworkScriptFile configuration.

Custom Parameters

You can turn erroring off by setting the "error" flag to fals in the options of toHaveNoViolations if you want to output violations without failing tests. This is useful if you are encountering a lot of errors and they are preventing you from committing to CI.

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with erroring off', async () => {
  const render = () => '<img src="#"/>'

  const html = render()

  // Pass false to prevent erroring, default is true when nothing is passed
  expect(await axe(html)).toHaveNoViolations({ error: false })
})

You can reduce the verbosity of output by setting the "verbose" flag to false in the options of toHaveNoViolations if you want to shorten the output of failing tests. This is useful if you are encountering a lot of errors and you want to clear up the console.

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with erroring off', async () => {
  const render = () => '<img src="#"/>'

  const html = render()

  // Pass false to restrict output verbosity, default is true when nothing is passed
  expect(await axe(html)).toHaveNoViolations({ verbose: false })
})

If you don't want to write to file when the test is run, you can set the "report" flag to false in the options of toHaveNoViolations. Reports are default written to the "jest-a11y-reports" directory in the current working directory called "report-{timestamp}.txt" with duplicates given an incrementing number at the end of the filename. If the "jest-a11y-reports" directory doesn't exist, one will be created.

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with erroring off', async () => {
  const render = () => '<img src="#"/>'

  const html = render()

  // Pass false to prevent to writing to file, default is true when nothing is passed
  expect(await axe(html)).toHaveNoViolations({ report: false })
})

You may also use these option flags in any combination when calling toHaveNoViolations. Such as expect(await axe(html)).toHaveNoViolations({ error: false, verbose: false }). Since the report flag is omitted, it will default to true. All flags default to true when omitted from the "options" object.

Writing Output to File

If you are in a test and you want to write the axe results to a specific file, you can pass the axe results to the reportViolations function with a path to a file. This function will automatically add the ".txt" extension for you.

const { axe, reportViolations } = require('jest-a11y-scanner')

it('writes to file', async () => {
  const render = () => '<img src="#"/>'

  const html = render()

  reportViolations(await axe(html), "./out_file.txt");
})

This should write out a report similar to this:

Report Date: Fri Dec 20 2019 10:45:06 GMT-0500 (Eastern Standard Time)

Axe-Core Version: 3.4.0

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Expected the HTML found at $('img') to have no violations:

<img src="#">

Received:

Images must have alternate text (image-alt)

Fix any of the following:
  Element does not have an alt attribute
  aria-label attribute does not exist or is empty
  aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty
  Element has no title attribute or the title attribute is empty
  Element's default semantics were not overridden with role="presentation"
  Element's default semantics were not overridden with role="none"

You can find more information on this issue here:
https://dequeuniversity.com/rules/axe/3.4/image-alt?application=axeAPI

If you would like to append to an existing file, you can pass "true" to the append parameter of reportViolations. Default is false.

const { axe, reportViolations } = require('jest-a11y-scanner')

it('writes to file', async () => {
  const render = () => '<img src="#"/>'

  const html = render()

  // pass true as the third parameter to append, default is false
  reportViolations(await axe(html), "./out_file.txt", true);
})

Testing React

const React = require('react')
const { render } =  require('react-dom')
const App = require('./app')

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')
expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with react', async () => {
  render(<App/>, document.body)
  const results = await axe(document.body)
  expect(results).toHaveNoViolations()
})

Testing React with Enzyme

Sometimes you will get errors on react code with child nodes like <MyComponent {props} /> when using Enzyme's shallow method. If that is the case, you may want to use the mount method shown below.

const React = require('react')
const App = require('./app')

const { mount } = require('enzyme')
const { axe, toHaveNoViolations } = require('jest-a11y-scanner')
expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with enzyme', async () => {
  const wrapper = mount(<App/>)
  const results = await axe(wrapper.getDOMNode())
  
  expect(results).toHaveNoViolations()
})

Testing React with React Testing Library

const React = require('react')
const App = require('./app')

const { render, cleanup } = require('@testing-library/react')
const { axe, toHaveNoViolations } = require('jest-a11y-scanner')
expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with react testing library', async () => {
  const { container } = render(<App/>)
  const results = await axe(container)
  
  expect(results).toHaveNoViolations()
  
  cleanup()
})

Note: If you're using react testing library you should be using the cleanup method. This method removes the rendered application from the DOM and ensures a clean HTML Document for further testing.

Testing Vue with Vue Test Utils

const App = require('./App.vue')

const { mount } = require('@vue/test-utils')
const { axe, toHaveNoViolations } = require('jest-a11y-scanner')
expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with vue test utils', async () => {
  const wrapper = mount(Image)
  const results = await axe(wrapper.element)

  expect(results).toHaveNoViolations()
})

Testing Vue with Vue Testing Library

const React = require('react')
const App = require('./app')

const { render, cleanup } = require('@testing-library/vue')
const { axe, toHaveNoViolations } = require('jest-a11y-scanner')
expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with react testing library', async () => {
  const { container } = render(<App/>)
  const results = await axe(container)
  
  expect(results).toHaveNoViolations()
  
  cleanup()
})

Note: If you're using vue testing library you should be using the cleanup method. This method removes the rendered application from the DOM and ensures a clean HTML Document for further testing.

Axe configuration

The axe function allows options to be set with the same options as documented in axe-core:

const { axe, toHaveNoViolations } = require('jest-a11y-scanner')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with a custom config', async () => {
  const render = () => `
    <div>
      <img src="#"/>
    </div>
  `

  // pass anything that outputs html to axe
  const html = render()

  const results = await axe(html, {
    rules: {
      // for demonstration only, don't disable rules that need fixing.
      'image-alt': { enabled: false }
    }
  })

  expect(results).toHaveNoViolations()
})

Setting global configuration

If you find yourself repeating the same options multiple times, you can export a version of the axe function with defaults set.

Note: You can still pass additional options to this new instance; they will be merged with the defaults.

This could be done in Jest's setup step

// Global helper file (axe-helper.js)
const { configureAxe } = require('jest-a11y-scanner')

const axe = configureAxe({
  rules: {
    // for demonstration only, don't disable rules that need fixing.
    'image-alt': { enabled: false }
  }
})

module.exports = axe
// Individual test file (test.js)
const { toHaveNoViolations } = require('jest-a11y-scanner')
const axe = require('./axe-helper.js')

expect.extend(toHaveNoViolations)

it('should demonstrate this matcher`s usage with a default config', async () => {
  const render = () => `
    <div>
      <img src="#"/>
    </div>
  `

  // pass anything that outputs html to axe
  const html = render()

  expect(await axe(html)).toHaveNoViolations()
})

jest-a11y-scanner's People

Contributors

nickcolley avatar dakebl avatar okry avatar thomasheyenbrock avatar camdub avatar connor-baer avatar piperchester avatar raven-wills avatar rzane avatar shaundr avatar simenb avatar zoetrope69 avatar greenkeeper[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.