Best way to automate loop in Selenium - selenium

I would like to automate some repetitive task - say submitting some form more than once. I am stumbling on the page load issues, so I want you to ask you how do you do it. Say, I want to submit ten different entries to our form. so I can do something like this:
for (int i =0; i<10; i++){
String name = getNextName();
String surname = getNextSurname();
Webelement newUserButton = driver.findElement(By.id("newUser")));
newUserButton.click();
WebElement name = driver.findElement(By.id("name")));
name.sendKeys(name);
WebElement surname = driver.findElement(By.id("surname")));
surname.sendKeys(surname);
WebElement submit = driver.findElement(By.id("submit")));
submit.click();
}
But I found out that if my test environment is slowlier, the above loop can crash. I tried to add some Thread.sleep() to the code, but if I want so submit, say, 200 entries, it can be really long to do the script.
Is there any function which can wait only the time when the form is ready?

Sounds like you need to add an explicit wait - see the Webdriver page Advanced Usage - Explicit and Implicit Waits
With the explicit waits, you can tell webdriver to wait until the form is in the ready state - typically a certain field is visible or reset (depends on what happens to your form when you click submit).

If you are using Selenium 2.0 you can make the WebDriver to wait until some action takes place by creating a WebDrivewWait object in you code. You can check out this link for more info - http://selenium.googlecode.com/svn/trunk/docs/api/java/index.html

Related

Selenium: Checking if several elements are not visible takes too much time

In one of my testcases, im checking if some elements are NOT visible.
Its very simple:
Login
Check if 5 buttons inside the left menu bar are not visible (As the user has no rights)
End test
This shouldnt take more than 10 seconds to test.
But as im using implicit wait, it does always wait 5 seconds for each button, which causes the test to take way too much time to finish. Currently it takes more than 30 seconds just to test if 5 buttons are not visible.
Im using this method:
var elements = _webDriver.FindElements(By.XPath(selector));
if (elements.Count > 0)
{
throw new Exception(selector + " still displayed");
}
Are there any other ways how to make this work?
Use a explicit wait to check for the first element and then just check the other elements directly (with implicitly_wait = 0).
something like:
try:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH, selector))
)
except TimeoutException:
# no element found
if element:
# check the presence of the other elements with find_element
documentation:
https://selenium-python.readthedocs.io/waits.html

Can't select option: element is found but invisible

I'm trying to automate a website which is not under my control, so I can't change its HTML and CSS. I need to select an option from a combo box.
I can successfully find a "select ../>" element but when I try to select an option via SelectByText, ByValue, ByIndex it results in the ElementNotVisibleException. The html is pretty complex on that page and I believe that developers assigned "display:none" by a css-style. I can navigate to the "div" which contains that combo box and click on it via Actions but it doesn't help to select an option after that. After such a click I see for a second the options on the screen and then the combo box collapses.
Is it possible at all to overcome such a problem?
Since Selenium API tries to be "user-centric" it will not allow interaction with non-visible elements. There are two approaches you can try:
1) Click on the select element, then perform an explicit wait for the option to become visible. This is useful if the page is using JavaScript to display the select options which can cause slight delay.
By bySelect = By.id("id_of_select_element");
By byOption = new ByChained(bySelect, By.xpath(".//option[contains(text(), 'text_of_option')]");
WebElement select = driver.findElement(bySelect);
select.click();
try {
// wait at-most 5 seconds for element to become visible
WebElement option = new WebDriverWait(driver, 5)
.until(ExpectedConditions.visibilityOfElementLocated(byOption)));
} catch(TimeoutException t) {
System.err.println("Timed out while waiting for dropdown to become visible: " + byOption.toString());
}
2) If the above doesn't work, you can be a little more invasive and execute some JavaScript to force the option to be selected. This is only recommended as a last resort.
public void selectDropdownByText(WebDriver driver, WebElement select, String text) {
((JavascriptExecutor) driver).executeScript(
"var select = arguments[0]; for(var i = 0; i < select.options.length; i++) {if(select.options[i].text == arguments[1]) {select.options[i].selected = true; }}", select, text);
}
ok, Element is not visible exception is thrown because of "user-centric" behavior of selenium,
In my working experience i found out that,
Selenium is not able to select element which are not visible to clients.
I mean can't select those who not appears on UI Window,
Still those are you can inspect on HTML DOM but cant access through selenium.
When those are visible on screen you can very well select those elements.
solution is before finding out select tag you must click on it to get visible full options tags.
Clicking makes all options that needs to be selected are now visible to clients.
Then you find that select element and then select options under select tag. when those List of options are completely visible on screen.

Not able to click or page not responding to click in phantomjs-selenium in java

