wait until no text in a box / boxes - java

I am writing in java a method using selenium that will clear a form entry, that is, several boxes may have text in them. My method will click a "clear search form" and then wait for all the boxes to be clear. I tried the following:
WebDriverWait wt = new WebDriverWait(driver, 30);
click("Clear Search Form", clearSearchForm);
for (int ind = 0; ind < boxes.size(); ind++) {
wt.until(ExpectedConditions.textToBePresentInElementValue(boxes.get(ind), ""));
}
however, it looks like the Expected Conditions waits for the text to contain "" rather than to equal "", so any text will contain "". I forgot to put in the clearSearchForm click, and the method succeeded anyway even though the text boxes were not clear, since they all contained "".
I tried to find an ExpectedConditions for the value to be equal to "" and not contain it but I could not.
I have seen people rewrite a wait method so they could customize it to what they want. When I searched with google I could not find examples, though I am sure there are examples, as I have seen them before. I just can't find them now. Can anyone direct me to such an example (or just type one)?
Thanks

Here is a possible solution
public static ExpectedCondition<WebElement> textInValue(final WebElement el) {
return new ExpectedCondition<WebElement>() {
#Override
public WebElement apply(WebDriver driver) {
return el.getAttribute("value").equals("") ? el : null;
}
}
}
And use it like this
for (int ind = 0; ind < boxes.size(); ind++) {
try {
wt.until(textInValue(boxes.get(ind)));
}
catch (TimeoutException e) {
// print message
}
}

Related

How to dynamically add clickable element to url address and phone numbers in string that come from api? Android Java

I have some data from api like:
"www.someUrl.com/someUrl.htm\ntel. +34 666 999 111"
or
"www.someUrl.com www.someUrl.com" - it is element.getTextDescription() in code below
I need to add this dynamically to android layout so i did something like this :
private void prepareHeader(TextView textView, El element) {
textView.setText(element.getTextDescription().replaceAll("\\\\n", "\n"));
}
private void prepareContent(TextView textView, El element) {
textView.setText(element.getTextDescription().replaceAll("\\\\n", "\n"));
}
private void prepareTextViews(ArrayList<El> data) {
for (int i = 0; i < data.size(); i++) {
TextView textView = new TextView(this);
El element = data.get(i);
String[] splittedElement = element.getTextName().split("_");
if (splittedElement.length == 2) {
prepareHeader(textView, element);
} else {
prepareContent(textView, element);
}
if (i == 0) {
textView.setPadding(40, 30, 0, 20);
}
essentialInfoContainer.addView(textView);
}
}
I don't know how to parse text which i get from api, and change part of it to clickable elements. I need something like this :
< it is clickable url element>www.someUrl.com/someUrl.htm< /it is clickable url element > + \ntel. + < it is clickable number element >+34 666 999 111< /it is clickable number element >
or
< it is clickable url element>www.someUrl.com< /it is clickable url element > < it is clickable url >www.someUrl.com< /it is clickable url >
sometimes element.getTextDescription() get me only regular string and then i would like to have: "regular string"
have a look at this post : Android set autoLink attribute programmatically
your best bet is going to be to create these dynamic objects with the autoLink property (which you can also set in xml obviously).
Linkify.addLinks(your_text_view, Linkify.PHONE_NUMBERS);
as a more complete example. hope this somewhat helps, also, have a look at SpannableStringBuilder : https://developer.android.com/reference/android/text/SpannableStringBuilder which can help you achieve different looks for these clickable items. Also consider either creating separate textview items per item you want to show, either in code or xml, as this might be an easier solution to your problem. let me know if this doesn't answer your question and i'll see what i can do to edit it.

Java selenium avoiding iframe address bar element

Currently I wrote a short program that traverses through a page and looks for web elements with the tagname = "input", then uses sendkeys to send data to the element, then submits it. The problem I have is that although it works most of the time, if I have an iframe on the page, and I traverse through the webpage looking for an element with the tagname = "input", it focuses on the addressbar of the iframe and sends data to it, then tries to submit it causing an error (when I printed the tagname of the addressbar in the iframe, it printed out "input" on the console).
Is there a way to avoid the addressbar on an iframe from being picked up as an element with the tagname = "input"?
Im using the following to check if an element has tagname of "input":
List<WebElement> element = driver.findElements(By.xpath("//*"));
int mainSize = element.size();
for ( int j = 0; j < mainSize; j++ ) {
if(frameElement.get(j).getTagName().toString().equals("input")){
//do something
}
}
Some notes:
-This occurs when going through the webpage elements searching through tagnames for "input" elements BEFORE switching to the iframe element with the switchTo() method.
In order to avoid the address bar, you can introduce one more check to ensure that the input element is not an address bar. Following is the updated code to achieve this:
List<WebElement> element = driver.findElements(By.xpath("//*"));
int mainSize = element.size();
for ( int j = 0; j < mainSize; j++ ) {
if(element.get(j).getTagName().toString().equals("input") &&
!element.get(j).getAttribute("class").equals("urlbar")){
//do something
}
}
UPDATE 1
We can retry when unexpected browser search bar appears. Try following:
List<WebElement> element = driver.findElements(By.xpath("//*"));
int mainSize = element.size();
for ( int j = 0; j < mainSize; j++ ) {
if(element.get(j).getTagName().toString().equals("input") &&
!element.get(j).getAttribute("class").equals("urlbar")){
//do something
try {
element.get(j).sendKeys(somedata);
element.get(j).submit();
} catch (WebDriverException we) {
System.out.println("It seems browser search bar has been appeared. Retrying...");
//Pressing escape key to get rid of browser search bar
element.get(j).sendKeys(Keys.ESCAPE);
//Retrying
element.get(j).sendKeys(somedata);
element.get(j).submit();
}
}
}
Let me know, if you have any further queries.

