[whatwg/dom] Closed Shadow DOM blocks accessibility testing (Issue #1290)

### 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 `iframe`s 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.

2. 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.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/1290
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/dom/issues/1290@github.com>

Received on Tuesday, 28 May 2024 23:02:51 UTC