-
Notifications
You must be signed in to change notification settings - Fork 197
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
Add Switch to Shadow DOM command #1320
Conversation
This allows the ability to move between a Shadow DOM context and the document context. If there is no Shadow DOM to switch to an error No Such Shadow DOM is returned.
return <a>error</a> with <a>error code</a> <a>no such shadow dom</a>. | ||
|
||
<li><p>Set the <a>current browsing context</a> to <var>element</var>’s | ||
<a><code>shadowRoot</code></a>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the shadowRoot
type? What if it is closed/open?
@@ -1325,6 +1326,12 @@ <h3>List of Endpoints</h3> | |||
<td><a>Switch To Parent Frame</a></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>POST | |||
<td>/session/{<var>session id</var>}/shadow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs to be on the element
</tr> | ||
<tr> | ||
<td>POST</td> | ||
<td>/session/{<var>session id</var>}/shadow</td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be on a web element namespace.
<li><p>Run the substeps of the first matching condition: | ||
|
||
<dl class=switch> | ||
<dt><var>id</var> is <a>null</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The id
will always be defined if it’s a web element.
The switching API for Shadow DOM is really suboptimal and adds a lot of unnecessary overhead to testing Web Components. A ShadowRoot is not an iframe, nor even like an iframe, and it shouldn't have a similar API. Please see my objections in #5869: SeleniumHQ/selenium#5869 (comment) |
So far I think @justinfagnani has a good point; I'm curious what your response would be, @andreastt and @AutomatedTester. |
This was briefly discussed in the working group meeting today. I think there was some agreement that this might not be the best API approach, but some thought is needed about how interactability checks should work with shadow trees. |
I am curious how easy it is for browser vendors to find an element within a shadow DOM. In the CDP I don't find any method like
The question is also whether or not we need to switch context in order to execute an action on an shadow DOM element. This can also add a lot of work on the client libraries having to flag elementIds as shadow elements or non shadow elements and having to perform a context switch before using that element id. TLDR: depending on how easy it is for browser vendors to find a shadow dom and execute an action on it we should either abstract it away or have the WebDriver bindings have to implement an abstraction on top of it. |
Looking inside shadow doms should be an explicit action because it's breaking encapsulation. It should be quite acceptable to treat a |
How about enhancing existing commands, e.g.
This could allow the driver to differentiate between both contexts and element types without putting more complexity to the binding implementations. If an action is then called on a |
Treating web elements inside a shadow DOM the same as any other web
element in the document makes a great deal of sense, thanks to
@jgraham for this idea. Scoping element retrieval commands to act
on a shadow root solves the problem of overreaching global state
that is both hard to define, maintain, as well as understand.
The assumption of this PR was that introspecting a shadow DOM would
behave like switching frames, where you need to set up a certain
amount of state before you can interact with the web element, and
then clean up the same state to interact with a web element outside
the shadow DOM.
That would require an awful amount of context managing, and because
shadow DOM elements essentially belong to the same document it’s
not clear we need the extra complexity of statefully changing the
“interaction mode” as we do for browsing contexts.
|
Note that in the proposal there is no session-global state associated with shadow DOMs. The change is that for elements that represent a shadow root, there are two associated That said, I could get behind adding parameters to the existing endpoints rather than adding new endpoints. One deciding factor there could be how the fallback works in existing implementations. In the case where there's a separate endpoint to get the shadow root then old implementations will fail explicitly. In the case that there's a parameter, it will be ignored by old implementations and they will silently have incorrect behaviour. |
thanks for clarifying @jgraham @andreastt
Are there already existing implementations for that endpoint? I was under the assumption that there aren't any. A brief research resulted that many implementations are allowing actions in the shadow dom by using the |
I meant the |
Yes, which is why the default is set to |
The default doesn't matter. The question is what happens in an existing implementation in the case that a user specifically requests looking at the shadow dom. With a new parameter, that parameter is ignored and we return the wrong result. With a new endpoint, that endpoint returns a |
The one reason why this can't be on The other reason for doing this as an explicit switch is that all interaction commands need to know the context of where it is executing. For example: <html>
<my-list>
<my-button>
<fancy-list-that-is-data-driven>
</my-button>
</my-list> If we have a mechanism that allows us to traverse down to In Web API terms if we do |
That doesn't matter; the proposed API doesn't depend on the ability to do anything other than select a shadow host from css (which is necessarily possible since it's just a normal element) and get a reference to its associated shadow root (which is possible via content APIs for the case of an open shadow root and must be possible from browser-internal APIs for a closed shadow root since that's required for the page to actually function).
Interaction APIs will presumably start from the element's nearest shadow root for the purposes of click. So in your example I would have to write code like:
(in practice you would chain the calls rather than making lots of intermediates at least in languages that support that style, so I don't think the programmer burden of this is too high). Note that this is basically exactly the same as you could do today using script APIs to access the contents of open shadow hosts:
|
Are there already existing implementations for that endpoint? I was
under the assumption that there aren't any.
For the sake of complete transparency there is some prior art in
Marionette, but I don’t think it should govern the direction of
this API discussion:
https://searchfox.org/mozilla-central/rev/8848b9741fc4ee4e9bc3ae83ea0fc048da39979f/testing/marionette/driver.js#2608-2630
|
This could be handled similar to if no element was found.
I am not sure how to interpret this. I see that we are aligned to some web APIs (e.g. querySelector -> findElement or querySelectorAll -> findElements) but in many cases we already do our own "thing". Aligning to existing standards is definitely good but if that means it would add unnecessary complexity I would avoid it.
I think this can be easily solved when we say that every |
I'm super strongly +💯 on this, to the extent I'll probably object to doing anything else.
To me it makes more sense to have I also think the harder part is defining element interactibility (given a |
I want to point out that in the standards groups the assumption has been that testing frameworks will provide a means to pierce ShadowRoots in searches, which is why it was ok to remove the shadow-piercing selectors like For open ShadowRoots, the encapsulation isn't intended to be strong enough to disallow code that knows that it's doing from reaching in. It's possible, and definitely not discouraged for testing, to write a |
For reference CDP seems to do something more like "give me the children of this node, including any shadow children", which does make sense for a debugger, but doesn't seem to map well to WebDriver since WebDriver only has selection by (various kinds of) selector not direct DOM traversal. |
I guess my suggestion is entirely redundant, anyway, given Given @justinfagnani said the Web Platform WG expected testing frameworks to provide a means to pierce shadow roots in searches, it would seemingly imply we either need to alter the semantics of CSS/XPath selectors or invent a new API to do something else? |
One option is to just implement |
To be clear, if |
That's closed ShadowRoots. The vast majority are open. |
Having test frameworks use useland shadow-piercing selector libraries was discussed at TPAC 2017, and several other times in in-person conversations:
|
The point is the piercing would break encapsulation. |
What is the desired outcome of |
The behaviour in relation to Get Element Text is somewhat undefined. However the browser implements shadow DOM, the expected outcome should be whatever running Get Element Text is horribly underdefined because we couldn’t reach agreement on what constituted visible text. |
Even so I if I have: const fragment = '<div>any html fragment</div>';
document.getElementById('test1').innerHTML = fragment;
document.getElementById('test2').attachShadow({mode:'open'}).innerHTML = fragment; I think |
Neither |
They do not. I think In reality I'm unable to get rendered text from within a shadow tree from any browser, only chromedriver ele.attachShadow({mode: 'open'}).innerHTML = '<style>div{display:none}</style><div>test1</div>test2'
console.log(Array.from(ele.shadowRoot.childNodes).map(e => e.innerText || e.wholeText).join(''));
console.log(ele.shadowRoot.textContent); I'm not sure what the correct answer is to how |
I think the behaviour of get element text should be a separate issue. This issue should be about how to access elements in the shadow tree, and the other issue about how to access text under the shadow tree. Depending on the constraints we find, the solutions may be unrelated (i.e. if it's possible to update Get Element Text to at least optionally return the shadow tree's text, that won't depend at all on the ability to access elements in the shadow tree). |
Filed #1350 for the Get Element Text issue. |
I have raised WICG/webcomponents#771 |
@AutomatedTester - what's the status on this? |
I need to pick this up again. I will look at it next week.
David
<http://www.theautomatedtester.co.uk/>
…On Thu, Jan 10, 2019 at 5:46 PM Luke Bjerring ***@***.***> wrote:
@AutomatedTester <https://github.com/AutomatedTester> - what's the status
on this?
Ran into this issue myself testing wpt.fyi, which I worked around using
execute script of arguments[0].shadowRoot.querySelector('foo') to fetch
foo from a web-component element.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1320 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAH2BpVLQ8C0QJw-gNwT-_xBiyYi4jRTks5vB3x0gaJpZM4XyctG>
.
|
I'm not sure this is the best place for this, but here goes anyway. I'm using webdriverio and have added this simple custom command: browser.addCommand('getShadowRoot', function(el) {
return browser.execute(el => el.shadowRoot ? el.shadowRoot : el, el.value);
}); Usage is sort of clunky: get myButton() {
browser.getShadowRoot(browser.element('my-container')).element('my-button');
} but I think it could be much nicer, if in webdriverio it were a getter function on the // get the custom element
get myElement() {
return browser.element('my-element');
}
// query inside it's shadowRoot
get myButton() {
return this.myElement.shadowRoot.element('my-button');
} The last example basically lines up with how things work inside the browser: document.querySelector('my-element').shadowRoot.querySelector('my-button'); edit: reread the thread. looks like @gsnedders suggested something very similar already. I still really like the idea of explicitly getting the shadowRoot (which my command does NOT do, it returns the element if it can't find a shadowRoot). |
This comment has been minimized.
This comment has been minimized.
Is there any update here?Who can push this pr? |
This comment has been minimized.
This comment has been minimized.
Any updates for us on the status of this PR @AutomatedTester, @shs96c, or @jgraham? It's been awhile since this PR started and it would be nice to know what the path forward is. I feel that this is a very important issue that needs to be addressed in order for developers to truly adopt and embrace Shadow DOM seriously. Shadow DOM enabled web components are one most exciting and powerful features of the modern web, but sadly if developers cannot properly or easily write tests for them without going through kludgy or complex workarounds then their adoption will be crippled since the cons will outweigh the pros in many cases. More on this here. |
There was an offer from Salesforce to tackle this. This is really not something the WebDriver spec should be tackling as it should have been handled by the DOM spec and all the work around web components. We are trying to rectify the issue now. |
Closing this for now. This feature will be added but hopefully Salesforce will do it soon |
Thanks so much for the update @AutomatedTester!
It's great to hear this is being actively worked on! How can I track the progress of this DOM/web components work and the aforementioned Salesforce team work? Are there relevant issues/PRs that we can reference? |
Plugging some updates here. We do have a merged PR for Supporting Shadow DOM, and respective WPT support. Thanks @jimevans! It seems that we still need browser implementations to catch up with the changes. @letsgotomars I believe the next step is looking at how we can help browser vendors now the tests have landed. |
This allows the ability to move between a Shadow DOM context and the
document context.
If there is no Shadow DOM to switch to an error
No Such Shadow DOM is returned.