Automate date-picker based on month text - selenium

I am trying to automate date-picker on a page, and I want to hit the previous/next button until I reach a desired month in the calendar. But the button does not click, only once it clicks and test cases passes without going any further. Current month is September it clicks and goes to August and the test case passes without being clicked further, lets say if I wish to click till January it does not happen
#FindBy(css=".ui-datepicker-month") //month displayed in date-picker
WebElement labelCalendarMonth;
#FindBy(id="txtStartDate_calendarButton") // button to open the date-picker
WebElement searchStartDateButton;
#FindBy(xpath="//a[#title='Prev']") // previous button in date-picker
WebElement calendarSearchStartDatePreviousBtn;
public void selectStartMonth(WebElement ele, String value) {
if(!labelCalendarMonth.getText().equals(value))
{
ele.click();
}
}
public void clickCalendarSearchStartDatePreviousBtn() throws InterruptedException
{
selectStartMonth(calendarSearchStartDatePreviousBtn, "January");
}
#Test()
public void testAddResourceSchedule() throws InterruptedException
{
resourceSchedulePage.clickCalendarSearchStartDatePreviousBtn();
}

I have worked with https://www.booking.com/ and they do have date picker, so just to give you little head up how do we handle this situation where we have to click till certain amount of time, for e.g: till Jan in your case, we can do the following :-
It's kind of obvious that we have to have infinite while loop.
while(true){
if(driver.findElement(By.xpath("month xpath which you wanna selct ")).getText().equalsIgnoreCase(month) && driver.findElement(By.xpath("year xpath that you wanna select")).getText().equalsIgnoreCase(year)) {
break;
}
else {
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("next botton xpath here, which is on date picker."))).click();
Thread.sleep(500);
}
}
Basically, the thing is you need to define month and year in advance in a string format. before running this code.
I have written a good solution here as well where I am clicking till end of Nov-2022

Related

How do i tell Selenium to wait until report get ready to download

After the selection of date from the date picker,clicking on 'View Report' button and then its take a time to generate the report and then it download the report.. My following code is working without an error but how do i use fluent wait instead of Thread.sleep(20000),(last line in below code). For fluent or explicit wait i ask to wait for what condition? Also wanted to verify whether the file has been downloaded or not with assertion. Any help will be appreciated.
public void generateReport() throws Exception {
clickDatePicker.click();
log.info("Select the Date from datepicker");
Select month = new Select(selectMonth);
month.selectByValue("0");
log.info("Selected the Month from datepicker");
Select year = new Select(selectYear);
year.selectByValue("2020");
log.info("Selected the Year from datepicker");
act.moveToElement(selectDate).click().build().perform();
buttonViewReport.click();
log.info("Finally clicked on Get Report button ");
Thread.sleep(20000);
}
Check the below method, which will make sure the script will wait until the download is started (for max of the minutes specified in the method call)
public void waitUntilDownloadStarted(WebDriver driver, int maxWaitTimeInMinutes) throws InterruptedException {
// Store the current window handle
String mainWindow = driver.getWindowHandle();
// open a new tab
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.open()");
// switch to new tab
// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// navigate to chrome downloads
driver.get("chrome://downloads");
Instant startTime = Instant.now();
int elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
// wait until the download is started
while ( (Long)js.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelectorAll('#downloadsList downloads-item').length") == 0) {
Thread.sleep(1000);
elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
if (elapsedTime > maxWaitTimeInMinutes) {
break;
}
}
// close the downloads tab2
driver.close();
// switch back to main window
driver.switchTo().window(mainWindow);
}
Tested as below.
waitUntilDownloadStarted(driver, 10);
Does anything appears like that your download has been generated? or inspect any change in HTML. then you can use the following code to wait until change appears.
WebDriverWait wait=new WebDriverWait(driver, 20000);
wait.until(ExpectedConditions.numberOfElementsToBe(locator, number));
where 20000 is time in milliseconds

stale element exception : click on report link in page then back button and so on

