-
Notifications
You must be signed in to change notification settings - Fork 690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
review options for accessibility linting (versus documentation) #6314
Comments
Machine TestingFollowing the conversation in #6725, I took a look at pa11y/pa11y-ci and how it could be used for testing in this project. It turns out that pa11y is a wrapper around puppeteer (to manage the browser instance) and HTML CodeSniffer (to run tests on the page received by the browser) which provides some benefits over using them directly:
Unfortunately, pa11y is hardcoded to Chrome. It might be possible to convert it to firefox (see additional notes below); however, even in this case, it seems like using pa11y to manage puppeteer to manage a separate firefox instance would add complexity to the test module, with both pa11y and the existing selenium wrappers implementing similar functionality. HTML CodeSniffer is a client-side script, injecting it using selenium would result in a less complex system overall. On the other hand, HTML CodeSniffer does not have a built-in method for reporting results (it just saves them in memory), so reporting would need to be handled separately. Reporting seems simlpe, because all we would need to do is save the results into a cookie, and I see at least one example of cookie-reading already in the test suite. The code is minimal and readable. Example json output of a pa11y run on the source login page> pa11y http://127.0.0.1:8080 --reporter json
[{
"code": "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail",
"type": "error",
"typeCode": 1,
"message": "This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5: 1, but text in this element has a contrast ratio of 2.65: 1. Recommendation: change text colour to #747394.",
"context": "<p id=\"footer-fpf\">\n SecureDrop is a project of...</p>",
"selector": "#footer-fpf",
"runner": "htmlcs",
"runnerExtras": {}
}] pa11y being hardcoded to Chromepa11y uses puppeteer; puppeteer does support firefox, as mentioned in their documentation. It might be relatively straightforward to tell pa11y to use firefox, but it's not immediately obvious to me how to do so. pa11y does forward launch options to puppeteer without any processing: https://github.com/pa11y/pa11y-ci/blob/master/lib/pa11y-ci.js#L39 // This function does all the setup and actually runs Pa11y
// against the passed in URLs. It accepts options in the form
// of an object and returns a Promise
function pa11yCi(urls, options) {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async resolve => {
// Create a test browser to assign to tests
let testBrowser;
// Issue #128: on specific URLs, Chrome will sometimes fail to load
// the page, or crash during or after loading. This attempts to
// relaunch the browser just once before bailing out, in case Chrome
// crashed at startup. This is just an attempt at mitigating it,
// it won't fix #128 completely or even at all
try {
testBrowser = await puppeteer.launch(
options.chromeLaunchConfig
);
} catch (error) {
testBrowser = await puppeteer.launch(
options.chromeLaunchConfig
);
} So I tried the most obvious thing and added {
"defaults": {
"chromeLaunchConfig": {
"product": "firefox"
}
}
} It wasn't clear how to verify whether firefox was used, so I just
I do not know that this is a precise or reliable way of checking the engine being used, but it seems like a reasonable approximation. Considering the reasons listed above for using htmlcs directly, and my ignorance about whether anybody else has looked into this particular issue already, I have not yet looked into it further. Human ReviewI have also put some thought into management of the requirements that need human review, although my ability to weigh the options here is limited because of my unfamiliarity with project resources & management. I have 2 initial thoughts on this though. Periodically review entire websiteWe could have an issue template that has a checklist of all of the items that require human review and create it automatically. This might happen based on the passage of time (for example, once per quarter) or based on release schedules (for example, requiring this review before a major release). This option makes it easier to control the amount of resources the project uses on this review, but might leave gaps where accessibility issues are unnoticed. Require accessibility review whenever a relevant file changesWe could also require the accessibility checklist to be filled out each time there are changes to html or css. This makes sure that there will be no gaps, but could cause a significant drain on resources. In the most absurd situation, we could end up telling people to re-verify that images have alt text when all they're doing is clarifying a sentence in a paragraph. I could argue that this should be trivial to confirm, because the author knows that they haven't added any images, but this kind of heavy-handed bureaucracy is likely to frustrate contributors and make it less likely that they will pay attention to accessibility issues that are actually relevant to their change. |
I sketched out what the 2 different methods (pa11y as a subprocess vs html codesniffer/htmlcs injection) would look like with some code that does the bare minimum to reproduce the error message from the manual pa11y run in the test suite. The code is extremely hacky, but gives a good idea of what the major immediate challenges for each approach are. Output from Using pa11yThe 2 things that stand out to me here are installing pa11y in the container and using firefox (or tor if possible) instead of chrome. I am currently handling the former by running The latter is trickier. There is an option in pa11y to pass in a pre-constructed browser instance, so theoretically we should be able to just have a small wrapper script and use pa11y as a library (the htmlcs version also has a small wrapper script to run the sniffs). I don't see any indication that puppeteer can use TOR Browser specifically, but I see that some tests currently in the suite are using the Firefox driver. Not sure what the criteria for that is. Using HTML CodeSniffer (htmlcs)The thing that stands out to me here is managing the htmlcs build. This scratch test just tosses the built javascript into the repo, but I think it would be ideal to place this in the docker image, similar to the assessment of pa11y above. Human ReviewOne more note on this topic: it looks like the notice level in htmlcs lists at least some (possibly all) of the items that require human review, so we could leverage this instead of manually maintaining the list of items. |
Exciting results, @saffronsnail! Since Tor Browser mostly inherits Firefox's accessibility properties—and since the Source Interface is JavaScript-free to encourage the use of Tor Browser's strict mode, which otherwise modifies those properties—I think using the Firefox driver where necessary should be both adequate and already a dramatic improvement over not having this linting at all! Note that, like #6072, we'll probably want these findings to be informational (non-failing) in CI to begin with—until we're confident enough in the tool's findings, and our ability to address them, to make them a hard requirement on subsequent pull requests. |
Makes sense, it looks like I can make sure that the accessibility tests aren't immediately fatal by adding
Regarding the browser discussion, it sounds like you're leaning towards using pa11y? I can definitely implement it that way, I'm just a little surprised because the HTML CodeSniffer version works with the |
Here's what I did today:
The You can view a diff of this version here. Is posting a diff sufficient or should I open a new pull request at this point? |
So, it turns out that using pa11y is more work than I expected. While pa11y lets me use actions to navigate through the page, creating everything to crawl through all the pages would be non-trivial, and it looks like the app navigators have most if not all of this implemented already. I'm switching back to HTML CodeSniffer for now, let me know if there's an issue with that (as a reminder, this is the underlying tool that pa11y uses to check for accessibility issues, so it will give us the same results, just the mechanics of processing it is different). The base of the change seems to be in a solid place right now. All that's really left to do is create the code that crawls through the different pages to make sure everything is tested. Fingers crossed I'll have something submittable by next Monday. You can view the current diff here. |
I think I have all of the source pages tested. Went a little faster than I expected, the journalist interface looks more complicated though. I haven't done a comprehensive review of the error messages, but all the ones I've seen have had to do with insufficient contrast. I expect the number of changes should be much smaller than the number of errors, for example all of the blue buttons have a contrast error, and I assume that the "blue button background color" is stored in one place, so adjusting that will fix it everywhere. I have a few outstanding questions, if you have the chance to look at them now great, if not then I'll include them in the body of the pull request when the commit is in a good state. Here is the current diff.
|
I have a decent chunk of journalist tests done. They're a little flaky because sometimes the page doesn't load before Also, since this is getting to be a pretty hefty change, I split it up into a few different diffs:
Outstanding questions unchanged from previous comment. |
Tests for the admin interface are in place. I still need to review the diffs to make sure everything is organized correctly, add docstrings, and check that the test times are reasonable. Diffs:
|
This looks like terrific work, @saffronsnail. Thank you for approaching it so rigorously! I've answered your recent questions inline (below).
We use pull requests to review all code changes, so please do open a pull request against this repository. Feel free to assign the review to me.
Thanks for flagging this. Can you clarify why you say that the user@sd-dev:~$ curl -s https://registry.npmjs.org/html_codesniffer | jq '.versions["2.5.1"].dist'
{
"integrity": "sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==",
"shasum": "d76d124b8f5cd0e58b3c1b142fd095a40573ea28",
"tarball": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.5.1.tgz",
"fileCount": 136,
"unpackedSize": 1271493,
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelPYMCRA9TVsSAnZWagAAfOAP/j0GG0g+7bEMvAjp/asy\nlHpqDNMJtVmvl4kXF3t6cWdq70ZpKpLD+xpuqbZH8D/iF5DtlTJ0Ekfsopr8\njKwb5zIf8HWg8qwSvwnFJdxkNy6rhWR4Ph4o0twHnPWeaLw5GkiW2iZAmigi\nMAA2OOS041FoVXC84eE+p5mGaYYiM1eSf4i9ikmOm/GBKExHrDjGPEP6idUo\nRoKE8dTKHS6GsnXGuoHvEX1NW0DR1WTuPn/BleYnqR1Yx+WbLaxWqaiZU9xr\n82d7Xpoqki7BPAS+z9KnZ5Z/3sc1pRMW8MVtRlwzi6s7JwKjOSKuEFFi5XNL\nSP71yr08J3tLr5J4twI4DgUhT0y9LuxUsei+6o4cc9DL2knaVpW7IdS5QppS\nP7NnyZ4KWTtTVvz1x2slpPNYogfBHQFLVOCflpIj1dB1fGNaDus9zusfgCPQ\nV17suyuu3+OI/+Mnrfm1l/bZaUQ7xvJ3syH1OoDZyzr8cspmN6fxcCANLipw\nCTwkhTG7yLrLc+3955Y+W9D01HDdnYsVymZZdQhwVDlYe2KOuSDTUYQrBSgj\n+rFZiql1M5xDZrRJC2Aq97GtqrR36k/R4t9GN3GzBWFM/DZU3bIFCYDCFgH8\nz+2NmmGFTaz4rkBsYHmsla0PoBCKE3C1CNDE6o4cD3SzQ+wvcDMFrnI9aTMk\n1Fp/\r\n=6T1P\r\n-----END PGP SIGNATURE-----\r\n",
"signatures": [
{
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
"sig": "MEYCIQDCW/oPd0XThYnTS+76sK72UB3q9uEEYGTH4rNQonkWLQIhAKxqe8D9bWdnetw7p9pIOWtcJPYBVkELB369grEGOO14"
}
]
} In any event, I'll make sure to flag this to our security engineers during review, since this change involves adding a new toolchain, not just pulling in an new dependency.
There's no canonical list of views, states, or conditions under test, and it seems like this is the main disadvantage of establishing a separate accessibility test suite: it's not just tacking on the accessibility evaluator to each of the existing functional tests. If that's not possible—e.g., by something like subclassing (My thinking with the above suggestion is that it would be better for long-term maintenance to get a good-enough first pass of accessibility validation "for free", whenever someone adds a new functional test, than to make authors of view-level changes also responsible for accessibility as well as unit-level and functional tests. This is in the spirit of linting—it's automatic, comprehensive, and intended above all to prevent trivial regressions—more than full functional testing, and I recognize that it may not be doable in this approach or with the tools available.)
Yes, stateless and stateful changes, respectively, per #6382: securedrop/securedrop/tests/functional/conftest.py Lines 200 to 203 in afe4a8b
|
@cfm Thanks for the info! I think most of the changes in the first diff are applicable to the more minimal approach you're looking for, I'll open a pull request once I have something that is less intrusive. I wasn't sure if it made sense to open a pull request as soon as I had an interesting diff or if it was better to wait until it was ready to go, it sounds like the former.
It looks like I misread the documentation, the "third party registry" context was pretty important there.
It looks like the pagelayout tests you mentioned earlier would be a good place to "sneak this in" since it's going through, at a minimum, some reasonable subset of existing pages. What would you think about adding a call to |
On Wed, Feb 01, 2023 at 08:34:58AM -0800, Skyler Ferris wrote:
@cfm Thanks for the info! I think most of the changes in the first
diff are applicable to the more minimal approach you're looking for,
I'll open a pull request once I have something that is less intrusive.
I wasn't sure if it made sense to open a pull request as soon as I had
an interesting diff or if it was better to wait until it was ready to
go, it sounds like the former.
Either way! You can always leave it marked as draft to make clear that
you're seeking feedback on work still in progress. :-)
It looks like the pagelayout tests you mentioned earlier would be a
good place to "sneak this in" since it's going through, at a minimum,
some reasonable subset of existing pages. What would you think about
adding a call to `sniff_accessibility_issues` to these functions,
immediately after they call `save_screenshot_and_html`? This seems
particularly convenient because these tests are already non-fatal, and
the the accessibility sniffs seem similar in spirit in checking the
page rendering of different languages (making sure that the pages
"look ok" for users with different backgrounds).
That sounds like a great approach.
|
Require WCAG compliance along with other linting enforced automatically in CI. Here's an overview of how to do so and the W3C's list of such tools, of which Pa11y and AccessLint look especially promising.
Originally posted by @cfm in #5743 (comment)
The text was updated successfully, but these errors were encountered: