- node version 14+
- yarn
yarn
Ensure you have docker and (optionally) docker compose installed.
$ docker-compose up -d --build
# NOTE: For some of the exercises below, we will be writing
# and running the unit tests. To run the tests you will have
# to run them from within the container.
#
# - grab the container ID: `docker ps`
# - shell into the container: `docker exec -it CONTAINER_ID sh`
#
# from there you should be able to simply run `yarn test`
# build the image...
$ docker build -t recipes
# spin it up...
$ docker run \
-it \
--rm \
-v ${PWD}:/app \
-v /app/node_modules \
-p 1235:1235 \
recipes
# once that completes, navigate to http://localhost:1235
Day I
NOTE: This particular app is built with react. An understanding of react will be helpful but is not required. We will walk you through everything!
Go ahead and run your local dev server (yarn start
). Feel free to play around with the app and get familiar with it.
Check the awesome recipes app out @ http://localhost:1235
🍰 🍝 🐮 🧀 🍃
src/index.js
is the entry point to the app. It handles rendering the whole app and, when not in production, will include@axe-core/react
containers/App/index.js
handles the "states" of the<App />
component. It's sole purpose is to handle state and pass relevant props down tocomponents/App/index.js
components/App/index.js
renders the "structure" of the app. It is where the global navigation/skip link/main elements live.components/Stats/index.js
is where the recipe stats live ("X eggs used", "Y recipes made", etc.)components/Recipes/index.js
is where the recipe tiles live. It also instantiates the view/edit modals for each recipe.
review existing unit tests / assertions
yarn test --watch # you may have to type "a" into the console to get *all* tests to run!
Fix the failing tests!
Test the live region out with a screen reader!
🤖 quick demo of @axe-core/puppeteer
!
Let's run axe on our app now that we've got passing unit tests.
- install the axe extension
sign up for axe DevTools Pro too! https://www.deque.com/axe/devtools/
NOTE: If you have an expired trial, send us your email in slack or zoom chat and we will extend your trial!
- navigate browser to
http://localhost:1235
- open up axe devtools
- scan the page
- save results!
if you happened to have opened up the devtools console earlier, you probably saw a few of these violations printed out in the console via @axe-core/react
- review serious and critical issues
- fix all of those issues
- run the scan again until you have 0 violations (you can ignore the needs review color contrast issues -- no real issues there)
Day II
Intelligent what!?!
axe Devtools Pro's Intelligent Guided Tests will guide you through testing that can't be fully automated and needs a human to answer simple questions in order to raise accessiblity violations that axe can't find on its own. Don't worry, these questions will be very easy to answer and require 0 accessiblity testing expertise.
Find / fix issues related to heading structure and document title
Find / fix issues related to interactive elements including their various states (on the settings page)
Run the keyboard IGT and observe what it finds.
- fix the focus indication issues
hint
see `components/Recipes/index.css` (`.Recipes__card-edit:focus` style declaration) - fix the fact that the recipe card's edit button is not marked up as a real button 🤦
- write a new unit test for this!
- run the keyboard IGT again to verify that the issues have been resolved! (#axeCleanKeyboardIGT)
Run the images IGT and observe what it finds.
- fix the stats images by marking them up as presentational
- write a unit test for this!
hint
adding `alt=""` is sufficient (but you _can_ go above and beyond and also set `role=presentation`) - make the pencil icons "Edit" image's alt text descriptive / unique by following the wireframe's requirement and appending the recipe name to the alt text
- write a unit test for this!
Click on "COOK CHOCOLATE CAKE" button to launch the modal. In devtools, click "Start testing forms".
- fix the
aria-required
issue- bonus: add some visual indication that the field is required!
- make the error messages more descriptive
- write a unit test for this!
- run the IGT again to verify that no remaining Forms issues exist (#axeCleanFormsIGT)
If you have time, run through the other IGTs and see if you can find any other issues
We wrote unit tests as we found issues...This prevents us from making the same mistake in the future and ensures these issues do not creep back into the source code.
Example: test that the stats images are all properly marked as decorative/presentational
// components/Stats/index.test.js
test('marks each icon as decorative', () => {
const stats = shallow(<Stats stats={statsStub} />);
stats.find('.Stat__value img').forEach(icon => {
expect(icon.is('[alt=""]')).toBeTruthy();
});
});
- get axe running in your unit tests
- write a11y-specific unit tests
- run IGTs on your page(s)