AS shown in the image : i want to click on each link one by one , on clicking :window does not gets change but it refresh.
clicking in the report link navigate to the next page, where clicking on back link it navigates back to the same page.
once it take back to the same page , locator no longer identify the next report link & throws stale element exception
public void getreports(String reportname) throws Exception
List<WebElement> li=driver.findElements(By.xpath(".//tbody/tr/th/following::
tr/td//div/a"));
for(WebElement e: li) {
if(reportname.equalsIgnoreCase(e.getText())) {
utilities.wait_control(e);
e.click();
break;
}
else if(reportname.equalsIgnoreCase("all"))
{
utilities.wait_control(e);
e.click();
NetReports ld = PageFactory.initElements(driver, NetReports .class);
ld.Netsubcategoryreport_backbutton.click();
Thread.sleep(2000);
} }
I think you just need a small adjustment to your loop:
String selector = ".//tbody/tr/th/following::tr/td//div/a";
List<WebElement> li=driver.findElements(By.xpath(selector));
for (int i = 0; i < li.length; i++) {
li=driver.findElements(By.xpath(selector));
WebElement e = li.get(i);
//Rest of your logic goes here
}
StaleElementReferenceException -
As the name suggests this exception occurs when the element stale, which means the element reference on which you are trying to take a action upon is no longer available on the page or has changed. 
To avoid this exception, try to find the element as and when you need to
take an action upon it rather than getting the element at some point of code
and then reusing it at different places.

WebDriver - Switch to new Window and selecting dropdown is not working in IE

Trying to switch to new window tab and then selecting a item from dropdown list is not working..
public static void handleNewTabWindow() {
driver.findElement(By.xpath(".//img[#src='/images/buttons/gl_upload.gif']")).click();
String Parent_Window = driver.getWindowHandle();
for (String Child_Window : driver.getWindowHandles()) {
driver.switchTo().window(Child_Window);
WebElement dropdown = getWhenVisible(By.xpath(".//select[#name='UPLOAD_ORG_ID']"));
dropdown.click();
getWhenVisible(By.xpath(".//option[contains(text(), 'CI Borrower')]")).click();
}
driver.switchTo().window(Parent_Window);
driver.close();
}
You must wait until a new window will appear on the screen before switching to it. Your code is trying to switch immediately after clicking on the button, in a couple of miliseconds - the browser is not so quick, you must wait a couple of seconds or so.
A not very elegant, but a quick solution is to introduce a fixed Thread.sleep( 2000 ); here:
driver.findElement(By.xpath(".//img[#src='/images/buttons/gl_upload.gif']")).click();
Thread.sleep( 2000 );
String Parent_Window = driver.getWindowHandle();
but this doesn't work very well.
A better solution is to implement a method that will wait until a new window appears on the screen (but no longer than some fixed timeout - for example 30-60 seconds). For example one of the most used method in our project is a method that waits for a window with a given title, something like this (code skeleton):
void waitForWindowWithTitleAndSwitchToIt( String windowTitle, int timeoutInSeconds ){
....
while( timeout-not-expired ){
handles = driver.getWindowHandles():
for( String handle: handles ){
driver.switchTo.window( handle );
if( driver.getTitle().contains( windowTitle ) ){
// found a window with a given title
return;
}
}
sleep( for a 1-2 seconds );
// and try again
}
throw new TimeoutException(
String.format("A browser window named %s doesn't appear on the screen", windowTitle )
);
}
We have implemented a couple of such methods in our project, which wait for a new window using different criteria: wait for window with a given exact title, for a window which a title that contains a given substring, for a window with a given string in the page source, for a window with a given (sub)string in the url, etc. etc.

Selenium : Handle a window that popups up randomly

We have a feature that collects customer feedback. For this , when the user logs out , a window pops up up randomly - not every time for every customer.
I want to handle this in my automation code.
Currently, at the log out, I'm expecting a window and switching to it and that code is failing when the popup window doesn't show up.
What's the best way to handle this .
This is what I have so far ...
public static void waitForNumberOfWindowsToEqual(final int numberOfWindows) {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return (driver.getWindowHandles().size() == numberOfWindows);
}
};
WebDriverWait wait = new WebDriverWait(driver, BrowserFactory.explicitWait);
wait.until(expectation);
}
I would handle the absence of popup window with a try/catch. Here is an example:
try {
WebDriverWait winwait = new WebDriverWait(driver, 3);
String mainWindow = driver.getWindowHandle();
// wait for 2 windows and get the handles
Set<String> handles = winwait.until((WebDriver drv) -> {
Set<String> items = drv.getWindowHandles();
return items.size() == 2 ? items : null;
});
// set the context on the last opened window
handles.remove(mainWindow);
driver.switchTo().window(handles.iterator().next());
// close the window
driver.close();
// set the context back to the main window
driver.switchTo().window(mainWindow);
} catch (TimeoutException ex) {
System.out.println("No window present within 3 seconds");
}
If possible, the ideal thing to do would be to have a look through the source to work out whether the popup window will appear, however if this isn't achievable you could take the following approach:
// Get the number of windows open before clicking the log out button.
int numberOfWindowsBeforeLogOut = driver.getWindowHandles().size();
// Click the log out button.
logOutButton.click();
// Check how many windows are open after clicking the log out button.
int numberOfWindowsAfterLogOut = driver.getWindowHandles().size();
// Now compare the number of windows before and after clicking the log out
// button in a condition statement.
if (numberOfWindowsBeforeLogOut < numberOfWindowsAfterLogOut) {
// If there is a new window available, switch to it.
driver.switchTo().window(titleOrWindowHandle);
}
In case you don't get the required window, the code will throw a TimeoutException. So, put wait.until(expectation) inside a try block and catch the exception. In code,
try {
wait.until(expectation);
} catch (TimeoutException ex) {
System.out.println("Nowindow This Time");
}