I am doing project on different crawlers and trying to mimic user actions. As part of it, I am crawling this url. Here there is a zip code box and I am trying to click on it and extract text from the drop down which will appear after that. I wrote the below code but not sure why it is not working at all. Can anyone please help? I did exhaustive search to find root cause but got nothing. Any suggestions would be much much appreciated.
driver.getUrl(aboveUrl);
WebElement inputBox = driver.findElement(By.id("pincodeInputId"));
inputBox.click();
System.out.println(driver.findElement(By.className("_3mWImx")).getText());
-- This gives null;
Awaiting help !
The reason is the node that you picked is the parent node of the element that has the text
You should use
System.out.println(driver.findElement(By.css("_3mWImx span")).getText());
And that would work. Also note that there are multiple element with the class _3mWImx, so this will only give you the first one. If you are interested in all of them, then you should be using driver.findElements and looping through the result
Actually there are more than one values in the drop down if you want to print all you have to used findElements(). Use this code it will give you desired result :
WebDriver driver=new FirefoxDriver( );
driver.manage().window().maximize();
driver.get("https://www.flipkart.com/moto-e4-plus-fine-gold-32-gb/p/itmevqynuz4fwxca");
WebElement inputBox = driver.findElement(By.id("pincodeInputId"));
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
inputBox.click();
List<WebElement> elements=driver.findElements(By.className("_3mWImx"));
for(WebElement ele:elements)
{
System.out.println(ele.getText()); //It will print innertext of each element
}
Output :
From Saved Addresses
Loginto see your saved addresses

Selenium WebDriver auto populate value from drop down

Could you please help me for finding an element in webdriver:
Suppose we have two drop downs one is client and second facility. Also, without selecting client we cannot select facility as its disabled.
We've selected client value from drop down.
Now I've written a script for a new tab.
After that, I've to find facility field through ID but it shows element is not found, then could you please help me for the same?
..
Attached is the screen shot for your reference.
Could you please check?
Continue with previous question Select options from Autopopulate text boxes using Selenium webdriver
When you are using same cssSelector second time, it locates first dropdown element which is invisible at that time. you need to use more specific locator as below using label text :-
WebElement facility = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("facility")))
facility.sendKeys("Ho")
List<WebElement> facilityOptions = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(".//div[label[text() = 'Ordering Location']]/ul[#class = 'typeahead dropdown-menu']//a")))
facilityOptions.get(0).click()
Full working example code :-
driver.get("https://bioceptbetaweb.azurewebsites.net/Account/Login");
driver.manage().window().maximize()
WebDriverWait wait = new WebDriverWait(driver, 60)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username"))).sendKeys("ajay.kumar#technossus.com");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password"))).sendKeys("Ajay#123");
wait.until(ExpectedConditions.elementToBeClickable(By.id("btn-Login"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Place a New Order"))).click();
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("loaderDiv")));
//this sleep is required because after invisibility of loader focus goes to first input which is Requisition Number
//If you are filling form from first input no need to for this sleep
//if you want to input directly to client field need to sleep to avoid focus first
Thread.sleep(3000);
WebElement client = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("client")));
client.sendKeys("Ho");
List<WebElement> dropdownOptions = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(".//div[label[text() = 'Client']]/ul[#class = 'typeahead dropdown-menu']//a")));
dropdownOptions.get(0).click();
WebElement facility = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("facility")));
facility.sendKeys("Ho");
List<WebElement> facilityOptions = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(".//div[label[text() = 'Ordering Location']]/ul[#class = 'typeahead dropdown-menu']//a")));
facilityOptions.get(0).click();

Is by.id better than by.tagname?

I was working on reading mails from gmail using webdriver and in between I hit upon this difference between By.id and By.tagname.
I am trying to get access to a "table" whose id is ":pg". So I could
Either use By.id(":pg")
OR use By.tagname("table") and search for an element with id :pg
Here is the code for both cases.
By.id:
WebDriver webDriver = new FirefoxDriver();
webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
webDriver = webDriver.switchTo().frame("canvas_frame");
WebElement table1 = webDriver.findElement(By.id(":pg"));`
Above code, I directly get the element which has id ":pg"
By.tagname:
WebDriver webDriver = new FirefoxDriver();
webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
List<WebElement> tables = webDriver.findElements(By.tagName("table"));
for(WebElement table2: tables){
String id = table2.getAttribute("id");
System.out.println("id: "+ id);
if(id != null && id.equals(":pg")){
System.out.println("FOUND IT!!!");
}
}
Above code, I find all elements with the tagname of table and then see which one has the id ":pg".
Both these code snippets are essentially doing the same but using different ways(By.id or By.tagname). However, the first snippet of code which uses By.id always succeeds while the second snippet of code which uses By.tagname fails almost always. (It will work with additional waiting however)
Why is this difference between By.id and By.tagname?
Thanks,
Chris.
The :pg element is not present on the page initially.
Using By.Tag, selenium will not wait for the :pg element.
Because By.Id example is more specific, selenium will continue checking if the :pg element exists until the implicit wait (5 seconds) times out.
By.Tag is not specific at all. On findElements(By.tagName("table"), Selenium will return an array of all the tables that are present immediately after the page loads. As the :pg element is not present yet, it will not be in the array.
To answer your question, yes it is better to use By.Id because:
1. It is more specific.
2. Saves lines of code
3. Forces selenium to wait for the element to exist.
It is better to use By.Id according to your question.
By.tag is not used for specific data, it actually will search and return an array of all the tables with the specified tag name. On the other hand using id you can get the appropriate output for identifying/locating element.
Go for tag only if id, name or class is not specified and the best way can be By.cssSelector if no element is found.
Thanks