Return String

Vision Deficiency Emulation With Puppeteer

Project Setup

Make sure you have Node and NPM installed. You can verify this by running node -v and npm -v in a terminal. Your Node version must be 14.3.0 or greater.

To install puppeteer you need to run npm install puppeteer from a terminal in your project folder.

If you are new to Puppeteer, consider reading the Puppeteer: Getting Started series to get up and running.

Finally, let's create an file called scrape.js and add some boilerplate to launch a browser and create a page.

Boilerplate

The boilerplate is based on Puppeteer: Better Project Setup which is part 6 of the Puppeteer: Getting Started series.

// Require the puppeteer library
const puppeteer = require('puppeteer');

async function run() {
    // Create the browser
    const browser = await puppeteer.launch();

    // Wrap scraping/testing code in try
    try {
        // Create a new page (tab) in the browser
        const page = await browser.newPage();

        // CODE USING PUPPETEER HERE

        // Catch and log errors
    } catch (error) {
        // Your chance to handle errors
        console.error(error);
    } finally {
        // Always close the browser
        await browser.close();
    }
}

// Run our function
run().catch(console.error);

The API

We can emulate color blindness and blurry vision easily by using the Chrome API for vision deficiencies. By calling page.emulateVisionDeficiency we can set what deficiency we want to apply with a string argument.

Currently Chromium supports achromatopsia, deuteranopia, protanopia, tritanopia and blurredVision. If you wish to stop emulation you can pass in a string of "none".

It is worth noting that enabling a vision deficiency does not change your CSS or computed styles in the browser. So far, I have found no way to programmatically access the changed color in automatic tests.

Color Blindness

There is a lot of nuance to color blindness and how it affect our users. This website provides an easy to understand overview of color blindness if you find, like me, that Wikipedia is too technical on the subject: https://www.colourblindawareness.org/colour-blindness/types-of-colour-blindness/

Achromatopsia: This rare condition makes you almost completely unable to see colors.

Deuteranopia: Red-green color blindness. (see article for differences)

Protanopia: Red-green color blindness. (see article for differences)

Tritanopia: Blue-yellow color blindness.

Taking Screenshots

Adding await page.emulateVisionDeficiency('tritanopia') somewhere in our puppeteer script will emulate blue-yellow colorblindness.

If we want to take a screenshot of multiple vision deficiencies, we can write a function like this:

/**
 * Take screenshots with selected deficiencies
 */
async function takeScreenshots(page, deficiencies) {
    // Loop over deficiencies
    for (const deficiency of deficiencies) {
        // Emulate current deficiency.
        await page.emulateVisionDeficiency(deficiency);

        // Take screenshot
        await page.screenshot({ path: `${deficiency}-screenshot.jpg` });
    }
}

To screenshot all the vision deficiencies currently available in Puppeteer we call that function with an array of every option:

const deficiencies = [
    'achromatopsia',
    'deuteranopia',
    'protanopia',
    'tritanopia',
    'blurredVision',
    'none'
];

The Code

This code will take a screenshot using every vision deficiency available in Chrome (including none) and save them each as a .jpg image.

// Require the puppeteer library
const puppeteer = require('puppeteer');

// Array of possible vision deficiencies
const deficiencies = [
    'achromatopsia',
    'deuteranopia',
    'protanopia',
    'tritanopia',
    'blurredVision',
    'none'
];

/**
 * Take screenshots with selected deficiencies
 */
async function takeScreenshots(page, deficiencies) {
    // Loop over deficiencies
    for (const deficiency of deficiencies) {
        // Emulate current deficiency.
        await page.emulateVisionDeficiency(deficiency);

        // Take screenshot
        await page.screenshot({ path: `${deficiency}-screenshot.jpg` });
    }
}

async function run() {
    // Create the browser
    const browser = await puppeteer.launch();

    // Wrap scraping/testing code in try
    try {
        // Create a new page (tab) in the browser
        const page = await browser.newPage();

        // Navigate to Return String website
        await page.goto('https://returnstring.com');

        // Take screenshots with vision deficiencies
        await takeScreenshots(page, deficiencies);

        // Catch and log errors
    } catch (error) {
        // Your chance to handle errors
        console.error(error);
    } finally {
        // Always close the browser
        await browser.close();
    }
}

// Run our function
run(deficiencies).catch(console.error);

Conclusion

With screenshots of pages or elements, we can now manually check if contrast is high enough to account for our colorblind users. While we don't yet have the tools to automate the process, hopefully that will come soon.