Accessibility Automation

@phenomnominal 2019

Is HArd, yes?

@phenomnominal 2019

Static ANalysis

@phenomnominal 2019

Lighthouse

@phenomnominal 2019

@phenomnominal 2019

@phenomnominal 2019

@phenomnominal 2019

Colour

@phenomnominal 2019

@phenomnominal 2019

@phenomnominal 2019

@phenomnominal 2019

Content

@phenomnominal 2019

AXE

@phenomnominal 2019

@phenomnominal 2019

@phenomnominal 2019

AXE + PUPPEteer

@phenomnominal 2019

@phenomnominal 2019

const { AxePuppeteer } = require("axe-puppeteer");
const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({
    headless: false
  });
  const page = await browser.newPage();
  await page.setBypassCSP(true);

  await page.goto("https://open.spotify.com");

  const results = await new AxePuppeteer(page).analyze();
  console.log(results);

  await page.close();
  await browser.close();
})();

@phenomnominal 2019

AXE + PUPPEteer + JEST

@phenomnominal 2019

@phenomnominal 2019

const { AxePuppeteer } = require("axe-puppeteer");
const puppeteer = require("puppeteer");

test(`accessibility hasn't got worst`, async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setBypassCSP(true);

  await page.goto("https://open.spotify.com");

  const results = await new AxePuppeteer(page).analyze();

  const violations = results.violations.map(violation => {
    delete violation.nodes;
    return violation;
  });

  expect(violations).toMatchSnapshot();

  await page.close();
  await browser.close();
});

@phenomnominal 2019

 PUPPEteer + JEST + Keyboard

@phenomnominal 2019

const puppeteer = require("puppeteer");

test(`can search with keyboard`, async () => {
  jest.setTimeout(30000);

  const browser = await puppeteer.launch({
    headless: false
  });
  const page = await browser.newPage();
  await page.setBypassCSP(true);

  await page.goto("https://open.spotify.com");

  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Enter");
  await page.keyboard.type("Propagandhi", { delay: 200 });
  await page.keyboard.press("Enter");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Tab");
  await page.keyboard.press("Enter");

  await page.close();
  await browser.close();
});

@phenomnominal 2019

 PUPPEteer + JEST + VOICEOVER + SPEECH-To-TEXT

@phenomnominal 2019

require("dotenv").config();

const util = require("util");
const path = require("path");
const exec = util.promisify(require("child_process").exec);
const recorder = require("node-record-lpcm16");
const fs = require("fs");

const speech = require("@google-cloud/speech");
const puppeteer = require("puppeteer");

async function voiceover() {
  const outputPath = path.join(__dirname, "./output.wav");
  const file = fs.createWriteStream(outputPath, {
    encoding: "binary"
  });

  const recording = recorder.record({
    sampleRate: 44100
  });
  recording.stream().pipe(file);

  const toggleVoiceoverScriptPath = path.resolve(
    __dirname,
    "./toggle-voiceover.scpt"
  );

  try {
    await exec(`osascript ${toggleVoiceoverScriptPath}`);

    const browser = await puppeteer.launch({
      headless: false
    });
    const page = await browser.newPage();
    await page.setBypassCSP(true);

    await page.goto("https://open.spotify.com/show/54XPfcl9oJdktfD1lT5V2N");

    await page.keyboard.press("Tab", { delay: 0 });
    await page.keyboard.press("Tab", { delay: 15000 });
    await page.keyboard.press("Tab", { delay: 2000 });
    await page.keyboard.press("Tab", { delay: 2000 });
    await page.keyboard.press("Tab", { delay: 2000 });
    await page.keyboard.press("Tab", { delay: 2000 });

    await page.close();
    await browser.close();

    await exec(`osascript ${toggleVoiceoverScriptPath}`);
    recording.stop();

    const speechClient = new speech.SpeechClient();
    const file = fs.readFileSync(outputPath);
    const audioBytes = file.toString("base64");
    const audio = {
      content: audioBytes
    };

    // The audio file's encoding, sample rate in hertz, and BCP-47 language code
    const config = {
      sampleRateHertz: 44100,
      languageCode: "en-US"
    };

    const request = {
      audio,
      config
    };

    // Detects speech in the audio file
    speechClient
      .recognize(request)
      .then(data => {
        console.log(data[0].results[0].alternatives[0].transcript);
      })
      .catch(err => {
        console.error("ERROR:", err);
      });
  } catch (e) {
    console.log(e);
  }
}

voiceover();

@phenomnominal 2019

What ELSE?

@phenomnominal 2019

Captions?

Animations?

@phenomnominal 2019

Questions?

@phenomnominal 2019

Fin.

Accessibility Automation

By Craig Spence

Accessibility Automation

  • 2,992