Issue encountered while setting date

I am entering date using the code below:

import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
browserName=DriverFactory.getExecutedBrowser().getName()
if (browserName==“FIREFOX_DRIVER”){
WebUI.setText(findTestObject(‘dateField’), ‘2017-10-31’)
}
else
{
WebUI.sendKeys(findTestObject(‘Object Repository/Test Objects/Pages/Page_Dashboard - Jobsparks/Job/input_Start Time_datecalendar’), Keys.chord(‘03/09/2019’, Keys.ENTER, Keys.TAB))
}

Script is getting executed successfully but no date is getting selected.

Is there any other way to select date from datepicker?

HTML:

I have had the same issue - I have reverted to just setting the date without using the date picker. I did this by just SetText() for the date input element.

If this doesnt work i have seen alot use javascript - something like this

Execute JavaScript | | document.getElementById(“edit-sales-funnel-widget-field-graduation-month-and-year-und-0-value-date”).value = “08/2017”;

While I would agree, it’s often easier to just set the text of the date field rather than using the datepicker widget, if the purpose of the test is to validate that the datepicker itself is working properly, then you obviously can’t resort to this in good faith.

If it’s a requirement of your test case that you work with the datepicker, the way I usually handle this is to create a Custom Keyword that handles all of the widgetry for the datepicker, and just call these methods from my test case. That way, if there are multiple datepickers of the same type in your app (or other apps), you have encapsulated all of that functionality (Page Object Model to the rescue). We can walk through the details if this if you want to go that route.

That being said, based on the test code you’ve shown us, it looks like sending keys into the field is enough for your purposes. Usually what happens with fields like this is if you click or send keys to the field, the datepicker widget appears automatically, and doesn’t disappear until the field “loses focus”. A normal, manual user would probably just click somewhere else on the page to achieve this. To do this using katalon, give this a try:

WebUI.sendKeys(findTestObject('dateField'), Keys.chord(Keys.CONTROL, 'a'));
WebUI.sendKeys(findTestObject('dateField'), '03/09/2019');
WebUI.sendKeys(findTestObject('dateField'), Keys.ESCAPE);
1 Like

Would you mind sharing the custom keyword and one example with it?

Sure, but remember, the following is designed to handle my particular datepicker functionality, with my own coding conventions (in particular, I make heavy use of what I call “predicate-driven” xpathing), so it will absolutely not work for you as-is. That being said, you could follow the approach and do something similar for your widget:

One of our datepicker widgets looks like this:

image

Here’s the Page Object that encapsulates all of the functionality for it:

import org.openqa.selenium.By
import org.openqa.selenium.WebElement

import com.kms.katalon.core.util.KeywordUtil

import base.util.ElementUtil

public class DatePicker extends Page {

	public void clickPreviousMonthButton() {
		KeywordUtil.logInfo("Date Picker: Clicking previous month button");
		WebElement button = findElement(By.xpath(getPreviousMonthButtonXPath()), defaultTimeout);
		button.click();
	}

	public boolean isPreviousMonthButtonVisible() {
		boolean visible = isElementVisible(By.xpath(getPreviousMonthButtonXPath()), defaultTimeout);
		return visible;
	}

	public boolean isPreviousMonthButtonEnabled() {
		boolean enabled = isElementEnabled(By.xpath(getPreviousMonthButtonXPath()), defaultTimeout);
		return enabled;
	}

	public void clickNextMonthButton() {
		KeywordUtil.logInfo("Date Picker: Clicking next month button");
		WebElement button = findElement(By.xpath(getNextMonthButtonXPath()), defaultTimeout);
		button.click();
	}

	public boolean isNextMonthButtonVisible() {
		boolean visible = isElementVisible(By.xpath(getNextMonthButtonXPath()), defaultTimeout);
		return visible;
	}

	public boolean isNextMonthButtonEnabled() {
		boolean enabled = isElementEnabled(By.xpath(getNextMonthButtonXPath()), defaultTimeout);
		return enabled;
	}

	public void setMonth(final String month) {
		KeywordUtil.logInfo("Date Picker: Setting month to " + month);
		WebElement dropdown = findElement(By.xpath(getMonthDropdownXPath()), defaultTimeout);
		dropdown.click();
		WebElement option = findElement(By.xpath(getMonthXPath(getSingleMonthPredicate(month))), defaultTimeout);
		option.click();
	}

	public List<String> getMonths() {
		WebElement dropdown = findElement(By.xpath(getMonthDropdownXPath()), defaultTimeout);
		dropdown.click();
		List<WebElement> options = findElements(By.xpath(getMonthXPath("")), defaultTimeout);
		List<String> months = ElementUtil.getTextsFromElements(options, true);
		dropdown.click();
		return months;
	}

	public boolean isMonthDropdownVisible() {
		boolean visible = isElementVisible(By.xpath(getMonthDropdownXPath()), defaultTimeout);
		return visible;
	}

