-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Shadow DOM traversal support #5869
Comments
also, while i do disagree with us implementing some kind of "shortcut", something like this could work: element
.FindElement(
By.ShadowSelector(
By.CssSelector("foo"),
By.CssSelector("bar")
)
); which is the equivalent of i can imagine there are plenty of people who want a "lazy" way to do whats in my original post, without the need for null checking and what not. Basically a single either way i think we still need to implement |
Even though I don't fully follow the request, I see nothing in regards to shadow root in specification. To my knowledge, support for custom commands like |
The request is to provide shadow DOM support. To provide a way of using Currently, you do not have any support for shadow DOM at all in regards to traversing the tree. So if we can't add |
Originally we had been discussing this mostly in the same approach as frames so you would do. shadow_root = driver.find_element(...)
driver.switch_to_shadow_root(shadow_root)
driver.find_element(....).click() This is how I have recently been implementing in Firefox as Firefox's shadow DOM becomes live. Then if you wanted to traverse back up the tree you would do shadow_root = driver.find_element(...)
driver.switch_to_shadow_root(shadow_root)
driver.find_element(....).click()
# Traverse back to the main tree
driver.switch_to_shadow_root(None) |
A solution like that makes sense to me too, its a very similar way of tackling it to my original idea ( Though I do think there should be a way of accessing a root relative to an element... Just like you can do You don't always have the original driver instance which created the element you are being passed, so how do you reach a shadow root from only a Of course there are ways around that (refactor so you do have a ref to the driver), but it seems to me it would be quite nice to have access through the element, being that is what "owns" it. Right now many people have to resort to executing a script which returns |
@43081j I’ll just point out that in Java st least (and .NET), you do almost always have a reference to the parent driver. You can usually cast to |
@jimevans really didn't realise there was a reference to the driver there 🙈 in that case, its fair enough, having a though do remember, |
@43081j shadow root is a property of an element so passing in the element and then looking for the property makes sense to pass in the webelement. The think that gets tricky is when we hit the issue of the |
yup sounds good to me. as for closed shadow roots, i think it should just be accepted that you can't access it (throw an exception). reason being, so if we call |
Yes, we need to throw an exception when |
a new exception would make more sense i think, seeing as its not an element really. its a document fragment i guess. so either an exception specific to shadow roots, or one a little more generic tied to documents ( i dont think we need to care about closed roots as we shouldn't be able to access them anyway. which makes the logic as simple as "is it null or not". |
If I understand correctly, we need to make it a part of spec (like frame switching), don't we? Or can we implement it purely in client bindings? |
Part of the spec. We originally punted this because Shadow DOM was chrome
only and the L0 version was crap and no other browser wanted to implement
it. Since that is ancient history and shadow dom is in most browsers (at
least in their nightly builds) we can move forward with what we have
discussed here. I am happy to write the spec prose
…On Tue, May 15, 2018 at 3:37 PM, Alex Rodionov ***@***.***> wrote:
If I understand correctly, we need to make it a part of spec (like frame
switching <https://w3c.github.io/webdriver/#switch-to-frame>), don't we?
Or can we implement it purely in client bindings?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#5869 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAH2Bogm-h_sKkV3NGqDqt-ue-5rwbuMks5tyuhDgaJpZM4T3Dip>
.
|
@AutomatedTester if you're happy to, could you get the ball rolling on this if you're happy to write the spec? would be great to get some movement on this |
I will do it, I am just waiting for the spec to reach spec on Thursday,
David Burns
Email: [email protected]
URL: http://www.theautomatedtester.co.uk/
…On Tue, May 29, 2018 at 7:35 PM, James Garbutt ***@***.***> wrote:
@AutomatedTester <https://github.com/AutomatedTester> if you're happy to,
could you get the ball rolling on this if you're happy to write the spec?
would be great to get some movement on this
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5869 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAH2BgduQpayjXWrVfXOPDO0xXbLclu3ks5t3ZTkgaJpZM4T3Dip>
.
|
is there any update on this? i do still question if the switching idea makes sense though, as it feels a little unnatural to be accessing an element's state/property in an indirect manner. its a shame we can't simply have cc @rictic and @justinfagnani |
I have been busy with other things but I have most of the spec written up locally. I am not sure what you mean by accessing it indirectly? To get an element state or property in a shadow DOM your proposal seems to suggest you want to do
Now if you want do multiple actions in the shadow DOM you now have to repeat constantly that you want to do The next problem is if you have 2 elements with the same ID, one in the main document and one in the shadow DOM and you forget to do the repetition of moving state you could start getting into false positives. The idea of switching helps us, and the client code, maintain a state that the code author thinks they are in and tries to remove a footgun. There is also the fun in knowing if it really is a |
This is just the DOM APIs, or really any API with nested objects, and there are plenty of other places where you might have a value that you need to dereference multiple time. Presumably you can deal with this like any other nested object and define a variable:
The repetition of
Switching seems really fraught to me. When is state restored? What if a test forgets to switch back, or if there's an exception? Will other new DOM APIs be put behind global switching state? Also, a ShadowRoot is simply a type of Node that's not included in |
So we're talking about the WebDriver API and not just DOM APIs. Not all DOM APIs map directly to webdriver because that wouldn't make sense. The idea is to conceptually treat the shadow DOM in the same way we treat frames. This would make it like driver.switch_to_shadow_root(element)
# switching a frame would be
driver.switch_to_frame(element) Yes we could make it something like shadow = element.shadow_root
shadow.find_element(....).send_keys("I like cheese") But that now causes
WedDriver authors are already used to the idea that they need to be conscious of their state in their tests if they had iframes. I don't see how this is different. The idea is if you you are in a shadow DOM to get back to the top document you would simply do driver.switch_to_shadow_root(None) which is equivalent frame switching would be driver.switch_to_frame(None) |
I think a huge difference between ShadowRoots and frames is the sheer pervasiveness and number of them. Apps are likely to have 100s to 1000s of ShadowRoots, basically every Custom Element will. And they're not nearly as special as iframes - they're in the same window and document, share the same globals, many style properties inherit through them, some events bubble up past them, light-DOM children are projected into them, and they're always attached to a host. Many tests need to check on some interaction between elements in the ShadowRoot and outside of it - ie, set a property on the host and make sure it's reflected in the shadow; click on a button in the shadow and many sure that an event is fired on the host, or an attribute is added; add a child and make sure it's assigned to a slot, style a CSS ::part and check that it's applied, etc. The idea that a ShadowRoot is a different state just doesn't really hold. It's merely a different branch in the DOM tree (the tree of trees). Iframes on the other hand have none of these APIs/interactions, and interactions between the iframe and it's host document are very limited, so these types of tests are probably non-existent and the pain that a switching-based API would cause haven't been felt. ShadowRoots also very commonly nest, whereas with frames testing through arbitrary testing nesting levels is probably pretty rare. So we'll want the ability to traverse deeply into ShadowRoots, possibly multiple branches of the tree of trees in a single test to test cross-components interactions. Consider a search form with three custom components - a text field, a button, and an output area - that all have shadow roots, all composed inside a shadow root. One way the test looks like this: const root = element.shadowRoot;
root.findElement(By.css('x-text-field')).shadowRoot.findElement(By.css('input')).sendKeys('hello');
root.findElement(By.css('x-button')).shadowRoot.findElement(By.css('button')).click();
assert.equals(root.findElement(By.css('x-output')).shadowRoot.getText(), 'hello'); Another way is like this presumably: driver.switchToShadowRoot(element);
driver.switchToShadowRoot(driver.findElement(By.css('x-text-field')));
driver.findElement(By.css('input')).sendKeys('hello');
driver.switchToShadowRoot(element);
driver.switchToShadowRoot(driver.findElement(By.css('x-button')));
driver.findElement(By.css('button')).click();
driver.switchToShadowRoot(element);
driver.switchToShadowRoot(driver.findElement(By.css('x-output')));
// I'm not sure how to do this - how would we get non-Element Nodes from a Driver instance?
assert.equals(driver.getText(), 'hello');
// And make sure you switch back at the end of the test!
driver.switchToShadowRoot(element); I personally find that much harder to follow because of the internal state of the driver, and there are certain things that are just not possible because you can't get a reference to a ShadowRoot, ie, you can't pass a root to a helper function, you're IDE won't help identify what root you're referencing on a line because it's not a reference... Also, now that we're using WebDriver to interact with ShadowRoots, what do all the other APIs on WebDriver do? Why do I care about
It's not possible to remove a ShadowRoot, even if you delete the |
I'd like to second @justinfagnani. Nested ShadowRoots are going to be very common and how would you e.g. select a list of all .whatever elements in a scenario like this where custom-list, custom-child and foo all have their own shadowroots?
|
Related: w3c/csswg-drafts#640 |
I have written a spec proposal in w3c/webdriver#1320 |
@AutomatedTester you didn't address any of my points in my last comment. Shadow DOM simply isn't like iframes, as I've pointed out, and some of your concerns, like removing a ShadowRoot, just aren't possible. The switching API will add significant and unnecessary overhead to testing Web Components. |
@justinfagnani how the client API looks doesn't have to mirror the webdriver spec exactly so we can sort that as we go. The idea is fundamentally is where we are working from and we need to "switch" to that point. Since there is no way to from In the case of a Since we have this situation where the remote end needs to know what context it should be in we need to tell it to switch to that and carry on doing the next item. As @gsnedders pointed out we dont have a mechanism to penetrate |
Hello to all, Regarding the handling of the Shadow Elements themselves, I see two major sources of concerns:
In that regard, I see that for the first issue a search would be recommended to avoid having to specify the whole tree of elements. But in that case, the second issue would raise the issue of collisions, forcing the framework to allow certain flexibility for the user to adapt to its certain case. Would it make sense to add the following functionalities?
Thanks |
@MelbinFrancis you are barking up the wrong tree, this is not a bindings issue, rather a W3C issue as @AutomatedTester said, the proposal will have to be accepted first. |
I was able to get the Shadow DOM to work with chrome, but no success with SafariDriver since Chromedriver now supports shadowDOM but not SafariDriver |
Need shadow dom support - I have one word for you: Playwright. |
playwright does not offer on-device testing in mobile browsers and is not an option for downstream issues like appium/appium#9733. I'm really surprised that this hasn't been fixed in over 2 years and that there's not more activity here. Is this really such a niche/edge case that not many run into? Or do they simply not use selenium for this kind of testing at all? |
@msn-pixel Can you please share the approach you followed. It would be really helpful. |
I actually have a 6 layer nested shadowroot with constant elements changing to deal with. In my opinion by far the iwebelements need to be able to have a .shadowroot for cleaned / easier to handle code. The current way is a flat out nightmare. Executescript needs to also be smart enough to continue off of a webelement. In fact I think executescript is the key for you to link all this together! |
I believe the original idea was very good, and I would be happy to see this topic pushed forward. |
@justnpT Maybe it is not appropriate to mention it here, but for in our project, it was reason #1 to move to Playwright (https://playwright.dev). It has everything you could dream of for shadow dom support. |
@Tallyb this is an interesting solution for anyone who is ok with building js-based test framework and drop all of the features that selenium environments and community brings in. It is very good that it is mentioned here as alternative. |
It appears that the webdriver has been updated to include shadow DOMs by @AutomatedTester . What is the next step in adding support to Selenium? |
@ngenereux-ps Well, we need an implementation from a browser vendor. I will try to carve out time over the next couple of weeks to add it to a browser so we can see how it works. |
Finally! This is heavily needed in my c# programming. Does this mean we can finally stop parsing .ExecuteScript? |
it looks like this shadow-dom tech took selenium by surprise and changed the game a little bit 😆 lucky those who don't have to deal with it |
@justnpT just as a note, Playwright now has bindings for: |
Glad to find some discussion here about Selenium supporting ShadowDOM 🙂 Echoing @justinfagnani and @dominikg: For our project, I'm looking into supporting scoped CSS, so that CSS from one module doesn't spill over into other modules. Support for If that's the case, then I think it's likely that there might be a lot of nested ShadowDOM elements. In our case, we'd probably have almost one ShadowDOM per HTML element: <div className="card">
#shadow-root
<div className="filter">
#shadow-root
<div className="filter-block">
#shadow-root
...
#shadow-root-end
</div>
#shadow-root-end
</div>
#shadow-root-end
</div> This is just our current concept, so we may find out that this is a bad idea 🙂 If we do implement something like this, though, I think it would make testing with Selenium almost impossible, given the current ShadowDOM API. Not sure what the fix is for this (and as I mentioned, we might find out that this doesn't work for our needs, anyway), but thought I'd throw this out there 🙂 |
We should probably close this issue, as shadow DOM traversal has been added to both the W3C spec and to (most? All of?) the language bindings. In Java, the The exception throwing behavior is consistent with the Selenium philosophy that you should know the structure of the page you’re automating. If the page does not match that understanding, that is an exceptional condition, warranting throwing an exception. |
Maybe there is some link to the pull request / topic where new changes werre introduced ? |
It got closed because the implementation on the Selenium side is ready, what is missing is the implementation on the browser drivers side. |
So that means folks should open up tickets with the respective browser drivers that are missing the implementation? If so, be good to link them here for reference. |
The implementation work is already underway. Chrome v96 support is likely: |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I've been gradually trying to push support of shadow DOM v1 into selenium (see #4230, #5762).
However, we are still missing one major piece: traversal.
There needs to be some ability to traverse shadow DOM when calling
FindElement
and what not.So maybe we can discuss some possible implementations here?
What we can't/shouldn't do:
/deep/
The way I see this working is that we should treat the DOM as we would in the browser, meaning there will not be a way to select a deep element in one call:
Which, in the browser, would be structured the same (no shortcuts):
So maybe we just need to implement
ShadowRoot
onWebElement
? Which can benull
(just like in the browser).The text was updated successfully, but these errors were encountered: