Uncharted Territory

Using aXe to Forge a Path

Madalyn Parker

Why Accessibility?

@madalynrose

Laws

Statistics

$$$

Code Quality

Β 

Everyone should be able to use the web☝🏿☝🏻☝🏼☝🏾☝🏽

<

@madalynrose

What is Web Accessibility About?

@madalynrose

Before: following the map

  • Meeting Standards (WCAG 2.0)
    • dichotomy: either it's compliant or it isn't
  • WAI-ARIA (W3C)
  • Tab indexes
  • Working with every screen reader/OS/browser

✨RULES✨

@madalynrose

Packing for the Journey

@madalynrose

πŸ“Œ Scoping πŸ“

Which part of your application do you start with?

What is small enough for me to cover?Β 

What could benefit the most?

What has the furthest reach?

Β 

@madalynrose

🌾 Resources ⛏

  • me
  • 1 month
  • browser audit tools
  • consultants
  • web a11y community
  • node modules
    • axe-core
    • react-a11y

@madalynrose

Deque Systems

@madalynrose

@marcysutton

⚽️ Game Plan πŸ“‹

  • Get axe-core working with testing stack
  • Run test audits on all frontend components
  • Address audit results
  • Manual testing
  • Address results

@madalynrose

Clearing the Brush

@madalynrose

Running Tests With aXe

using axe.run

  • arguments
    • context (section of the DOM we are testing)
    • options
      • rules
      • selectors
    • callback
  • results
    • arrays of what passed and what didn't

@madalynrose

A11yHelper Setup/Cleanup

  //mount component properly
  mountForA11yTest: (component) =>
    dom = new DOMContext()
    doc = dom.getDocument()
    div = doc.createElement('div')
    doc.body.appendChild(div)

    wrapper = mount(component, { attachTo: div })

    return { wrapper: wrapper, div: div, dom: dom }
  //clean up after ourselves
  cleanUpA11yMount: (div, dom) =>
    dom.getDocument().body.removeChild(div)
    dom.destroy()

@madalynrose

A11yHelper Audit

  runAudit: (node, config) =>
    oldNode = global.Node
    global.Node = node.ownerDocument.defaultView.Node

    return new Promise((resolve, reject) =>
      axeCore.run(node, config, (err, results) =>
        global.Node = oldNode
        if err
          reject(err)
        else
          try
            assert.equal AxeCoreResults.hasViolations(results), false 
            assert.equal AxeCoreResults.getViolationsList(results).length, 0
            resolve()
          catch e
            reject(e)
      )
    )

@madalynrose

Testing Flow

/*
ImageComponent = ({ url, altText }) ->
    <img src={url} alt={altText} />
*/

describe '<ImageComponent />', =>
  it 'should have no accessibility errors', ->
    url = 'https://mywebsite.com/some/path/to/an/image.jpg'
    //return passesA11yTest(<ImageComponent url={url} altText={""}/>

@madalynrose

Success!

tests caught a lot of surface-level problems

@madalynrose

Logs and Boulders

@madalynrose

@madalynrose

@madalynrose

🌈

@madalynrose

🌈

🌲

🌲

🌲

@madalynrose

@madalynrose

🌈

🌈

🌈

@madalynrose

🌲

🌈

🌈

🌈

🌲

🌲

🌲

🌲

@madalynrose

🌲

🌈

🌈

🌈

🌲

🌲

🌲

🌲

🌲

🌲

🌲

🌲

@madalynrose

@madalynrose

🌈

🌈

🌈

@madalynrose

🌈

🌈

🌈

🌲

🌲

🌲

🌲

🌲

🌲

🌲

🌲

@madalynrose

@madalynrose

🌈

🌈

🌈

@madalynrose

🌈

🌈

🌈

🌲

Accessibility Gaps

  • Superfluous elements
  • Navigation
  • JS hidden elements
  • Live areas

@madalynrose

Building Something New

@madalynrose

Pruning

What can go?

@madalynrose

New Trails

@madalynrose

Adjusting Focus

@madalynrose

Turn-by-turn Directions

@madalynrose

  <div
    aria-live="assertive"
    aria-atomic="true"
    role="alert"
    id={id}
    style={defaultStyles}>
    <p>{text}</p>
  </div>
  defaultStyles = {
    position: 'absolute',
    visibility: 'visible',
    overflow: 'hidden',
    display: 'block',
    width: '1px',
    height: '1px',
    margin: '-1px',
    border: '0',
    padding: '0',
    clip: 'rect(0px, 0px, 0px, 0px)',
    clipPath: 'polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px)',
    whiteSpace: 'nowrap'
  }

Olark's Announcer

@madalynrose

Olark's Announcer

control region changes in state based on chat box focus

if(chat box is focused)

    add event to list of announcements

    join list of announcements with periods

    dump list of announcements into announcer

else

    # chat box will already play a notification
    # sound if it is not focused

    add event to list of announcements

@madalynrose

What is Web Accessibility About?

@madalynrose

πŸ“’ RULES πŸ“’

@madalynrose

🌈 USABILITY 🌈

@madalynrose

🌈 USABILITY 🌈

@madalynrose

  • Repeatability
  • Establishing and sticking to patterns
  • Starting Somewhere
  • Iteration

Thanks

@madalynrose

https://slides.com/madalynrose/axe/

Resources

@madalynrose

Uncharted Territory: Using aXe to Forge a Path

By Madalyn Parker

Uncharted Territory: Using aXe to Forge a Path

  • 1,432