	public boolean isMonthDropdownEnabled() {
		boolean enabled = isElementEnabled(By.xpath(getMonthDropdownXPath()), defaultTimeout);
		return enabled;
	}

	public void setYear(final String year) {
		KeywordUtil.logInfo("Date Picker: Setting year to " + year);
		WebElement dropdown = findElement(By.xpath(getYearDropdownXPath()), defaultTimeout);
		dropdown.click();
		WebElement option = findElement(By.xpath(getYearXPath(getSingleYearPredicate(year))), defaultTimeout);
		option.click();
	}

	public List<String> getYears() {
		WebElement dropdown = findElement(By.xpath(getYearDropdownXPath()), defaultTimeout);
		dropdown.click();
		List<WebElement> options = findElements(By.xpath(getYearXPath("")), defaultTimeout);
		List<String> years = ElementUtil.getTextsFromElements(options, true);
		dropdown.click();
		return years;
	}

	public boolean isYearDropdownVisible() {
		boolean visible = isElementVisible(By.xpath(getYearDropdownXPath()), defaultTimeout);
		return visible;
	}

	public boolean isYearDropdownEnabled() {
		boolean enabled = isElementEnabled(By.xpath(getYearDropdownXPath()), defaultTimeout);
		return enabled;
	}

	public void clickDay(final String day) {
		KeywordUtil.logInfo("Date Picker: Clicking day " + day);
		WebElement element = findElement(By.xpath(getDayXPath(getSingleDayPredicate(day))), defaultTimeout);
		element.click();
	}

	public List<String> getDays() {
		List<WebElement> elements = findElements(By.xpath(getDayXPath("")), defaultTimeout);
		List<String> days = ElementUtil.getTextsFromElements(elements, true);
		return days;
	}

	public boolean isDayVisible(final String day) {
		boolean visible = isElementVisible(By.xpath(getDayXPath(getSingleDayPredicate(day))), defaultTimeout);
		return visible;
	}

	public boolean isDayEnabled(final String day) {
		boolean enabled = isElementEnabled(By.xpath(getDayXPath(getSingleDayPredicate(day))), defaultTimeout);
		return enabled;
	}

	public void clickTodayButton() {
		KeywordUtil.logInfo("Date Picker: Clicking 'Today' button");
		WebElement button = findElement(By.xpath(getTodayButtonXPath()), defaultTimeout);
		button.click();
	}

	public boolean isTodayButtonVisible() {
		boolean visible = isElementVisible(By.xpath(getTodayButtonXPath()), defaultTimeout);
		return visible;
	}

	public boolean isTodayButtonEnabled() {
		boolean enabled = isElementEnabled(By.xpath(getTodayButtonXPath()), defaultTimeout);
		return enabled;
	}

	// ***************** XPATHS *****************:
	public String getPreviousMonthButtonXPath() {
		return "//div[@class='react-datepicker']//button[contains(@class, 'previous')]";
	}

	public String getNextMonthButtonXPath() {
		return "//div[@class='react-datepicker']//button[contains(@class, 'next')]";
	}

	public String getMonthDropdownXPath() {
		return "//div[@class='react-datepicker']//div[contains(@class, 'month-read-view')]";
	}

	public String getMonthXPath(final String predicate) {
		return "//div[@class='react-datepicker']//div[contains(@class, month-option) " + predicate + "]";
	}

	public String getYearDropdownXPath() {
		return "//div[@class='react-datepicker']//div[contains(@class, 'year-read-view')]";
	}

	public String getYearXPath(final String predicate) {
		return "//div[@class='react-datepicker']//div[contains(@class, year-option) " + predicate + "]";
	}

	public String getDayXPath(final String predicate) {
		return "//div[@class='react-datepicker']//div[contains(@class, 'datepicker__week')]//div[@role='option' and not(contains(@class, 'outside-month')) " + predicate + "]"
	}

	public String getTodayButtonXPath() {
		return "//div[@class='react-datepicker']//div[contains(@class, 'today-button')]";
	}

	// ***************** PREDICATES *****************:
	public String getSingleMonthPredicate(final String month) {
		return "and text()='" + month + "' ";
	}

	public String getSingleYearPredicate(final String year) {
		return "and text()='" + year + "' ";
	}

	public String getSingleDayPredicate(final String day) {
		return "and text()='" + day + "' ";
	}
}

You would then call these methods as needed to manipulate the widget. For example, lets say I wanted to select the date of April 1, 2020, using the “next month” arrow to get to the month, the “year dropdown” to get to the year, and the actual calendar to select the day:

DatePicker datepicker = new Datepicker();
datepicker.clickNextMonthButton();
datepicker.setYear("2020");
datepicker.clickDay("1");
1 Like

Hi,

if field is readonly true, then change it as readonly false by javascript
then you are able to set date (string) to field without using datepicker

def y = WebUI.executeJavaScript("return document.getElementsByClassName('class-name')[0].readOnly=false;", null)
println ("DEBUG readOnly value y "+y)

Note! if you are using getElementsByClassName it returns list then have to use index [x]