Skip to content
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 testing with OpenTest #225

Closed
wisam2013 opened this issue Nov 25, 2019 · 16 comments
Closed

Shadow DOM testing with OpenTest #225

wisam2013 opened this issue Nov 25, 2019 · 16 comments
Labels

Comments

@wisam2013
Copy link

I have a question over testing Shadow DOM with opentest.
Is that possible?

@adrianth
Copy link
Contributor

adrianth commented Nov 25, 2019

You can test the shadow DOM by executing client-side JavaScript. When you want to fail the test, you can throw a user-defined exception using the throw keyword.

Suppose we have a simple HTML page like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <div id="div1"></div>

    <script>
        var div1 = document.getElementById("div1");
        var shadowRoot = div1.attachShadow({mode: "open"}); 
        var input = document.createElement("input");
        input.value = "John";
        shadowRoot.appendChild(input);
    </script>
</body>
</html>

If you wanted to add a test step in OpenTest to verify that the value of the input element in the shadow DOM is "John", you'd do it this way:

- action: org.getopentest.selenium.ExecuteScript
  args:
    script: |
      var shadowRoot = document.getElementById("div1").shadowRoot
      var inputFromShadowDom = shadowRoot.querySelector("input");
      if (inputFromShadowDom.value != "John") {
        throw new Error("The name in the shadow DOM input is not John!");
      }

@adrianth adrianth changed the title Shadow DOM with opentest Shadow DOM testing with OpenTest Nov 25, 2019
@wisam2013
Copy link
Author

Ok thank you, and the selenium keywords will be used the same approach?

@adrianth
Copy link
Contributor

If you're asking whether you can use the regular OpenTest Selenium keywords together with this approach, the answer is yes. You can combine any of the Selenium keywords with the code sample in the post above. The only thing to keep in mind though, is that the JavaScript code used with the ExecuteScript action is actually being executed client-side (in the browser) and not on the test actor, which means that the JS API available in that context is restricted to what you can do in the browser. For example, you will not be able to run keywords using the $runAction API in that context, since that API is not available in the browser.

@wisam2013
Copy link
Author

Ok thank you for the explanation.

@wisam2013
Copy link
Author

wisam2013 commented Jan 20, 2020

Hi Adrian,
i have the following code and i do not know how exactly to use the approach of the shadow dom.
I still want to be able to use click on "id= locator-meprson".

<wp-state-context _ngcontent-owh-c4="" state="MePersonModel" theme="theme-light">
#shadow-root(open)
 <slot>
    <wp-meperson> reveal
 </slot>

#shadow-root (open)
<div id="mePerson-container" class="mePerson-container">
    <div id="locator-mePerson" class="mePerson-block background-primary-color1 border-primary-color1">
        <wp-contact size="medium" subline="" notstandardcolor="true" hidecontactinfoinsmallscreens="true" theme="theme-light"></wp-contact>
        <expand-arrow-icon class="medium-icon bar-icon bottom-icon expanded-false theme-light"></expand-arrow-icon>
    </div>
    <div class="mePerson-container expanded-false">
        <div class="setting-buttons-container">
            <wp-button id="signout" text="SIGNOUT" tabindex="15" addpadding="0 12px" addcursor="pointer" theme="theme-light"></wp-button>
            <wp-state-context state="UccModel" theme="theme-light">
                <wp-ucc-profiles-button id="ucc-profiles-button" buttonid="locator-meperson-manage-profiles-bttn" text="MANAGE_PROFILES" addpadding="0 12px" addcursor="pointer" theme="theme-light"></wp-ucc-profiles-button>
            </wp-state-context>
        </div>
        <div id="mePersonInfo-container" class="mePersonInfo-container">
            <wp-contact size="medium" subline="" theme="theme-light"></wp-contact>
            <wp-state-context class="ucc-toggle-container" state="UccModel" theme="theme-light">
                <wp-ucc-toggle locatorid="locator-uccstate-toggle" target="currentUcc" update-always="true" theme="theme-light"></wp-ucc-toggle>
            </wp-state-context>
        </div>
        <div class="settings-container">
            <wp-meperson-setting theme="theme-light"></wp-meperson-setting>
        </div>
        <div class="reasoncodes-container">
            <wp-state-context state="UccModel" theme="theme-light">
                <wp-reasoncode-setting theme="theme-light"></wp-reasoncode-setting>
            </wp-state-context>
        </div>
        <wp-state-context state="UccModel" theme="theme-light">
            <wp-ucc-profiles-screen id="ucc-profiles-screen" theme="theme-light"></wp-ucc-profiles-screen>
        </wp-state-context>
    </div>
