Accessibility in JavaScript Applications

Accessibility Integration Testing

Marcy Sutton Todd

Marcy Sutton Todd

Principle Studios
Accessibility in JavaScript Applications

Check out a free preview of the full Accessibility in JavaScript Applications course

The "Accessibility Integration Testing" Lesson is part of the full, Accessibility in JavaScript Applications course featured in this preview video. Here's what you'd learn in this lesson:

Marcy discusses the reasons why integration and end-to-end testing are effective tools, and then goes over options for testing frameworks.


Transcript from the "Accessibility Integration Testing" Lesson

>> Marcy: But I wanna move on to another type of testing, accessible pages. And so we were talking about units. What if you have multiple units on a page that would change your testing approach? So, I think of accessible pages as really being about the interoperability of components. And for accessibility that can be important to handle focus, going from one component to another.

Like our client side routing, that would be a good example of something we could test. Because that's multiple components kind of interoperating with each other. And this is really the space where we get into integration and end-to-end test. And they're pretty synonymous to me. I think, maybe there is some differing opinions about.

If there's actually a difference in definition for those two, but I use them interchangeably. And I think a lot of other people do, too. But the basic ideas here are that these tests use real world browsers. So instead of headless browsers like JS DOM, you're using a real browser instance, which is more like whatever user would experience.

It's a space to test document or page level rules. So, things that only exist when you have a full HTML web page that's rendered. That there are some things for accessibility, there like page titles, things like that. Testing your widget interrop like I mentioned and color contrast may be a good one to test.

Because it's kind of computationally intensive, it's often a site level thing like testing the contrast of one component. Maybe if it's a component library, I could see that, like one in the note that all pass in isolation. But on most websites and web applications, color contrast would be something across the whole site.

And lastly, I find that these styles of tests are great for flexibility with frameworks, like when Angular 2 first came out. Their testing utilities were pretty new and a little bit rough to use. Maybe the docks weren't quite there, and so I could use Selenium WebDriver and Protractor aside from whatever the framework was saying to use at that time.

It's sort of one step removed from the actual framework APIs and it gives us some flexibility in stable testing environments so that we can write some tests. They end up being pretty portable, too. You could theoretically take the same integration test from a different site if the conditions are right.

And even, this is a good use case for any kind of testing unit testing as well. That if you're really writing your tests correctly, you should be able to do a whole rewrite. And if you're really focused on the outcome, your test should still pass. And I think the React team did that when they moved to Fiber.

They had a lot of tests that they were able to do a full rewrite and keep them passing. So, pretty fantastic. Here's an accessibility test example from Selenium WebDriver, which is one. It's an MPM install away for Selenium/WebDriver. And I can write some keyboard tests here. So in Selenium-land, I set up a driver, which is a new Selenium instance, and I can tell it what browser.

So here I am selecting Chrome, I tell it to go and get a URL, in this case, local host port 4,000. That returns a promise, and when that's done, that is my setup, so I've got the driver, I can run tests on. And in my test here I've got a test saying it should change state with the keyboard.

And this test is looking at a custom radio switcher. It's from eBay's MIND Patterns project. And so I'm testing to make sure that the aria-checked state, it's a state, not a property. That when I tell Selenium, I go send the keys, go send it a space key. I wanna make sure that this custom radio button would actually toggle that aria-checked state.

So that's what this test is doing. And it's series of promises that then chaining actions. And at the end I can assort that the attribute that I've gotten, I get attribute with aria-checked, that it will equal true. So, this is a good tool. It's maybe a bit more dated.

I've used Selenium WebDriver a lot. And now that I have been in other frameworks, I look at this, and I'm like [SOUND] [LAUGH], to be honest. Because that's a lot of extra syntax just to get the test to work. All of those all of the returning the element and keeping that chain alive.

It's a lot, the amount of time I spent trying to get the API to work, just was so effortless, I can't believe that worked. Selenium never goes that well. That's why I can't really believe it worked that well. So, what I'm using instead now is Cypress. And our project that you downloaded earlier in the day, that's why Cypress is in there.

It's a pretty big download, so that's kinda the cost of it. But it has a desktop interface that you could do some testing with. I don't know about the accessibility of the interface, but you can use it as just a run-once thing. So it doesn't open that interface.

And in our application, I'm gonna go to package.json. And here I've got some scripts for Cypress, so the site open will call Cypress open, cy:run is cy:run, Cypress run. And that's that opening the desktop testing interface versus just running it on the command line, so the use cases for that, the end-to-end.

So, the command that I'm going to use to run this, once I have some tests in here, is NPM run test:e2e. And you can call that whatever you want. It could be test:integration, test:cypress, whatever you wanna call it. But there's another example here for test:e2e:ci. And that's doing this one off cy:run just like do it.

So that way, if you're pushing to GitHub or something, and you want it to run your tests, you don't want it to get blocked on that interface. There's no person to interact with the interface, right? So we need those two things. And that's what these do. That's why these scripts are both in here.

But when I'm actively doing testing, kind of as a human, not a machine, I'm usually using the interface. But every now and then, the one off runs are nice. And maybe part of a larger test suite, that's what you would need. So, let's go back to our slide.

So, in this example I'm using Cypress. So, the API for the actual tests like describe and the it, that's a lot like other test frameworks, so pretty intuitive. So, I'm gonna describe some accessibility checks. This is referencing Cypress' type script definitions. So that will give you some autocomplete for the commands and give you some ideas about what these commands are.

So, before each test, I'm going to visit the homepage in this, it's just the /route. I'm gonna wait 500 milliseconds. Just in case the page needs render, sometimes gets the site's just like boot up time and the test environment for some reason. I found that that wait can help a little bit.

And it's using the API, not like a hacky set timeout or something. And in our test here, I'm saying it checks if a footer link is focusable and has the correct attributes. So, using the Cypress API get all by text, I can just pass it a random string to match something on the page.

In this case, that's looking for a link in the footer. So, maybe there's probably more than one link on a page that says Gatsby on the Gatsby site, so maybe this is a little brutal. But I could probably filter it further if I'm writing test just for the footer.

I could just use Cypress to go find the footer element and then start looking inside of it. That would be scoped to this, that section, and maybe that's how you group your test, maybe not. But I'm going to use the focused to return which element is focused, and then I can make assertion.

So, I'm saying it should have the text of Gatsby, it should have an attribute with And it should not have a CSS style of outline width of zero. And that last one depends on CSS and JS being there, I believe, because that's how it's setting it. I'm not sure that that would work with regular CSS, so that would be something to try.

I just happen to know that does use that, but maybe not. We'll go play with it and see

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now