I have an issue that I try to resolve.
I have a page with 4 dropdowns.
and I want to select value in each one og them.
Since the site is angular I used operation to open a drop down and other to select value.
the problem is that after clicking the dropdown to open, all the values are under the same xpath.
( the values generated after pressing the dropdown)
Example dropdown 1 19 values:
Pressing drop down 2 32 values with the same xpath
The problem is after filling dropdown 1, and passing to dropdown 2, the xpath is the same but values not changed quickly enough, So I press drop down 2 and selenium try to find values, but see values of first dropdown.
How can I make selenium (not with thread sleep) to wait until my value exists in the dropdown.
This is my code for searching a value in webelements list (meanning the drop down)
public static void clickOptionInListByXpath(String Xpath, String clickedValue)
{
Integer flag = 1;
WebElement option2;
WebDriver driver2 = WebDriverMgr.getDriver();
List<WebElement> dropdownOptions = driver2.findElements(By.xpath(Xpath));
// for (WebElement option : dropdownOptions )
for(int i= 0;i<dropdownOptions.size() && flag == 1;i++)
{
option2 = dropdownOptions.get(i);
System.out.println("\n Option is: " + option2.getText());
if(option2.getText().equals(clickedValue))
{
option2.click();
flag = 0;
}
}
}
This it my code for waiting text to be seen in single element by xpath with 1 results, not in list (xpath for more than 1 element)
public static void getWebElementByXpathWithWaitTextToBeSeen(String xpath,String text)
{
WebDriver driver2 = WebDriverMgr.getDriver();
// driver2.manage().timeouts().implicitlyWait(IMPLICIT_WAITE, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver2,EXPLICIT_WAITE);
wait.until(ExpectedConditions.textToBePresentInElementLocated(By.xpath(xpath),text));
}
How I can wait until text exists in web elements list? and it will refresh the list every time ?
p.s I use sleep it will work however I want code without hard coded sleep
regards
Let me clarify the preconditions first and please correct me if I am wrong:
You have 2 identical web-elements on page that represent 2 drop-downs.
Each of them can generate N web-elements which are all identical in scope of the whole document.
The issue is: when you get all the drop-down options, there is no way to identify from which drop-down they are.
Based on given amount of information I may offer you to start from finding both drop-down elements first, and keeping references to them till you have done all your tests with them.
In this case you will be able to find not all the options, but options that are children of specific drop-down, e.g. using
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#visibilityOfNestedElementsLocatedBy-org.openqa.selenium.WebElement-org.openqa.selenium.By-
Summarizing - find both drop-downs first, and then look for the values not only by xpath, but xpath + parent dropdown.
Related
Not able to iterate through WebElement List
Hi
I am doing some action on https://www.makemytrip.com/ under Departure. When click on Departure, it will show calendar of two months.
I am able to get two webElements with same xpath as mentioned below, now I want to go one by one, and getText() to match with user month name.
List<WebElement> month_list= driver.findElements(By.xpath("//div[#class='DayPicker-Month']"));
ListIterator<WebElement> listIter= month_list.listIterator();
while(listIter.hasNext()) {
WebElement elem= listIter.next();
System.out.println(elem.findElement(By.xpath("//div[#class='DayPicker-Caption']/div")).getText());
}
But every time, it is reporting same text :
July 2019
July 2019
However, I am expecting it should report :
July 2019
August 2019
Please guide me how can I perform anything on each element one by one.
You should try using . instead of / in you second xpath as below :-
System.out.println(elem.findElement(By.xpath("./div[#class='DayPicker-Caption']/div")).getText());
Absolute vs relative XPaths (/ vs .)
/ introduces an absolute location path, starting at the root of the document.
. introduces a relative location path, starting at the context node.
you can make use of foreach loop. Try the below code
for(WebElement monthName: month_list)
System.out.println(monthName.getText())
P.S. I doubt your Xpath ,the xpath which you wrote is the entire month calendar(that is the month name , the dates , the prices on each dates so its the entire div that you have picked)
Kindly try
List<WebElement> month_list= driver.findElements(By.xpath("//div[#class='DayPicker-Caption']"));
You can Try using,
List<WebElement> monthname= driver.findElements(By.xpath("//div[#class='DayPicker-Caption']"));
After Storing in List of Webelements you can use different kind of for Loops for getting the text.But the best preference is forEach Loop and for Iterative Loop.
forEach Loop:
for(WebElement months: monthname)
{
System.out.println(months.getText())
}
General forLoop
int length= monthname.size();
for (int i = 0; i<length; i++)
{
String name = monthname.get(i);
System.out.println(name);
}
PS: But The Best Preference is to go with forEachLoop Rather than General For Loop.
I'm creating a simple script to visit priceline.com and then searching "N" under Departing Flights and selecting New York City (NYC) from the dropdown list.
My code successfully types into the search bar but is still unable to find the dynamic dropdown with all the relevant results. I am not sure why.
// Clicks on "Departing from?" textbox and clears it before typing 'N'
driver.findElement(By.id("flight-departure-airport0")).click();
driver.findElement(By.id("flight-departure-airport0")).clear();
driver.findElement(By.id("flight-departure-airport0")).sendKeys("N");
// Store all dynamic search results into a list
List<WebElement> departureDropdown = driver.findElements(By.id("//*['flight-departure-airport0-dropdown']/div/div/div"));
System.out.println("List: "+departureDropdown);
Expected:
I expected departureDropdown to have a length of 9 with various airports. (Nadi, New York City, Nagasaki, etc) and expect departureDropdown[i] to return one of the city names in plain text.
Actual:
My code is stuck at the list initialization. departureDropdown is empty.
You have used By.id but you have created xPath.
Try with below xPath
List<WebElement> departureDropdown = driver.findElements(By.xPath("//div[#id='flight-departure-airport0-dropdown']//div[#role='option']"));
I have a CellTable with Pagination that is fed by a ListDataProvider. I set the page size to 5 and the expectation is that when there are more than multiples of 5 rows in ListDataProvider, the page numbers get incremented, and vice-versa. I have Add and Delete buttons that can be used to add and delete cell rows.
The problem is that Pagination adds and deletes pages at the wrong ListDataProvider size. For example, since the page size is 5, I'm expecting that when I add the 6th row to the table, the page size gets incremented. However, the page size is being incremented when the 7th row is added instead of the 6th.
Page not incremented with 6th entry -
Page incremented with 7th entry -
The issue is the same when deleting entries too. The page is updated when row size is down to 4 instead of 5. The issue does not persist if I refresh the page though. As in, when I add the 6th entry and refresh the page, the page number gets incremented as expected, and vice-versa when deleting.
I tried debugging this but couldn't figure out why this is happening. What am I doing wrong here? My code -
#UiField(provided=true) CellTable<MyClass> myTable = new CellTable<MyClass>();
final ListDataProvider<MyClass> myProvider = new ListDataProvider<MyClass>();
final SingleSelectionModel<MyClass> selectionModel = new SingleSelectionModel<MyClass>();
#UiField(provided=true) Pagination pagination = new Pagination(PaginationSize.SMALL);
SimplePager pager;
myProvider.addDataDisplay(myTable);
// create and add columns
createPagination();
private void createPagination() {
myTable.setSelectionModel(selectionModel);
pager = new SimplePager(TextLocation.CENTER, ((SimplePager.Resources)GWT.create(SimplePager.Resources.class)), false, 0, false);
pager.setRangeLimited(false);
pager.setDisplay(myTable);
pager.setPageSize(5);
pagination.rebuild(pager);
}
I'm also calling the createPagination() method in the onSuccess() methods for the add and delete functions.
The .ui.xml for the CellTable and Pagination -
<bc:CellTable ui:field="myTable" striped="true" bordered="true" width="800px" styleName="{style.myTableStyle}"/>
<b:Pagination ui:field="pagination" />
Adam's comment helped me debug the issue.
After adding or removing data, I needed to flush the ListDataProvider so that the changes take place immediately instead of waiting until the end of the event loop -
myProvider.flush();
A query is executed from within a facade to generate the report data. The query is correctly grouping data as follows: one row with A=351 (the one with B=757), rows with A=352 (B=523/535/etc.), and so on.
If the first row appearing in the page has A=350, then the second has a value diferente from 350 (e.g. 351), the "351" header will be displayed in the next page (only if there are enough 351 rows to reach another page, of course).
The 2nd and 3rd rows should not be inside 351 group, but inside another group called 352. But this behavior is not always happening for other pages. In this case, both descriptions are equal, but still 352 is being displayed on page 11.
Is it a bug in JasperReports?
I used to do a programmatic sort instead of SQL GROUP BY, as follows, and it didn't change anything:
Collections.sort(Reports.LIST,
(Comparator<MyObject>) new Comparator<MyObject>() {
public int compare(MyObject o1, MyObject o2) {
if (o1.getA().compareTo(o2.getA()) == 0) {
return o1.getB().compareTo(o2.getB());
} else {
return o1.getA().compareTo(o2.getA());
}
}
}
);
EDIT: Found out it happens in this specific case wherever the row is located (the 352 one is the last one in this page):
The Group Expression option has only the description, not the number; so, when the descriptions were equal for same number, it didn't separate the rows.
Steps:
Open iReport and your file;
Go to the Report Inspector (the left pane)
Click on the desired Group Header and open the Properties pane (right side)
Under the last section Group properties, type the correct Group Expression.
I want to retrieve a title from a div, a start hour and an end hour all of that from a big div called day and inside another div called event
I need to had these items to a list but right now i'am stuck here because it can't retrieve my 3 elements.
Document doc = Jsoup.connect("http://terry.gonguet.com/cal/?g=tp11").get();
Elements days = doc.select("div[class=day]");
Elements event = doc.select("div[class=event]");
for(Element day : days)
{
System.out.println(" : " + day.text());
for(Element ev : event)
{
Element title = ev.select("div[class=title]").first();
Element starthour = ev.select("div[class=bub right top]").first();
Element endhour = ev.select("div[class=bub right bottom]").first();
System.out.println(title.text()+starthour.text()+endhour.text());
}
}
None of there is no div in that document which have only day as class argument. They all have day class combined with another class which prevents div[class=day] from finding such div. Same problem applies to div[class=event] selector.
To solve it use CSS query syntax in which . operator is used to describe class attribute
(hint: if you want to select element which has few classes you can use element.class1.class2).
So instead of
select("div[class=day]");
select("div[class=event]");
use
select("div.day");
select("div.event");
Also instead of
ev.select("div[class=bub right top]");
ev.select("div[class=bub right bottom]");
you could try using
ev.select("div.bub.right.top");
ev.select("div.bub.right.bottom]");
This will allow you to find div which has all these classes (even if they are not in same order or there are more classes then mentioned in selector).