How to get all "li" elements of "ul" class in Selenium WebDriver

I'm new to Selenium webdriver. I came across a requirement where I have to run my test which clicks on all links with in a section. Can someone help me with the Java code for this. Attached a image which shows firebug properties of that particular section.
I have tried the below code but it returns me a null list.
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://dev.www.tycois.com/");
driver.manage().window().maximize();
List<WebElement> allElements = driver.findElements(By.xpath("html/body/div[10]/div/div[1]/div[3]/ul[1]/li[5]"));
System.out.println(allElements);
for (WebElement element: allElements) {
System.out.println(element.getText());
element.click();
}
}
Thanks in advance.
The details aren't clear but it looks like you are trying to print the links in the INDUSTRIES section of the footer. If that's true, this should work.
driver.get("https://dev.www.tycois.com/");
WebElement industries = driver.findElement(By.cssSelector("div.columns.three.alpha > ul"));
List<WebElement> links = industries.findElements(By.tagName("li"));
for (int i = 1; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
You can't click the links in this loop because once you click the first one, you will no longer be on the page. I would suggest that you store the URLs from each link in an array and then driver.get(url) for each one. Or you could store the expected URLs in an array and compare the URLs from the links to the expected URLs and not have to navigate at all. The choice is up to you...
The solution from JeffC works with the tweak detailed below -
driver.get("https://dev.www.tycois.com/");
WebElement industries =
driver.findElement(By.cssSelector("div.columns.three.alpha > ul"));
List<WebElement> links = industries.findElements(By.tagName("li"));
for (int i = 0; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
The alternate answer above, which I cannot comment on because I'm new to the site had
for(int i=1; i < links.size(); i++)
However this misses off the first element in the list. The suggested fix to use -
for(int i=1; i <= links.size(); i++)
will cause an IndexOutOfBoundsException.
To fix, simply set your iterator to start at 0 instead of 1
You could use like for example:
driver.findElements(By.xpath("//li[contains(#class,'managed-services')]/ul/li/a"));
It is usually bad idea to use XPath attached to root of html i.e Absolute xpath, you should always try to use the shortest selectors possible i.e Relative xpath.
Also remember that if links are hidden, you need to trigger action, which enables them - like open menu for instance.
You can try with the below code.
Just change the xpath according to your application.
List<WebElement> liElements = driver.findElements(By.xpath(".//*[#id='fk-mainhead-id']/div[2]/div/div/ul/li"));
System.out.println(liElements);
for(int i=1; i <= liElements.size(); i++)
{
WebElement linkElement = driver.findElement(By.xpath(".//*[#id='fk-mainhead-id']/div[2]/div/div/ul/li[" + i + "]/a"));
System.out.println(linkElement.getText());
}
WebElement industries = driver.findElement(obj.getElement("history_list"));
List<WebElement> links = industries.findElements(By.tagName("li"));
boolean a = false;
Thread.sleep(10000);
for (WebElement option : links) {
System.out.println("value =" + option.getText());
String s = option.getText();
if (s.equals(new_site_name)) {
a = true;
break;
} else {
continue;
}
}

Waiting for a chart to refresh, selenium Java

I'm trying to find an appropriate ExpectedConditions method for this situation. I have a chart and I want to check the text in each row after re-sorting the chart. Problem is, when the chart is refreshing, the text still exists, it's just greyed out. So when I click a button to get the chart to be re-sorted, then look for the text that I'm looking for right away, the test fails because the text hasn't changed yet. I can't use visibilityOfElementLocated because the element is still visible when the chart is refreshing, I'm just waiting for the element to change.
Not sure if any of that makes sense!! It is a really difficult issue to explain.
A little background: I'm using Selenium Java and testing using Chrome. Here is my method thus far. It works fine, I just need to figure out how to make the program wait long enough for the chart to refresh WITHOUT using a sleep statement.
Thanks a bunch everyone! I know that wasn't as clear as it could be, but please let me know if you need any clarification.
public void Check_for_text_in_column(String text, String row, String column)
{
By by = By.xpath("//*[#id=\"table_Table_table_ktg\"]/tbody/tr[" + row + "]/td[" + column + "]/div/div/span");
WebDriverWait wait = new WebDriverWait(getWebDriver(), WAIT_TIME);
//This is the line that I need to change:
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
if(!element.getText().equals(text))
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
}
Cheers!
You can replace
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
with
WebElement element = wait.until(ExpectedConditions.textToBePresentInElement(by, text));
EDIT:
Your WAIT_TIME is the timeout for your wait.
If the expected condition hasn't returned true before timing out according to your WAIT_TIME, then element will be null.
So, your check could look something like this:
if(element == null)
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
EDIT:
Perhaps another option could be something like this:
public void Check_for_text_in_column(String text, String row, String column)
{
By by = By.xpath("//*[#id=\"table_Table_table_ktg\"]/tbody/tr[" + row + "]/td[" + column + "]/div/div/span");
WebDriverWait wait = new WebDriverWait(getWebDriver(), WAIT_TIME);
// your original find
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
// flag to set when text is found, for exiting loop
boolean hasText = false;
// counter for # of times to loop, finally timing out
int tries = 0;
// until text is found or loop has executed however many times...
while (hasText == false && tries < 20) {
// get the element
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
// if text is not present, wait 250 millis before trying again
if(!element.getText().equals(text){
Thread.sleep(250);
tries++;
}
else{
// text found, so set flag to exit loop
hasText = true;
}
}
if(!element.getText().equals(text))
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
}
I know you said you don't want sleep statements, but I assume you meant that you just don't want a single unnecessarily long one. Even ExpectedConditions are using sleep internally. They sleep for a few milliseconds between polling for changes - and that's exactly what this does, just without the ExpectedCondition type wrapper.

How to switch between frames in Selenium WebDriver using Java

I am using java with WebDriver.I have to switch between two frames. I have recorded the test case in selenium IDE and in that I got the values as selectFrame relative=top select Frame=middle Frame
But there is a problem it is not able to recognize the relative=top and middleFrame. How can I solve this problem in Selenium WebDriver with Java?
WebDriver's driver.switchTo().frame() method takes one of the three possible arguments:
A number.
Select a frame by its (zero-based) index. That is, if a page has three
frames, the first frame would be at index 0, the second at index 1
and the third at index 2. Once the frame has been selected, all
subsequent calls on the WebDriver interface are made to that frame.
A name or ID.
Select a frame by its name or ID. Frames located by matching name
attributes are always given precedence over those matched by ID.
A previously found WebElement.
Select a frame using its previously located WebElement.
Get the frame by it's id/name or locate it by driver.findElement() and you'll be good.
to switchto a frame:
driver.switchTo.frame("Frame_ID");
to switch to the default again.
driver.switchTo().defaultContent();
First you have to locate the frame id and define it in a WebElement
For ex:- WebElement fr = driver.findElementById("id");
Then switch to the frame using this code:- driver.switchTo().frame("Frame_ID");
An example script:-
WebElement fr = driver.findElementById("theIframe");
driver.switchTo().frame(fr);
Then to move out of frame use:- driver.switchTo().defaultContent();
You can also use:
driver.switch_to.frame(0)
(0) being the first iframe on the html.
to switch back to the default content:
driver.switch_to.default_content()
Need to make sure once switched into a frame, need to switch back to default content for accessing webelements in another frames. As Webdriver tend to find the new frame inside the current frame.
driver.switchTo().defaultContent()
There is also possibility to use WebDriverWait with ExpectedConditions (to make sure that Frame will be available).
With string as parameter
(new WebDriverWait(driver, 5)).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("frame-name"));
With locator as a parameter
(new WebDriverWait(driver, 5)).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("frame-id")));
More info can be found here
This code is in groovy, so most likely you will need to do some rework. The first param is a url, the second is a counter to limit the tries.
public boolean selectWindow(window, maxTries) {
def handles
int tries = 0
while (true) {
try {
handles = driver.getWindowHandles().toArray()
for (int a = handles.size() - 1; a >= 0 ; a--) { // Backwards is faster with FF since it requires two windows
try {
Log.logger.info("Attempting to select window: " + window)
driver.switchTo().window(handles[a]);
if (driver.getCurrentUrl().equals(window))
return true;
else {
Thread.sleep(2000)
tries++
}
if (tries > maxTries) {
Log.logger.warn("Cannot select page")
return false
}
} catch (Exception ex) {
Thread.sleep(2000)
tries++
}
}
} catch (Exception ex2) {
Thread.sleep(2000)
tries++
}
}
return false;
}

Categories