Set a Date in a Date Picker
Type into the input when allowed, set the value directly when it is read-only, or drive the calendar widget when nothing else works.
Problem
Date pickers come in three kinds: a native <input type="date">, a text input with a calendar popup, and a read-only field that only accepts clicks in a calendar. Each needs a different technique, and clicking through months is slow and fragile.
Solution
Prefer typing. Fall back to setting the value and dispatching the events the framework listens for. Drive the calendar only for widgets that ignore both.
WebElement date = driver.findElement(By.id("delivery-date"));JavascriptExecutor js = (JavascriptExecutor) driver;
// 1. Native input[type=date]: type in the browser's locale format (Chrome: mmddyyyy keystrokes)// or set the ISO value directly, which is what the input stores.js.executeScript("arguments[0].value = '2026-10-15'; arguments[0].dispatchEvent(new Event('change', {bubbles: true}));", date);
// 2. Text input with popup: clear, type, press Escape to close the popupdate.clear();date.sendKeys("15/10/2026", Keys.ESCAPE);
// 3. Read-only input driven by a React/Vue calendar: set the value through the framework's setterjs.executeScript(""" const el = arguments[0]; const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; setter.call(el, arguments[1]); el.dispatchEvent(new Event('input', {bubbles: true})); el.dispatchEvent(new Event('change', {bubbles: true}));""", date, "15/10/2026");date = driver.find_element(By.ID, "delivery-date")
# 1. Native input[type=date]: set the ISO value it storesdriver.execute_script( "arguments[0].value = '2026-10-15'; arguments[0].dispatchEvent(new Event('change', {bubbles: true}));", date)
# 2. Text input with popupdate.clear()date.send_keys("15/10/2026", Keys.ESCAPE)
# 3. Read-only input driven by React/Vue: use the native setter so the framework noticesdriver.execute_script(""" const el = arguments[0]; const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; setter.call(el, arguments[1]); el.dispatchEvent(new Event('input', {bubbles: true})); el.dispatchEvent(new Event('change', {bubbles: true}));""", date, "15/10/2026")const date = await driver.findElement(By.id('delivery-date'));
// 1. Nativeawait driver.executeScript("arguments[0].value = '2026-10-15'; arguments[0].dispatchEvent(new Event('change', {bubbles: true}));", date);
// 2. Text input with popupawait date.clear();await date.sendKeys('15/10/2026', Key.ESCAPE);
// 3. Framework-controlled read-only inputawait driver.executeScript(`const el = arguments[0];const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;setter.call(el, arguments[1]);el.dispatchEvent(new Event('input', {bubbles: true}));el.dispatchEvent(new Event('change', {bubbles: true}));`, date, '15/10/2026');var date = driver.FindElement(By.Id("delivery-date"));var js = (IJavaScriptExecutor)driver;
// 1. Nativejs.ExecuteScript("arguments[0].value = '2026-10-15'; arguments[0].dispatchEvent(new Event('change', {bubbles: true}));", date);
// 2. Text input with popupdate.Clear();date.SendKeys("15/10/2026" + Keys.Escape);
// 3. Framework-controlled read-only inputjs.ExecuteScript(@" const el = arguments[0]; const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; setter.call(el, arguments[1]); el.dispatchEvent(new Event('input', {bubbles: true})); el.dispatchEvent(new Event('change', {bubbles: true}));", date, "15/10/2026");Why It Works
Typing exercises the real input path. Setting .value skips it, so you must dispatch input and change yourself. React in particular tracks the value through the native property setter; assigning el.value directly is swallowed, which is why strategy 3 calls the prototype setter.
Gotchas
- Native date inputs store ISO (
yyyy-mm-dd) regardless of display format; typing uses the locale format. - Strategy 3 bypasses the calendar’s own validation (min/max dates, disabled days). Assert the app accepted the value afterwards.
- Only drive the calendar (clicking month arrows and day cells) when the picker has business logic in those clicks, and then compute the number of “next month” clicks from the current date rather than hard-coding it.