Skip to content

Closed Shadow DOM blocks accessibility testing #1290

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

Closed
tgrushka opened this issue May 28, 2024 · 1 comment
Closed

Closed Shadow DOM blocks accessibility testing #1290

tgrushka opened this issue May 28, 2024 · 1 comment
Labels
accessibility Affects accessibility topic: shadow Relates to shadow trees (as defined in DOM)

Comments

@tgrushka
Copy link

What is the issue with the DOM Standard?

As a user and a developer / accessibility engineer who is legally blind, I ask for your consideration of a major barrier for both users and developers / testers in terms of accessibility that has not been given much voice in the Shadow DOM discussions, but its urgency is increasing.

The problem

I understand Shadow DOM and the usefulness of encapsulation of components. What I do not fully understand is the need to have closed Shadow DOM (specifically, shadowrootmode="closed") and the lack of any mechanism to even see (via JavaScript) the presence of closed declarative shadow roots in the page at all -- or whether that is even a WhatWG / W3C standard, or just a Google / Chrome team decision.

Nonetheless, the shadow root is now ubiquitous (and closed mode even misused by developers thinking it is a security measure), and its usage, particularly declarative with server-side rendering (SSR), is only increasing.

Many developers believe the web is becoming more accessible. However, it is actually becoming less-so, partly due to the complexity of testing with features such as Shadow DOM, iframes, etc. that have been introduced since the 90s. While these features may make life easier for developers, they make end-to-end accessibility testing much more difficult because of all the different and convoluted workarounds, such as:

  • test engine code must be injected into every iframe, and cross-frame communication managed;
    • every test engine must then account for being run in an iframe and somehow "understand" its document context across that barrier;
    • yeah, I know, different issue, but you see what I mean -- one could argue that iframes and shadow DOMs are functionally similar in that they isolate components -- on a different vs. the same URL -- but in terms of accessibility testing, both cases must be handled individually, doubling the complexity;
  • it was unanimously (why?) decided (c. 2015?) that shadow root-penetrating CSS selectors will no longer work -- even though accessibility testing was raised as a concern at that meeting, so getting selectors that will work across these barriers to identify violations within shadow roots (without JavaScript) is impossible;
    • while that helps developers with encapsulation, it complicates accessibility testing;
    • they could have allowed the root-crossing selector to identify an element, but not allow it to modify its style -- but that ship has sailed;
  • and now the declarative shadow DOM support for server-side rendering (SSR) of <template shadowrootmode="closed"> components makes these components impossible to test without intercepting web requests and using regular expressions to rewrite the HTML body to make them open...
    • even a MutationObserver on the window/document doesn't work, because the HTML of these closed roots is removed before the DOM is even ready (try document.outerHTML);
    • the closed roots are available in the results of the call to the Chrome DevTools Protocol method: dom.GetDocument;
    • however, there is no way to modify these nodes via CDP that modifies their shadow root type to be open so that accessibility testing engines can see into them;
  • Overriding Element.attachShadow is really an inelegant and brittle monkey patch that really should not be encouraged, but unfortunately is the only solution for imperatively-created closed shadow roots that has evolved from not having a solution to this problem.

Some may ask the question: why do accessibility testing tools even need to test "closed" components, since these components should have already been tested by the developer? I argue that the answer is in the question, and further, that e2e tests are equally important to the unit tests of the components.

Proposed solutions

Please, if at all possible, give developers a way to override closed shadow DOM hosts to be open. I noticed this was done for Chrome Extensions. But there should be a way, since it is a DOM standard, to override these for testing. I can hear some developers screaming that they don't want their closed components being messed with; however, this is not sensible from an accessibility standpoint, and the priority should be on the user who needs the accessibility, then on the developer/author who authored the page and wants to make their page accessible, and then finally on the developers of frameworks and components.

I can just envision tons of closed shadow DOM components coming out into web frameworks in the near future, because that's the "easy way out" in terms of making a component work "anywhere," and when has just trusting developers to "do the right thing" without giving users, authors, and testers a way to override these behaviors actually worked?

I argue that:

  1. The author of a page should be able to disable closed shadow DOM on the page, because the author of the page takes priority over the author of a component on that page (especially if that component is part of a UI framework built by a 3rd party). This should not present a merit problem since the standard explicitly states that Shadow DOM is not for security.
  • Making closed shadow roots "read only" might be half-way acceptable, but (accessibility) and other testing often requires components to be manipulated via scripts, but of course human interactions could be simulated as long as the results could be read from the component. This would make these components more difficult to test, but at least possible to test without HTTP request interception.
  1. At minimum, browser automation tools should be able to set a flag, issue a command, etc. to disable closed shadow roots and make the browser treat them as open. But this would be up to each browser vendor, again presenting testers with a huge dependence on each browser to allow such a workaround.

I hope the first option could be both declarative and imperative, again such that request interception would not be required to run tests on a page with closed shadow roots.

My first choice would be removal of closed shadow roots from the standard (if they are even part of the standard), or at least the standard stating that all shadow roots are open. If developers try to understand accessibility better, and the importance of testing, I don't see how this would be so controversial, especially since interfering with a Shadow DOM tree requires a deliberate effort and can't seem to happen accidentally anyway.

My second choice would be overriding the closed state of the shadow root deliberately by 1. above, possibly as a meta tag, body or window property, that could be set both declaratively and imperatively.

My third choice would be to make closed shadow roots "read only", such that JavaScript could not modify properties inside them (aside from user extensions), but again, I'm not foreseeing all the testing challenges this might present (not to mention user CSS, which I use all the time), so hope everyone doesn't jump on this solution first.

Conclusion

In conclusion, the problem is that closed shadow roots are near impossible to test as part of end-to-end (e2e) testing for accessibility:

  • declarative closed shadow roots are impossible to test without HTTP interception and body modification;
  • imperative closed shadow roots are very difficult to test without overriding Element.attachShadow, which really should be discouraged.
    I propose a solution of:
  • removing closed from the Shadow DOM standard, or preferably standardizing that all Shadow DOMs must be open;
  • providing a mechanism for page authors/developers and testers to override and disable closed shadow DOMs for a page, or a mechanism in browser testing APIs to disable closed shadow roots;
  • making closed shadow roots able to be open as read-only, although not ideal.

Thank you for your consideration.

@annevk
Copy link
Member

annevk commented May 29, 2024

This was an issue for a while, but w3c/webdriver#350 has been resolved and WebDriver is the recommended way to do such automated testing. E.g., https://w3c.github.io/webdriver/#get-element-shadow-root.

If you're interested in reading more about the rationale behind closed shadow roots I wrote up https://annevankesteren.nl/2019/10/encapsulation-theory a while back summarizing some of the discussion on that front.

@annevk annevk closed this as not planned Won't fix, can't repro, duplicate, stale May 29, 2024
@annevk annevk added topic: shadow Relates to shadow trees (as defined in DOM) accessibility Affects accessibility labels May 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accessibility Affects accessibility topic: shadow Relates to shadow trees (as defined in DOM)
Development

No branches or pull requests

2 participants