Testing Accessibility
with Marcy Sutton
Making sure our apps and websites are accessible is a must-have for shipping. How can we be sure we're meeting a11y needs? Marcy Sutton will teach us how!
Topics
Resources & Links
- https://testingaccessibility.com/
- https://reactjs.org/docs/create-a-new-react-app.html
- https://testing-library.com/docs/ecosystem-jest-dom/
- https://testing-library.com/docs/ecosystem-user-event/
- https://www.learnwithjason.dev/let-s-learn-modern-redux
- https://www.cypress.io/
- https://egghead.io/
- https://translifeline.org/
Transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show, we're bringing back one of my favorite people, Marcy Sutton. Marcy, how are you?
MARCY: Hello. I'm doing pretty well. How about you, Jason?
JASON: I'm doing well. I'm very excited to be going into, you know, it's the first day of Pride month, so I'm super excited about that. Wearing my rainbow hat in solidarity. Very excited about that. We're also kicking off some things at Netlify that I'm really happy about, like we're going to be doing some donation matching to, what's it called, trans I can't I forgot. Oh, no, I should have looked this up. I forgot the name of it, but we're going to do be doing a donation matching to a trans lives matter or human rights organization to make sure we're helping with that. Doing initiatives with that. That has me really excited. And today I get to hang out with you, which is one of my favorite things in the whole world. It's been a while since we've had the chance to hang out, so I'm just very, very pleased to have you back around. But for folx who aren't familiar with you and your work, do you want to give us a little bit of a background on yourself?
MARCY: Sure thing. Well, as Jason said, I'm Marcy, and I'm a web developer who really enjoys working on accessibility. And I've done a bunch of different things in my career, and somehow I've gotten this far and I'm, like, still corralling myself back to where I started as a web developer. Because you kind of get pushed in all these different directions, like should a be a specialist, should I not? Should I be a manager? Should I not. I've done this career path. Now I'm a consultant and I work with organizations to help them with accessibility, as technical and as handson as possible. So, right now I can't really say who my client is, but I can say I'm enjoying doing both design, like, I'm giving input on design and an engineering for accessibility and working on some testing, automated testing, which I've done a lot of. It's, like, the perfect sweet spot of everything that I want to do, and I get to work part time, which is like a dream. So, yeah, things are good. I'm very happy.
JASON: Excellent. I'm so happy to hear that. And Phil showed up and shared the name of the charity. It's called translifeline.org. We'll make sure that shows up in the show notes for anybody who is interested. So, yeah, you have been, as you said, all over the stack. You've been an engineering manager. You've been in, like, kind of Dev rel, delve advocacy. You've been a straight up engineer. You've done it as a consultant, as a fulltime employee. So now you are in independently doing this, right? You're your own boss. Which is always amazing. So, that also means all you out there watching, after you see how amazing Marcy is or even now, you know what, sight unseen, go talk about bringing in Marcy to help you out. Today, we're going to talk a little bit about how to do, like, testing, right? So, the thing that's really important, and I think that we're seeing more and more of an adoption of this as a baseline strategy, which I think is largely thanks to the work of folx like you and the other folx in the accessibility community, is that companies are starting to realize that they can't treat accessibility as a feature or as a we'll do it later when we have time. They're starting to treat it as acceptance criteria for building and launching features. I know that's not true across the board, but I am seeing it come up more and more as a central consideration for companies when they talk about the way they build their product. And so that's all good in theory, right? Like I hear that, I nod my head. I want to do that, absolutely yes. What I'm not sure of, though, I do my best with accessibility, but I'm not an accessibility expert. What I don't know how to do is after I've set up that initial work, how do I make sure I don't reintroduce problems or that I'm paying attention to the things that I need to be paying attention to in the projects that I'm building without it being something that is, like, you know, given that it's out of my core expertise, right? So, what safeguards and guardrails can I put up for myself to make sure that I'm not accidentally making things worse? We talked a little bit about testing, right? So, today, we're going to work on that. I would love to get your take on, like, what's your philosophy around this? And because I feel like there are a lot of ways we could tackle this, so I'd love to hear what your preferred approach is.
MARCY: Yeah, so, I'm a big fan of automated testing. I've also worked on automated testing tools, so I know very intimately where the edge is on what you can automate and what you can't. It's improving by the day as new startups enter the space and, you know, people focus their PhD dissertations on, you know, areas or whatever, but I go in really trying to automate the lowhanging fruit of things that you shouldn't really trip over, definitely not more than once. Like if you write a component and it needs to respond to the keyboard, you can automate a lot of the testing to ensure that contract is there so that the component doesn't break unknowingly, as long as you have pretty robust tests. You know, either you don't break it coming back from a vacation or, you know, long weekend or whatever, and that your teammates know how something should work, and so there's a lot of those interactions that are based in the keyboard that you can start with, and that has a benefit of kind of by extension also supporting screenreaders, because there is a lot of overlap making things keyboard interactive and screenreader interactive. We can start with some of those basic interaction tests and that's where I usually go first, but I know that that's not going to cover everything, so I have to come at it from another angle as well by looking at the web content accessibility guidelines, you know, other best practices to know, okay, well, what am I missing through my automated test suite? Like quality of alternative text or, you know, things with screenreaders that can't be automated. So, testing the experience, and that is where it gets trickier for people who have the enthusiasm but not necessarily the knowledge of accessibility.
JASON: Mmhmm
MARCY: And I see this happen a lot where people are like, yay, accessibility, and they get in there and do that and it's wonderful and someone actually tests it and it's like, oh, this is pretty unuseful.
JASON: Yeah, so
MARCY: You have to test it.
JASON: Exactly, right? So, an example of this that I've seen is I've seen discussion about, like, the ARIA markup and how we make that work. One of the things that I see conflicting advice on is, you know, people are like, oh, make sure you add ARIA labels to things so that they're accessible and then you'll hear from the other end, you should only need ARIA labels if you're not using semantic markup. So it can be as somebody who is near to it but not deep in it, it can be hard to know where those boundaries are and, like, that sort of thing. So speaking as the person you're talking about, I care about it, but I don't have the deep knowledge that lets me know I don't have the instinctual understanding of how this works, understanding how to test these things and see, like, did I make this better or worse by trying to add these ARIA labels? Is what I'm doing actually improving things or am I just jumping through hurdles that are actually making this experience more difficult for everybody? So, I'm really excited to kind of dig into that a little bit and look at what the possibilities and are heuristics I can develop as a developer by default for accessibility. I know we're on a little shorter schedule than usual. We're going to try to wrap this one up by 30 minutes past the hour, so we've got about 50 minutes from now until we need to be done here. So, at the risk of being a little bit hasty, I'm going to try to jump us over into pair programming view, so that we can go ahead and start looking at some code together. The first thing that I want to do is make sure everybody knows we've got live captioning. We've got Jordan helping us out from White Coat Captioning. On the homepage of learnwithJason.Dev. Our live captioning is made possible through the support of our sponsors, we've got Netlify, fauna, Auth0 and Hasura, all kicking in to make the show more accessible to lots of people. Which means a lot to me. Make sure you head over to Twitter and follow Marcy there. A nonstop fountain of really good insights and knowledge and resources. So that is a highly recommended follow from me. Definitely go make that happen.
MARCY: Thanks, Jason.
JASON: So, Marcy, if we want to start, what do you think is the best place to start here, if I if we want to kind of do some basic testing?
MARCY: Sure thing. Well, I guess I should mention I have a project that I'm working on called Testing Accessibility. We sort of danced around it a little bit.
JASON: Yes.
MARCY: So Testing Accessibility is I'm kind of thinking of it as, like, my career thesis project almost. You know, going back to college, you kind of have this at least for me, I had a big project at the end of it. It's testingaccessibility.com, by the way. So, after working in accessibility and frontend development, I have some stories to tell and some insights to share, so this project is in partnership with Egghead. And the first step right now is that there is a free email course that you can subscribe to, and coming up later in the year will be some new workshop material, so I am super excited to finally get this off the ground, because I bought the domain name, you know, maybe a year and a half ago and was like, it's a sign. I need to make this project. And then reality set in of, oh, yeah, wait, I'm an engineering manager. How am I going to do all this stuff in addition? It just yeah, the timing wasn't quite right. So now I'm finally diving into it.
JASON: Yeah.
MARCY: And creating some new material. So, starting there, you know, for people who want to learn about accessibility ongoing, there's that, but in terms of sitting down right now to look at your project, I would say let's well, first, pick which UI we're going to talk about. Because that's usually where I'm starting, is I'm looking at something that already existing. Maybe I'm looking at designs, but I have something visual to react to. No pun intended. But something to look at how is a user with a keyboard only going to interact with this web page, and that's usually where I start.
JASON: Okay. So, what I'm going to suggest so that we don't have to figure out how to, like, implement tooling into a legacy project is let's start with Create React App. And we can put in a couple things so that we can look at how, like, how this gets done, maybe some ways that look right, but end up being wrong, and then how we can do tests to make sure that we don't fall into those traps. So, let's start here. We're gonna use Create React App today. And to do that, I'm going to npx createreactapp and then we'll give it a name. So, let's do that in the learnwithjason repo. Create React App and we'll call this one testingaccessibility.
MARCY: Nice. We can talk kind of as we're going through this about some of the really notable parts about clientrendered applications built with React or Vue or other things because there is common issues with clientside routing and focus management and really appy kind of interactivetype things that are really important. Like if we don't do anything about those when we're building these JavaScriptheavy websites, they end up being less accessible than if you had built something static in basic HTML.
JASON: For sure. Yeah. Talking about Veidt. I love Veidt. We did an episode last week, in fact, where we looked at. Let me see, let's go to episodes here. Oh, look at this. We've got a bunch of subscriptions coming in. Thank you all so much. Who's doing it? Ben, look at you gifting out all those subs. Thank you all so much to everybody who is getting a subright now. Make sure you abuse the heck out of that boop emote, because, remember, if you're motivated enough, you can bury us in boops, so thank you. Welcome all to the boop crew. Span those boops, as Amanda says.
MARCY: What have I been missing?
JASON: The show has gotten way weirder since the last time you were on, Marcy. The chat and I have a
MARCY: Weird is good.
JASON: The chat and I have become loving frenemies. (Laughter) But so, yeah, if you want to see how Veidt works with Create React App, we did this on the Modern Redux episode. It's super fast and powerful. We're going to stick with the heavily test Create React App so we have as few things as possible that can go sideways on us. So, what I'm going to do is open this up. And here is our repo, and inside of it, we see we have Testing Library is set up. Is Testing Library a good one to use for accessibility testing?
MARCY: Yes, it's amazing. Love it.
JASON: Excellent. Perfect. That's what I'm hoping for. So, we've got some basic tests set up. In our source folder, we have an app and a test harness set up there, so we should be able, if I'm understanding correctly, we should just be able to add more tests in this file, right?
MARCY: Yes. Yep.
JASON: Okay, perfect.
MARCY: They need to apply to something, so we might need a little more UI to test.
JASON: Yeah, so let's look at the start command here and see if we can get this going. So, we're going to do an npm run start.
MARCY: And I think we had one question in the chat a little while ago about the best phase of development to start accessibility testing, something like that.
JASON: Mmhmm.
MARCY: And it all depends what you have access to. I mean, if you get the opportunity to talk to the design teams you're working with and actually influence what they're doing by providing more technical guidance, you could hopefully have a better time at it, but if you're getting a site that's already built and you have to go in and fix it, better then than never, but the earlier you can incorporate accessibility, the better.
JASON: Yeah, I mean, I think it's like anything, right? You know this is something that you have to focus on, and so if you consider it from the beginning, you can make choices that support that as opposed to having to go back and reverse engineer a bunch of previous decisions to, like, fit something in after the fact. It's never fun to deal with that.
MARCY: And it might never it might never be accessible that way, too, because
JASON: That's fair, yeah.
MARCY: The design portion of it, like, we can only polish things so much as developers sometimes. Yeah, you can't go slap a bunch of ARIA labels on something when maybe the design fundamentally, the interactions, the visuals. So, yeah, we really want to shift it earlier in the process. But you don't always have that luxury.
JASON: Absolutely. Yeah.
MARCY: We can give ourselves some grace.
JASON: Now in this case, we do have that luxury. We can build a couple things in here. So, let's make some stuff we wanna test. So I feel like there are a couple things I imagine that are, like, really common. My guess is we want to test our forms, our navigation, and maybe a button. Are there any other things that you wanna, like, make sure that we cover?
MARCY: Sure. Some common ones that come to mind as common issues, like, maybe something that should be hidden but isn't, like a mega menu. If we had navigation that maybe we can do a testdriven development portion of, like, hey this has links in it. It's not open. They shouldn't be reachable right now. You know, we can write a test that, you know, asserts something and then maybe we go add the CSS to actually hide it or something like that.
JASON: Okay. Yeah, let's do that. Okay. So, maybe what we can do then is let's start with a form. Because a form I know how to code. So, I'm gonna do (Laughter) I'm gonna do a form. And in our form, we will set up a label, and it'll be like email, and I'm doing this in the worst possible way right now. So, I assume we're going to refactor this a little bit. And we're gonna do it like this and when we'll do like a button submit, right? And maybe we'll copy/paste these two and say this one's gonna be, like, name and name. Right? Okay. So, this is a it's not a pretty form, but it's here, and it's kind of doing what we want. And then we're gonna have okay. So, we did that one. And then we're gonna have some navigation. Maybe we can put our navigation on top, actually.
MARCY: Type text, by the way.
JASON: Oh, yeah, absolutely should. You are right. Okay. So, outside of just doing the minimal definitely not correct implementation here, I'm not gonna do the actually, like, broken implementation. (Laughter)
MARCY: Just inventing types, you know?
JASON: So, for navigation, we would want to use, like, the nav element or what's the right way to set this up?
MARCY: Yeah. So, in HTML 5, there are semantic elements for things like navigation, so we could use the nav. I think, you know, depending on the design of the site, if it should belong in the header because it's, you know, a logical area in the header, that's one consideration.
JASON: That's actually a good point. Let's put the nav up here.
MARCY: So we can put it up there. And then usually in a November, I'll put a list of links, you know, and unorder the list.
JASON: Oh, an unordered list, okay.
MARCY: Yep. And then you'll have links that navigate. So, this is a hot topic these days. Links for navigation versus buttons for interactions. And so on the web, when we are navigating the user to a place, it should be a link usually, but it gets a little fuzzy in web applications sometimes, especially if you have something that looks like a desktopstyle menu but it's full of links. It gets a little tricky sometimes. But just remember links that navigate, make them look like links. That's kind of the basics.
JASON: Yeah. And then let's add one more for testing accessibility. Here it is.
MARCY: We got a type equals boop.
JASON: Type equals boop. Okay. So, this is gonna be our nav. We've got one local link and two external links, and that is showing up in our Create React App. This is we'll have to fix our CSS a little bit here, but as a as a starting point, right, that's a nav. I feel like there are definitely things that need to be addressed here a little bit. But we can talk about that in a minute. And then maybe we want, like, a hidden nav here. Hmm. How would we want to do that?
MARCY: We could use the same nav that you've already written.
JASON: Okay.
MARCY: And maybe part of our styling will be to, like, show and hide or something like that.
JASON: Oh, yeah, perfect. So, if we do that, would there be a button here to, like
MARCY: Sure. That is a pattern I have had to code a lot. I would say if we're going to show and hide, maybe we could put it up at the top above the, you know, Learn React sorts of things.
JASON: Sure. Let's do it up at the very top of our header. Okay.
MARCY: And I'm not sure how far we will get, but we can kind of do the lowfi, you know, making a test fail because things are showing when they shouldn't be.
JASON: Yeah.
MARCY: Which is a solid way to do testdriven development.
JASON: Okay. So, before I make this actually show and hide, do you want to do tests?
MARCY: Yes.
JASON: Okay. Let's do it.
MARCY: I don't get to do this often enough. I'm always like more tests, more tests.
JASON: I'm ready. Let's do it. So, I'm gonna open up app.test.js. And so we have, let's see, can I do it this way? How's this gonna work?
MARCY: Ooh.
JASON: So we can kind of look at our bits here and see things and get our tests in. So, if I want to make a test, we would say, like, we're saying we want hidden things should be hidden when they're not visible on screen. So, this would be, like, hides
MARCY: Yeah.
JASON: nav links from keyboard nav when closed or hidden.
MARCY: Yeah, I forget. Do you give just DOM in this project? I know you had Testing Library.
JASON: That's a great question. Let's find out.
MARCY: Yes, we have jestdom.
MARCY: Part of what's fun but can be challenging is knowing your testing tools and being able to tell. You have to go read about some assertions for accessibility. For example, I'm looking jestdom to see if there is an is visible matcher or assertion or something like that. Often it will depend on the implementation whether it can actually assert the access things that we want. So, to really hide things, and there's a menu on this page that's actually very with, like, that little sliding drawer that just popped out is a perfect example of what we want to build. Behind this, you can see it's grayed out. The link, form controls, that should all be hidden somehow. You should not be able to toggle to it or tab to it with your keyboard. So, things like visibility hidden, that would change the display. I guess there's different there's different
JASON: Here comes some chaos, sorry. (Laughter)
MARCY: Oh, no. Oh, my gosh. It's a Corgi parade. So, anyway, there's different techniques for kind of changing the display or whether you can tab to things, and so this is an example of what I'm talking about.
JASON: Mmhmm.
MARCY: And so your testing tools, you know, if you want to rely on something like is visible, we need to go see how it works.
JASON: Yeah. Okay.
MARCY: Are we gonna get stampeded again?
JASON: No, it looks like we're okay.
MARCY: We're clear. (Laughter)
JASON: Oh, look, there is a toBeVisible. Is that going to be keyboard visible or visually visible?
MARCY: So, we haven't done any styling yet, so we would expect that if our menu, you know, our lowfi menu that we haven't fully coded yet, if we write something that says "this should not be visible," it's gonna fail because we haven't added the CSS or any functionality to actually hide it.
JASON: Ah. I got you.
MARCY: You get the failing test. You get the failing test written, and then you go and make it actually not be visible.
JASON: Okay. And so I can render app, and then we have screen here. And screen getByText. So, let's see this here. We want to render app. And then we'll say the haveLink is going to be screen.get wait, what was it? GetByText.
MARCY: Yeah, I tend to use Test Matcher or Test Attributes. Like in Cypress, you can use data attributes. Yeah, right there, datatestID. I tend to do those in case the text changes. Something kind of brutal. We can make our tests more robust. Because you know then that that is for a test element. And I'd probably put it on the anchor.
JASON: On the anchor? Okay.
MARCY: On the anchor tag.
JASON: All right. So, let's get that one out of here. And then we'll just put it on each of them. And I'm gonna close our drawer so that we can see a little bit more on the screen here.
MARCY: And I suppose it depends how you want to write your test, like, maybe you could put a data test ID on a parent node, like the UL, and then you can use the test framework to find each link. You know, you have possibilities with how you can code these. It sort of depends
JASON: Yeah.
MARCY: Yeah, how much logic testing code you want to include.
JASON: So, maybe what we should do for this one because we're going to be showing and hiding the whole nav is we can say we expect the main nav not to be visible by default. We're gonna start it hidden, and then when you toggle that button, it will open. So, we would we would expect here that main nav would be gettingBy let's see, queryByTestID.
MARCY: I love those APIs. I'm such a nerd.
JASON: Really nice. And then let's get mainnav. Okay. And then we can say expect main nav oh, wait, not toBeVisible. Am I doing that right?
MARCY: Yes. This will fail and make something pass with our styling. I'm trying to find the toBeVisible documentation. It's sending me all over the place.
JASON: I don't know what I'm doing. It wants to watch all my stuff. I think I just gave Facebook permission to watch my entire computer. Whoops.
MARCY: Okay. I did find the documentation for toBeVisible. It is under Testing Library
JASON: Dirty hackers. Sorry.
MARCY: What's happening?
JASON: Sound effects. We've got fullblown chaos.
MARCY: Wow.
JASON: Let's see. I think this might have stopped because I asked for permission. So, let's run that again. Testing. Hello?
MARCY: Well, to sort of fill in the space, toBeVisible allows you to check if an element is currently visible including display not being sent to none. We can use that technique. You can use visibility as hidden or collapsed. I think visibility hidden, that one actually does remove things from, you know, keyboard access. Unlike opacity 0, if you used opacity 0, you would still be able to reach things in the menu.
JASON: That's not how that works as all, is it? Would it be a style?
MARCY: Yeah. So, we can style it however we want, and then we can write tests to assert that it's accessible or not. And so part of this will be checking visibility. We can also try and send focus into it and expect that it won't be focusable, like any of the links inside of the nav. That's kind of the, you know, there is a visibility part to it and then a functional interaction part to it. So, we'll write both of those assertions.
JASON: Okay. Is this correct?
MARCY: Yes. I'm going to I have some examples, but I'm blanking on at the moment. There's different techniques for doing these different hiding techniques and they all have, like, really nuanced differences. Actually, I have a code pen I could pull up that I've used in my frontend masters workshops and various things. Let me go find it.
JASON: Okay. Why aren't you running my tests, is my major concern right now.
MARCY: Yeah, no feedback, huh? It's just sort of hanging.
JASON: Yeah, it's just hanging, so I don't know if it's trying to activate.
MARCY: Maybe a nodes thing or something. That's usually what I try to do.
JASON: You do like log level, right? (Music) (Laughter)
JASON: What am I doing? Come on. Why are you like this?
MARCY: In an elevator or something. That's very dramatic.
JASON: Did I get that right? Is log level the wrong thing?
MARCY: I'm not sure. It might depend on the tool. Or is that a Node thing?
JASON: I don't know. Let's see. Hangs. Test command hangs. That's what we're running into. Test CI, no watchman. Okay.
MARCY: Watchman. I've never really used that.
JASON: I don't know what watchman is, so I'm gonna
MARCY: It must be something that Create React App includes or
JASON: Yeah, it must be. So, let's do it this way. And let's run test CI instead. And let's maybe do it without the there we go. Okay. So, no test files related to files changed since last commit. That's incorrect. Because we changed this one. Press "A" to run all tests. Let's run ' em. Fails. Perfect. Okay. So, received element and visible, and that's what we wanted. So, if we change our code, we've got class name, appnav, app CSS, appnav should be visibility hidden, and let's go look at our code.
MARCY: And to add more detail about the CSS that we're using, visibilityhidden will keep its space so it won't collapse, but it will make it not you don't see anything other than the space still being kept. But it will knock something out of the tab order, so you can't tab into anything with the keyboard that's in a visibility hidden region, and it will also impact what's called the accessibility tree, which is kind of like the dom, but it's all accessibility information that gets exposed to screenreaders and other assistive technologies.
JASON: Oh, whoops. I screwed that up. That's why that didn't work. Okay. So, then if I move into GitHub, testing accessibility, and we'll do npm run test: ci to run all our tests. And it says it is still despite the visibility hidden Belgian set. And if we look, we can see
MARCY: Maybe.
JASON: that it's hidden.
MARCY: Maybe this yeah, the two I'm looking at the jestdom documentation. So, I'm glad I mentioned earlier that you have to kind of go and read up on a tool to see if, like, it'll do what you expect. I'm looking at the documentation for jestdom, and it says it should be visible if it does not have its CSS property visibility set to either hidden or collapse, so that should work, but it doesn't seem like it is. So, things I would look for so, you're verifying that it's hidden in the actual UI.
JASON: Mmhmm.
MARCY: Are we testing the right element? Is there any kind of a timing issue? Let's see. So, we've got UL main nav. That's the test ID that you are querying for.
JASON: Mmhmm. And it finds that in our test, too, like, it's showing us the right thing. Here's our UL.
MARCY: Yep.
JASON: And then the class is appnav, which is over here. Appnav, and we can see here that it's hidden. Like it's not visible. I can't click anything.
MARCY: So, this might be a really unfortunate issue with jestdom. I'm actually searching their issue tracker.
JASON: Let's see if I do it the other way, because we would want this to bump in this case. So, let's do a display: none and a display: block to see if that solves our problem here.
MARCY: Yeah, unfortunately, I did find an issue on jestdom's issue tracker from February 2020.
JASON: Perceived element is visible. Are you testing something that I am not
MARCY: It might be an issue with the tool, which in that case, I end up pivoting my approach, so if the if the assertion or the tool isn't going to give me a reliable result, I tend to, like, think of another way to test it. So, we could since that's not doing what we expect, what we really care about is keyboard users not going into something that's invisible. And so we could assert, you know, when it's closed. That's where the visibility piece is nice, but maybe there's another there's something we can check for or a different tool we can use.
JASON: Yeah.
MARCY: Although we should
JASON: So, maybe what I can do is I can just put together the open and, like, setOpen here and we'll do a useState that comes in from React. We'll start it at false. And then what we can do is with our appnav, we're setting
MARCY: And we got a couple comments in the chat. Someone suggesting inline styling, which maybe that could help you roll out if, like, your styles aren't being applied in the Test Suite or something, but in terms of, like, the enduser experience, that shouldn't make a difference. But we could take Ryan Warner's suggestion of moving removing the not to see if it will pass on the not toBeVisible to see if that assertion is working at all.
JASON: Oh, yeah, good call.
MARCY: It should be visible right now. So, yeah, maybe it's an issue with the toBeVisible with the visibility hidden. So, what we could try, another piece of data that we could pull in is trying to use displaynone instead of visibilityhidden, and that will collapse it completely. It won't hold its space. Oh, you have
JASON: Yeah, so, I tried that, and it didn't do what I thought it would do, which is a little confusing.
MARCY: Huh.
JASON: But it is yeah, not sure why
MARCY: Still not working, huh?
JASON: Maybe what we can do is is we can do, like, a navlink.
MARCY: Your audience really likes inline styles. What am I not surprised? Hey, they have a place. They have a purpose. I'm wondering if there's a timing issue, like, in the event loop, JavaScript is checking for some display. It's maybe I would be surprised since there's into animations, but every now and then, more than we would like, there are timing issues with accessibility. Listening for CSS transitions and animations, sometimes you can wait and make sure something is done being styled. Found multiple elements.
JASON: That's my fault. I add the same test ID to a bunch of things, which I'm realizing now is not correct. So, maybe
MARCY: Nicky T says try find by test ID. I don't know if that'll help.
JASON: Is that different than query by test ID?
MARCY: Maybe that's for multiple? I'm not sure.
JASON: Received element is visible. So I think you're right, that this is a timing issue, because it's but it doesn't make any sense that it's a timing issue, because unless the CSS is being applied after the fact, which I guess is possible because we're importing it like this
MARCY: Mmhmm.
JASON: Okay. So, let's try inline CSS. Let's do it. Let's see what happens.
MARCY: Yeah, this is all interesting data gathering. So, of course, I would love it if everything went smoothly, but it's kind of more helpful to, like, see what happens when you try to test stuff for accessibility. Because there is some wrangling of tooling, love it or hate it. We tid get one suggestion to try Cypress instead, which I do love Cypress. Because sometimes it can be the tooling. Like you're trying to test the UI and CSS stuff in a headless test suite or, you know, if it's not rendering in a browser, it has some weird edge cases with how the testing tools are implemented.
JASON: Oh, it was definitely a timing issue with the way that CSS gets imported. So, now that it's in line, it's doing what we expect.
MARCY: Huh, interesting.
JASON: And so we can, like, revert here. Let's go back to main nav.
Aha! Behold, my bucket!
JASON: That's the bucket. It's a timing issue. So, apparently the way the Dev server loads CSS in Create React App means the tests run before CSS is applied. Which is not ideal. But we worked around it.
MARCY: Yeah, what do you do about that?
JASON: So, then the good thing is is that, like, by using my keyboard, I can see that this is missing. Like I can't get into it.
MARCY: Cool.
JASON: But if I change the visibility, then I can keyboard nav into this.
MARCY: Cool.
JASON: Which is good. That's what we wanted.
MARCY: And we can write a test that basically asserts that, you know, that manual piece.
JASON: Ooh, yeah, let's do it. So, test links are keyboard navigable when nav is open.
MARCY: Yes. I love that you're writing a separate test because I totally would have lumped it in with the other one.
JASON: So, I mean, honestly, I'm mostly doing this just because I don't really know how all of this is going to work, so I'm gonna grab this, and now I want to click on main nav. So, can I just, like, does that just work? Can I just click?
MARCY: Yeah. Yep. You should be able to interact with it as a user would. So, is main nav, that's the UL, so you might need to find the button or whatever
JASON: Oh, that's right. That's right.
MARCY: The on click handler is
JASON: Yes.
MARCY: Think like a user. I am finding the button and clicking it. You can even get really fancy and say, you know, to test the keyboard accessibility of the button, maybe this could be a separate test, but say it was a div that had a click event on it, you could write a failing accessibility test for the keyboard trying to focus on it and then the tool will yell at you. That you're trying to focus on something that is not focusable.
JASON: Oh, okay. Let's start with that. Let's start with the thing that we want to figure out, which is we want to get the nav link, and we're only checking for one right now. I think I took it off the others. So, we've got the nav link. And the others don't have it. So, we're gonna just test for this one. So, we'll do a screen query by test ID, and we're going to get the nav link. And then what's the so, if I go to navlink.focus
MARCY: Yes. So, this is when the menu is closed, correct?
JASON: Mmhmm.
MARCY: So, yeah, if you engine expect well, is there a test property or something for the focused element? I mean, in JavaScript, we always have document.actdevelopment, which will return the most current element. In Cypress, it's Cypress focused.
JASON: It looks like there is a to have focus option auto completed for me. So, let's see what that does.
MARCY: Okay. It should fail, I would think. No, it passed.
JASON: It does say that it's hidden. But it is finding this nav.
MARCY: And we don't have any tests that are open in the menu yet, correct?
JASON: No, this was the part that would have opened it, so it should have should have
MARCY: So, there's no, like, stale state.
JASON: Just for just for double checking, let's run that test again and make sure that it's not doing something weird. Yeah, so it expects the nav is not visible, but inside of the nav, we're finding this nav link and we're focusing on it.
MARCY: That should fail. And this is where the testing tools, you kind of have to know, like, what's happening with them. A lot of the older testing tools, this wasn't something we could rely on to, like, have the tool tell you whether you're trying to focus on a nonfocusable element. But now that we can, but it does require some finessing. So we know we have the right nav link.
JASON: Right.
MARCY: We're sending a focus event to it. And I guess it really depends what the test is doing. I mean, it should be sending an actual focused event there, and that should fail if it's not, you know, that link is inside of a nav element with display none on it. So that should, you know, make sure it can't be focus on.
JASON: So, it's clear that it's not visible. Which is good. Is it, like, because the parent element is not visible, but we, like, dom selected the nav link, can you focus on a hidden element if you, like, directly go to it? Should we try to do something where we, like, tab or something? Does that work?
MARCY: Sure. Yeah, let's try it. Yeah, it should. So, what you could do is, like, use the testing tool to maybe you get the main nav and then do do a, like, keyboard event. Let's see. So, jest yeah, how do you do event? Testing Library would be the event user event part, right?
JASON: Enter key hint. Access key.
MARCY: I mean, so, the Native JavaScript event we would probably be using is on keyUp so that when the user lets go of the key, it would do its thing. In Testing Library, they made an extra package called User Event. And I don't know if they have oh, yeah, there's a tab. There's a tab part of the API.
JASON: Okay. So, I need to install that?
MARCY: That would help. I mean, I would it's a tool I would reach for if I was using Jest and Testing Library, so might as well try it.
JASON: You said it's called the user event?
MARCY: It is I'm going to find the whole way to install it. It is@testing.library/user/event.
JASON: Perfect. Did they install these
MARCY: Wow, time is flying by, huh?
JASON: I know, it happens so fast. These are all regular dependencies. So it goes as a regular dependency.
MARCY: And we got a question or a comment I apologize, I haven't caught all of them, but there was a question about whether to check by a roll or something accessibility related instead of getBytestID. I would say those tend to be more brittle for test cases than using a dedicated test ID. So that then it's pretty clear that's what the testing mechanism is for. Yeah, roles shouldn't be changing a whole lot. However, I think when you have these test IDs, it just is a really clear signal that that is there for testing, so don't move it.
JASON: Okay. So, if I want to import the tab event, what do I do from Testing Library? Do I have to import something from the user event?
MARCY: Yes, import user event from�@testinglibrary/userevent. It's on their documentation. It shows implement user without curly braces.
JASON: Like that?
MARCY: Yes. Exactly.
JASON: Okay. And so now that I have user event, I have my main nav toggle, and what I wanna do is tab from here.
MARCY: Yes. You could say userevent.tab. And we actually get a nice assertion of we can expect the nav link to have focus. Once we have and that would be on a new line. So, the userevent.tab.
JASON: Oh, I get it. Okay, so then we would expect, and we're already doing that part, so we'll just take out this. That part should all work then. So this should fail. Let's make sure to take out the visible part so it does what we expect.
MARCY: That assumes well, we need to make sure that we're starting from the right place. So, user event.
JASON: Links are keyboard navigable. Cannot read property focus of null. Main nav toggle. Did I screw this up?
MARCY: Oh, on line 24, maybe, the main nav toggle.
JASON: That's this bit here. I might have okay, I screwed this up. However, it's finding it despite the fact that we are not opening
MARCY: Hmm. Main nav toggle.focus. Yeah, so, we're sending a tab event, so we're not actually toggling the thing.
JASON: Right.
MARCY: Yeah. Hmm. Our inline CSS is still in place, so it should be a timing issue on this one.
JASON: So this is like it the not inheriting the visibility properly. So, maybe we can display none.
MARCY: Oh, yeah, try it.
JASON: Display block and display none.
MARCY: Yeah, that may be an issue with the testing tool and visibility. Let's see, is it gonna fail? Yeah.
JASON: Received element with focus.
MARCY: Ah, okay. That worked.
JASON: That's perfect. That did what we want, so now let's add the click part, and this should solve that issue.
MARCY: Yes.
JASON: Testdriven development duh duh duh duh duh duh duh duh duh duh (Laughter)
MARCY: I'm so glad that worked.
JASON: I'm also very happy that that worked. This is exactly what we wanted, right?
MARCY: Yeah.
JASON: So we were able to kind of go in
Aha, behold! My bucket!
JASON: With a little bit of finagling, it looks we need to follow up with Testing Library not behaving the way it's supposed to. That's fine. Bugs are bugs. We can work through those. Once we're able to figure out this display block issue, we're able to say, okay, tool, when it's hidden, go to the button, tab from the button, and you should be able to see the thing. And that's what we want. When I go here and I tab around, we get to the buttons. We go from button to Learn React. If I hit space bar and activate with that, my next tab goes to this home link which is our nav link.
MARCY: Yes.
JASON: So, our test now reflects actual user behavior, hitting buttons and trying things.
MARCY: Yeah.
JASON: That feels right. Because now if I go and change something and it breaks this, my test will fail and tell me, hey, somebody's supposed to be able to tab to this button and to this button and you're not doing that anymore.
MARCY: Yeah, and I see this so on, you know, on big websites all over the internet. There are layers like the mega menus where it just was never tested with a keyboard, so you end up getting stuck in all this hidden content. These types of tests are really great because you can automate this stuff and then you can leave effort and energy and time for things that you can't automate that are more nuanced and require humans to go and check. But then you can at least sleep better at night knowing you've at least tested this part. Two things I would say, you all kind of saw us have to get into the nitty gritty of testing tools and figure out what works best. I would echo the comment in the chat about potentially using Cypress instead. It seems a little bit more robust. Anything that relies on JS Dom is a bit trickier. You find edge cases with styling. We just installed and used, it says JS Dom doesn't support tabbing. In order to enable tab from the enduser's perspective. However, this limit means components like focus trap React will not work. So, all of that to say, yeah, you might want to use Cypress for this just so that you're not chasing all of these edge cases all the time.
JASON: Yeah. And, like, this here is like a, you know, we've got the ability in tab. Like Cypress does have support for tab.
MARCY: Yep.
JASON: Or we do or we don't. Is it in here.
MARCY: Well, there are other ways around it. You can send key events. You can kind of construct the tab event. You might not have that really slick�.tab function, but there are ways to do it. Other ways, you know? Send a key event or something.
JASON: Yeah.
MARCY: But in terms of, like, visibility and CSS bugs and stuff like that, having it render in a real browser can remove some headaches.
JASON: For sure. Well, I mean, I know that you've got a hard stop at 11:30, so I want to make sure we get you out of here on time. With that, I think we can call this one done. What I am going to do, since we didn't get a chance to clean up the form. I'm going to take the form that is definitely not accessible out of the source code so that nobody gets any ideas from that bad code. So, what we'll do is put this up online. Marcy, thank you so much. Where should someone go if they want to take next steps? I'm gonna start that by giving everyone another link to testingaccessibility.com. Where else?
MARCY: That is definitely a place. There is the email course that you can take right now, and then my new workshop stuff will be out soon. Soonish. Kind of working on that. Yeah, different formats on various things. You can follow me on Twitter. I tend to post mostly about web development and accessibility with the occasional bike or motorcycle or van thing. Watch my follower count drop when I tweet about anything other than accessibility. But, hey, we're hopeful humans, right?
JASON: That's right. Well, perfect.
MARCY: Yeah.
JASON: Okay. With that, y'all, thank you so much for hanging out. Marcy, thank you so much for hanging out. As always, this episode has been live captioned. We've had Jordan with us all day from White Coat Captioning making sure the show stays accessible to more people, made possible by our sponsors Netlify, fauna, Auth0 and Hasura making it more accessible to more people. While you're on the site, look at the schedule. I have a million things I haven't posted yet. Oh, boy, look at my nav immediately showing how broken it is. You can add the show on Google Calendar to make sure you see upcoming episodes. A lot of good stuff coming. Thursday, I'm going to do a solo episode. Tune in for that. We'll figure out what the topic will be. We'll do that. People like Tomasz coming on, Ben Myers. I have a whole bunch in my inbox I haven't added to the schedule yet. Please go add on Google Calendar and that will get you what's coming up so you never miss an episode. Okay. All right. I think that's everything. Chat, thank you so much for hanging out, as always. Marcy, thank you one more time.
MARCY: Thank you, Mr. VP. How do you do it all? Congratulations.
JASON: I have no idea. All right. Thanks, y'all. We're going to go find somebody to raid, so stay tuned. We will see you next time.
MARCY: See you later, everyone. Have a good day.