Screenscraping a Datepicker with Scrapy + Selenium

So i need to scrap a page like this for example or this and i am using Scrapy + Seleninum to interact with a datepicker calendar.
Basically i need to check for the availabilities of the rooms for each day in a month for example, so my idea was trying to click the not disabled links/dates on the datepicker and check if an error message appears or not for me to know if its available or not.
I have no idea if this is the proper way or even how to do this with this tools. I have been playing around with them but still looks like i am far from a final solution.
Does anyone know how i can tackle this or even provide the code for me to achieve this?
Hi please find the answer below
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get("https://www.airbnb.pt/rooms/516301?check_in=2016-04-14&guests=1&check_out=2016-04-17");
// selecting firstdate picker -- check in
driver.findElement(By.xpath("//*[#class='col-sm-6']/input")).click();
// note calendar is not completely visible hence to make it visible
// scroll a little bit down
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,200)");
// take all calendar dates inside the list
// here i have update my code to skip stale element exception
List<WebElement> alldates = driver.findElements(By.xpath("//*[#class='ui-datepicker-calendar']/tbody/tr/td/a[contains(#class, 'ui-state-default')]"));
System.out.println("Size is : "+ alldates.size());
// suppose you want to select 27 form the all dates
// keeping it as a parameter
String dateToBeSelected = "19"; // check in
for(int i=0;i<alldates.size();i++){
alldates = driver.findElements(By.xpath("//*[#class='ui-state-default']"));
System.out.println("dates is : " + alldates.get(i).getText());
// selects a check-in date
if( alldates.get(i).getText().equals(dateToBeSelected)){
alldates.get(i).click();
break;
}
}
// on selection of Checkin date check out calender automatically pop ups
System.out.println("--------------------------");
String datetobeselected = "27";
for(int i=0;i<alldates.size();i++){
alldates = driver.findElements(By.xpath("//*[#class='ui-state-default']"));
System.out.println("dates is : " + alldates.get(i).getText());
// selects a check-in date
if( alldates.get(i).getText().equals(datetobeselected)){
alldates.get(i).click();
break;
}
}
// actually after calendar selection whatever text is shown in red color
// i am not sure what is it (sorry only English)
// identify the text with red color is present or not
boolean errorMsg = driver.findElement(By.xpath("//*[#class='panel-body panel-light']/div[2]/p")).isDisplayed();
if(errorMsg){
System.out.println("error msg is displayed");
}else{
System.out.println("error msg is not - displayed");
}
Hope this helps you also note this above example takes check-in and checkout date as parameter if you want code to take non disabled date automatically please feel free to ask i will update my answer.