I am trying to automate application,tried first to find xpath or CSS locators unable to find looks no frame also inside the element.
I am able to handle using JavaScript but unable to enter full text in the search box,it's trimming some text,,please help me.
JavaScript which i tried.
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#loc').shadowRoot.querySelector('#item0 > div.disable-select.city-country-name').click();");
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#dates').shadowRoot.querySelector('#depart').shadowRoot.querySelector('#btn').click();");
My scenario i want to click search form and enter some destination details,If possible anyway i can handle this case using locators suggest me
Shadow DOM Elements are used in this website. Shadow DOM provides encapsulation for the JavaScript, CSS, and templating in a Web Component.
Shadow DOM allows hidden DOM trees to be attached to elements in the
regular DOM tree — this shadow DOM tree starts with a shadow root,
underneath which can be attached to any elements you want, in the same
way as the normal DOM.
Refer this To get details about it or for more details Google it.
Now handle Shadow element take reference from this blog. I've tried the below code to enter text as you expected and its working for me.
public static WebDriver driver;
public static void main(String[] args){
System.setProperty("webdriver.chrome.driver", "driver_path");
driver = new ChromeDriver();
driver.get("https://www.wego.com.my/hotels");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.manage().window().maximize();
WebElement root1 = driver.findElement(By.id("app"));
WebElement shadowRoot1 = expandRootElement(root1);
WebElement root2 = shadowRoot1.findElement(By.tagName("wego-search-form"));
WebElement shadowRoot2 = expandRootElement(root2);
WebElement root3 = shadowRoot2.findElement(By.tagName("wego-hotel-search-form"));
WebElement shadowRoot3 = expandRootElement(root3);
WebElement root4 = shadowRoot3.findElement(By.id("loc"));
WebElement shadowRoot4 = expandRootElement(root4);
shadowRoot4.findElement(By.cssSelector("div.root-container div.container")).click();
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
Actions action = new Actions(driver);
action.click(element).sendKeys(Keys.chord(Keys.CONTROL, "a"));
element.sendKeys(Keys.DELETE);
element.sendKeys("narendra");
}
public static WebElement expandRootElement(WebElement element) {
WebElement newElement = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot", element);
return newElement;
}
Updated
As an alternative of sendKeys(), JavascriptExecutor can be used to set the value of text box. Use below code
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
javascriptExecutor.executeScript("arguments[0].value='Your Text Goes Here';", element);
I've tested this so many time and this is working fine in each case.
Note: using JavascriptExecutor may not trigger the search result auto suggestion.
Related
Selenium cant find this xpath I tried every way I need to click last button Deactivate but I cant
I tried xpath,cssSelectors,
#When("^I click deactivate button$")
public void iClickDeactivateButton(){
WebElement deactivateBatchButton = driver.findElement(By.xpath("//BUTTON[#_ngcontent-c14=''][text()='Deactivate'][text()='Deactivate']/self::BUTTONclass='deactivate']"));
deactivateBatchButton.click();
}
I want to click this button and carry one rest of the tests.
As the desired element is a Angular element and to locate it you have to induce WebDriverWait and you can use either of the following solutions:
cssSelector:
WebElement deactivateBatchButton = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.deactivate.xh-highlight")));
xpath:
WebElement deactivateBatchButton = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[#class='deactivate xh-highlight' and text()='Deactivate']")));
You can carry on with the button name.
WebElement deactivateBatchButton = driver.findElement(By.xpath("//*[text()='Deactivate']"));
deactivateBatchButton.click();
I am using the sendKeys(key,Keys.TAB) method to navigate through a form.
Actions action = new Actions(driver);
CharSequence key = null;
for(int i=0;i<42;i++)
{
action.sendKeys(key,Keys.TAB).build().perform();
}
At the end of every action(a tab key press) I want to know which form element is selected
I want to reach to the 42nd element of the form and cross check whether its the desired element and for that i need to retrieve some of its information.
I am new to selenium and I am not able to figure out a way to achieve this.
You can use WebDriver's TargetLocator class for this purpose.
WebElement currentElement = driver.switchTo().activeElement();
This will return you with current element it focussed currently. If no element is focussed it will return you the body element, which is the case when u launch your browser.
Internally it will be returning u the element returned by document.activeElement. So to verify u can always run as:
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement currentElement = (WebElement) js.executeScript("return document.activeElement");
I am trying to dynamically search an "li" tag item and double-click on this website: www.jstree.com (the right-top hierarchy tree sample). The code does find the WebElement but does not do anything. I am trying as follows. Can someone please point to what I am doing wrong? I am using Firefox 35.0.1 and selenium 2.44.0.
driver.get(baseUrl + "http://www.jstree.com/");
WebElement we = driver.findElement(By.xpath("/html/body/div/div/div[1]/div[1]/div[2]/div[1]/ul/li[1]/ul"));
Actions action = new Actions(driver);
List<WebElement> liItems = we.findElements(By.tagName("li"));
for(WebElement liItem:liItems)
{
System.out.println(liItem.getText());
if(liItem.getText().startsWith("initially open"))
{
System.out.println("Found it...");
liItem.click();
action.moveToElement(liItem).doubleClick().build().perform();
break;
}
}
I ended up doing this:
Modified the selector to make sure ONLY the expected elements are returned. It helps a lot in terms of execution time and reducing the number of unwanted loopings. And, then find the element in run time and use Action() on that to perform double click. I also update the Selenium binding as #alecxe suggested to work with latest Firefox
public void DemoTest() throws InterruptedException {
List<WebElement> liItems = driver.findElements(By.xpath("//*[contains(text(),'initially open')]"));
for(WebElement liItem:liItems)
{
Actions actions = new Actions(driver);
actions.moveToElement(liItem).doubleClick().build().perform();
}
}
Im trying to automate the Google Images page:
https://www.google.com/search?q=pluralsight&biw=1416&bih=685&source=lnms&tbm=isch&sa=X&ei=qGd6VN6bEZTooAT7q4C4BQ&sqi=2&ved=0CAgQ_AUoAw
All the images have the same class but no id and the results are constantly changing. So I would like to be able to click on the images based on their index.
I know how to do it in C#...but I cant figure out how to specify in the index in Java. When I try to select an index beyond 0, I get and IndexOutOfBounds error, but i cant figure out why
WebElement image = chromeDriver.findElement(By.className("rg_di"));
WebElement imageLink = image.findElements(By.tagName("a")).get(1);
imageLink.click();
Here is the entire code im using...any help would be appreciated:
System.setProperty("webdriver.chrome.driver", "/Users/user/chromedriver");
WebDriver chromeDriver = new ChromeDriver();
chromeDriver.get("http://www.google.com");
WebElement searchBox = chromeDriver.findElement(By.id("gbqfq"));
searchBox.sendKeys("pluralsight");
searchBox.sendKeys(Keys.RETURN);
chromeDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement imagesLink = chromeDriver.findElement(By.linkText("Images"));
imagesLink.click();
WebElement image = chromeDriver.findElement(By.className("rg_di"));
WebElement imageLink = image.findElements(By.tagName("a")).get(1);
imageLink.click();
Any help would be greatly appreciated
In your code:
WebElement image = chromeDriver.findElement(By.className("rg_di"));
will return the first element found on the page with a class of "rg_di".
That element has only one <a href=... /a> tag in it.
You are getting an IndexOutOfBounds exception because you are asking for the second one (zero based indexing). If you change your final WebElement to:
WebElement imageLink = image.findElements(By.tagName("a")).get(0);
The code should work for you with that small change.
This is my quick version (note the lack of storing elements I only need to do one thing with as WebElements):
public static void main(String[] args) {
// I don't have Chrome installed >.<
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement searchBox = driver.findElement(By.id("gbqfq"));
searchBox.sendKeys("pluralsight");
searchBox.sendKeys(Keys.RETURN);
driver.findElement(By.linkText("Images")).click();
WebElement image = driver.findElement(By.className("rg_di"));
image.findElements(By.tagName("a")).get(0).click();
// super-shortened version:
// driver.findElement(By.className("rg_di")).findElements(By.tagName("a")).get(0).click();
}
I'd do:
List<WebElement> we = chromeDriver.findElements(By.cssSelector(".your-class a"));
we.get(1) //should get first element in array
This code worked very well when we have similar object properties for same web buttons, then using
List<WebElement> we = webdriver.findElements(By.cssSelector(""));
and then getting
we.get(1).click();
Thank you so much for posting this answer.
Another solution may be like this:
If the class name and the index of the web element are known, then following code works:
driver.findElement(By.xpath("(//*[#class='android.widget.ImageView'])[18]")).click();
I'm using #FindBy annotations to locate WebElements. But I want to use these WebElements in methods as parameters. I had success with this only if WebElement was found on page. But if I want to wait for it I must use By (with same locator) instead.
E.g.
private static final String SEARCHFIELD_LOC = "#search input[placeholder]";
#FindBy(css = SEARCHFIELD_LOC)
public WebElement searchField;
public By searchField_by = new By.ByCssSelector(SEARCHFIELD_LOC);
That way I can use this WebElement as By object in some method, like
public boolean isElementDisplayedWithWait(final By by) { .... }
So for each element I have 4 lines of code. I'm to lazy and searching for a way to simplify that.
I found totally another solution. I will store my locators as strings.
public String searchField = ".slide.slide_search input[placeholder]"
So only 1 line of code per locator. And I hope supporting only CSS locators will be enough. I will NOT use #FindBy for getting WebElements. Instead, I will get WebElements using special method that will wait for element and will log what's going on. I will implement getting WebElement like this:
WebElement we = wait.until(ExpectedConditions.visibilityOfElementLocated(new By.ByCssSelector(locator)));
where wait is
Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
.withTimeout(timeout, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring( StaleElementReferenceException.class ) ;
The alternate of having wait/assertions/verification methods with webelement itself is available with extended webelement in QAF formerly ISFW. For example:
#FindBy(css = SEARCHFIELD_LOC)
public WebElement searchField;
searchField.waitForPresent();
searchField.assertPresent(); //auto wait
searchField.verifyPresent(); //auto wait
Reference:
QAF Selenium testing-frameworks
ISFW FAQ