</div>

i justt copied the JS from the page:

document.querySelector("#app-panel > app-main > div > div.grid > div.topbar.background-primary-color5.color-white > top-bar > div > div.meperson > wp-state-context > wp-meperson").shadowRoot.querySelector("#locator-mePerson > wp-contact") 

so if i good understand you solution is like this:

 - description: Shadow root
            action: org.getopentest.selenium.ExecuteScript
            args:
              script: |
                var shadowRoot = document.getElementById("mePersonr").shadowRoot;
                var mePerson = shadowRoot.querySelector("locator-mePerson");
 - description: Click in the meperson
            action: org.getopentest.selenium.Click
            args:
              locator: meperson

This approach did not work. I used an extension in chrome to find the shadow path "LWC ShadowPath" and i used the following path just to see if it works:
the tool gave me the following path : jspath "document.querySelector('wp-meperson')"
I used it like this:

          - description: Shadow root
            action: org.getopentest.selenium.ExecuteScript
            args:
              script: |
                var shadowRoot = document.querySelector("wp-meperson").shadowRoot;

I get the following in the log:

Executing  action org.getopentest.selenium.ExecuteScript with arguments  {"script":"var shadowRoot =  document.querySelector(\"wp-meperson\").shadowRoot;\n"}...
--
10:48:03 | ACTOR1 | DEBUG: The output values from action org.getopentest.selenium.ExecuteScript were:  	>>>>> result = null 

@wisam2013 wisam2013 reopened this Jan 22, 2020
@adrianth
Copy link
Contributor

I'm afraid what you're looking for is not yet available in the Selenium library, but that's because the WebDriver standard doesn't support it yet. You can have a look at this issue. So you can validate elements in the shadow DOM using JavaScript code with the ExecuteScript keyword, but you cannot interact with the elements (e.g. click on them).

@wisam2013
Copy link
Author

OK Thank you @adrianth , that's a pity as all the tests i have written in the last 8 months are not working because of this issue. I know it is not Opentest shortage of functionality but selenium. Do you have any expectation about that?

@adrianth
Copy link
Contributor

While the proper way to solve this is for WebDriver to introduce support for the shadow DOM, you shouldn't give up the hope just yet, as it appears there might be some workarounds. I'll take a look at this again and will let you know if I have any good news.

@wisam2013
Copy link
Author

Thank you @adrianth , i do appreciate your support.

@wisam2013
Copy link
Author

Hi @adrianth do you have any update about this issue?

@wisam2013
Copy link
Author

Hi does any one tried this https://www.npmjs.com/package/wdio-webcomponents

@adrianth
Copy link
Contributor

@wisam2013 I've done most of the research but there's no solution available yet. We need to make sure to implement this the right way so that we don't have to introduce breaking changes later on.

@stale
Copy link

stale bot commented Aug 14, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 14, 2020
@stale stale bot closed this as completed Aug 21, 2020
@wisam2013
Copy link
Author

Hi, I did notice that on the selenium webdriver a support have been made to the shadow root. Can any one confirm that? When can we expect it to be used in Opentest.

@adrianth
Copy link
Contributor

@wisam2013 I don't believe Selenium supports shadow DOM yet. If you have different information please provide a link an I will have a look.

@ewmartinez
Copy link

If you're asking whether you can use the regular OpenTest Selenium keywords together with this approach, the answer is yes. You can combine any of the Selenium keywords with the code sample in the post above. The only thing to keep in mind though, is that the JavaScript code used with the ExecuteScript action is actually being executed client-side (in the browser) and not on the test actor, which means that the JS API available in that context is restricted to what you can do in the browser. For example, you will not be able to run keywords using the $runAction API in that context, since that API is not available in the browser.

Hi @adrianth
Based on this response, we can't use the $include() aproach to use with ExecuteScript? just to clarify.
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants