We had Selenium tests running on Sales Force non Lightning. Now I am converting to Lightning. There is a chain of menus to go through. I have successfully navigated to a certain menu, but now I have run into a problem. This is not the standard question about new element names. Here is the question. This is a small piece of what the page looks like (see below).
When using inspect with Chrome I can find the elements. This is what it looks like (a small cross section corresponding to above). The SPAN tag has the label ("Original Agreement") and the DIV below it will contain the box for the input value.
<div class="slds-form-element__control" data-aura-rendered-by="228:1224;a">
<div data-aura-rendered-by="1108:0" class="uiInput forceSearchInputLookupDesktop uiInput--default" data-aura-class="uiInput forceSearchInputLookupDesktop uiInput--default">
<label class="label inputLabel uiLabel-left form-element__label uiLabel" for="157:1224;a" data-aura-rendered-by="1103:0" data-aura-class="uiLabel">
<span class="" data-aura-rendered-by="1104:0">Original Agreement</span>
<!--render facet: 1106:0--><!--render facet: 1107:0--></label>
<div data-aura-rendered-by="161:1224;a"><div class="contentWrapper slds-box--border" data-aura-rendered-by="162:1224;a">
However, Selenium can not find the elements (though inspect does). When I did a "View Page Source instead of an
inspect, almost the entire thing is in JavaScript like this:
function rewriteAndInjectCss(linkEl, source, varLookup) {
var css = rewriteCssVars(source, varLookup);
injectStyles(linkEl, css);
}
but a lot more. Almost all functions, with maybe only a couple elements.
In the past when I have seen something similar there is often an iframe to switch to to get the elements. But there is no iframe to switch to. So I am stuck how to get these. Can anyone shed some light?
OK. Found it. I needed to do a driver.switchTo().defaultContent()
Related
Example of the HTML of a dropdown element:
<div aria-owns="ember-basic-dropdown-content-ember1234" tabindex="0" data-ebd-id="ember1234-trigger" role="button" id="ember1235" class="ember-power-select-trigger ember-basic-dropdown-trigger ember-view"> <!---->
<span class="ember-power-select-status-icon"></span>
</div>
The xpath and CSS selector also contain the same ember id.
xpath : //*[#id="ember1235"]
css selector : #ember1235
The ember id would change from id="ember1235" to say, id="ember1265" when there is a change in the UI.
I am using id to locate the element. But every time it changes I need to modify the code. Is there any other attribute I could use for Ember JS UI elements?
There is quite a lot to discuss in your question but hopefully we will have a good answer for you #PriyaK
The first thing to mention is that Ember IDs may not be the best method to select an element in the DOM. As you have already mentioned, they can change from time to time and also it doesn't really give you a great semantic thing to select in your selenium test so it might seem a bit out of context when looking back.
One thing that you could try is to either pass a class to the ember-power-select component (the one that provides the HTML that you used in your example) and use that to select the element, something like:
<PowerSelect
#class="my-fancy-class"
as |name|
>
{{name}}
</PowerSelect>
Then you should be able to select the selected value by using the CSS selector .my-fancy-class span (because the component outputs the selected value in a span)
We just tried this in an example app but it didn't actually work 🤔 Never fear, you can also do something like this and it should work with the same selector as before:
<div class="my-fancy-class">
<PowerSelect as |name|>
{{name}}
</PowerSelect>
</div>
This is fine, but there are also a few issues using classes for selectors in tests. One example of a problem that might crop up is that your tests might all suddenly stop working if you did a style refactor and changed or removed some of the classes on your elements. One technique that has become popular in the Ember community is to use data-test- attributes on your DOM nodes like this:
<div data-test-my-fancy-select>
<PowerSelect
#class="my-fancy-class"
as |name|
>
{{name}}
</PowerSelect>
</div>
which can then be accessed by the following selector: [data-test-my-fancy-select] span. This is great for a few reasons! Firstly it separates the implementation of your application and tests from your styling and avoids the issue I described above. The second benefit of this method is that using what #Gokul suggested in the comments, the ember-test-selectors package, you can make use of these data-test- selectors in your development and test environments but they will be automatically removed from your production build. This is great to keep your DOM clean in production but also, depending on the size of your application, could save you a reasonable amount of size in your templates on aggregate.
I know you say that you are using selenium for your testing but it's also worth mentioning that if you're using the built-in Ember testing system you will be able to make use of some testing helpers that addons may provide you. ember-power-select is one of those addons that provides specific testing helpers and you can read more about it in their documentation: https://ember-power-select.com/docs/test-helpers
I hope this answers any questions you had!
This question was answered as part of "May I Ask a Question" Season 3 Episode 1. If you would like to see us discuss this answer in full you can check out the video here: https://www.youtube.com/watch?v=1DAJXUucnQU
I have a Protractor/Jasmine E2E Automation test that is to drag and drop a couple of collapsible panels to change the order and just verify they the elements have been moved.
I'm currently running latest versions of Protractor, Jasmine, and webdrivers (tests run in IE 11)
EDIT: Found out we're using ng-dragula to perform the drag and drops. I'm assuming protractor just isn't playing nicely with this. I'll do more digging about it, but still curious to know if there's a work around.
/end edit
This function used to work, and I have since tried a handful of variations of it:
browser.actions().
mouseMove(dragFromElement).
mouseDown().
mouseMove(dropToElement).
mouseUp().
perform();
browser.actions().
dragAndDrop(dragFromElement, dropToElement).
perform();
I've also tried with .getWebElement() appended to the element tag, getting each elements location and doing a mouse click, move, drop to those locations, and trying various actionSequences instead of actions().
Basically all of the above will highlight the text of the elements like it's clicking behind the panels and does not actually grab the element and drag/drop it.
Curious to know if this is a known problem or if there's a possible solution for my issue.
What i'm working with is:
<core-drag-and-drop-panel _nghost-wod-4="">
<div class="sortable-panels" _ngcontent-wod-4="">
<div id="elementId_10" class="draggableDiv" _ngcontent-wod-4="" aria-dropeffect="move" aria-grabbed="false">
<div id="elementId_12" class="draggableDiv" _ngcontent-wod-4="" aria-dropeffect="move" aria-grabbed="false">
<div id="elementId_1" class="draggableDiv" _ngcontent-wod-4="" aria-dropeffect="move" aria-grabbed="false">
</div>
</core-drag-and-drop-panel>
Please don't make comments regarding why i posted a similar question. I have tried many things and nothing is working. Below is the HTML
<div id="businessSettingsColumn1">
<div class="sectionLink">
Business details
</div>
<div class="sectionLink">
Operating hours
</div>
<div class="sectionLink">
Closed dates
</div>
<div class="sectionLink">
Appointment notifications
</div>
I need to click the second link
I have tried
1) webdriver.findElement(By.partialLinkText("Operating hours")).click();
2)webDriver.get(mylement.findElement(By.tagName("a")).getAttribute("href"));
3)
List<WebElement> businessLinks= busCol.findElements(By.className("sectionLink"));
for(WebElement bLink :businessLinks) {
if(bLink.getText().contains("Operating hours")) {
bLink.findElement(By.tagName("a")).click();
}
}
4) Using the Action builder to move the mouse and then doing a click
Also when i did this 3 times in a row , my element got clicked
webdriver.findElement(By.partialLinkText("Operating hours")).click();
webdriver.findElement(By.partialLinkText("Operating hours")).click();
webdriver.findElement(By.partialLinkText("Operating hours")).click();
I am using Firefox version 25.0 and Selenium version 2.35.0. Funny thing though is when i do a sysout , the values get printed and when i try to get the url using webdriver I get "Element not found in the cache - perhaps the page has changed since it was looked up" .. its pretty much a static page with links only so i dont understand why i am not able to click it.. Any help will be much appreciated.
Can you try calling focus() on the element before you click on it?
This usually occurs because the element was there at some point, but then something happened and then it's no longer there for some reason. I encounter this frequently when a page makes AJAX calls for example.
Have you tried adding some waits so that selenium is sure that the element is ready?
I was unable to find the element (with id below) with Selenium even though it's visible in the html source page after successfully clicking on 'Search' button (using Selenium) of the previous page that has url as follows:
String url="https://sjobs.brassring.com/1033/ASP/TG/cim_advsearch.asp?partnerid=25314&siteid=5290";
driver.get(url);
if(driver.findElements(By.id("submit1")).size() != 0)
driver.findElement(By.id("submit1")).click(); // clicking on 'Search' button
if(driver.findElements(By.id("ctl00_MainContent_GridFormatter_YUIGrid")).size() != 0)
System.out.println("FOUND!");
String pageSource= driver.getPageSource();
"FOUND!" was never rendered, nor pageSource contained the element with the above id. I am using Selenium 2.3.3 and testing with latest versions of IE, Chrome, and Firefox webdrivers. Could someone please help? Thank you.
About 1/3 from the bottom of the target page are the followings (third line is location of the id):
<div id="ctl00_MainContent_GridFormatter_datatable" class="datatable">
<div id="THeadersDiv" style="display:none;">
<table id="ctl00_MainContent_GridFormatter_YUIGrid" class="basicGrid" border="0"> <!-- this is the element in question -->
I think I got it. I believe that the driver cannot find the element because there are two elements both with identical IDs. (which is terrible web code). I looked at the rest of the code, and it looks like the two elements also share the same class, and are the only two elements with that class.
Therefore, I believe that doing a By.className(".basicGrid") should work
i'm going to rewrite all my tests project, by replacing Selenium by HtmlUnit because i'm not able to get plain text in selenium as i can do with htmlunit using "HtmlPage:asText" method. Getting plain text can help me to verify easily the content of a page, without paying attention of the presence or not of the tags.
For example a plain text like this " One, two three" may correspond to many html source:
<p>One, two three</p>
or <table> <tr><td>One1</td><td>two</td><td>three</td> </tr></table>
or <div><span>One, </span> <span>two, </span> <span>three, </span> </div>
By using HtmlUnit i can write functional test without paying attention of how the actual content will be represented in the html format.
This will give you only plain text in page
String pageSource=driver.findElement(By.tagName("body")).getText();
Below logic will gives you entire page source.
driver.getPageSource();