Recently, I found myself facing a seemingly simple task: filling in an HTML input of type Date
using Selenium and Selenide. While my experience was with Selenium, I suspect the challenges I encountered would be similar if I were using Cypress or other testing frameworks.
The Standard Approach: $(bySelector).setValue(theNewValue)
In most cases, the straightforward approach of using Selenide’s setValue
method works like a charm:
$(bySelector).setValue(theNewValue);
However, I hit a roadblock when Firefox decided to play hard to get. Firefox presents a neat calendar popup for the Date
input, but the calendar itself is not part of the web page’s source code. If you inspect the page source, you’ll only find <input type="date">
and nothing more.
Thinking Outside the Box: Hacking the Calendar Popup
In my desperation, I considered trying to hack Firefox’s calendar popup by displaying it and clicking the appropriate date. I even thought about using Java’s Robot
class and mousePress
function. But let’s face it: that approach would be error-prone, a maintenance nightmare, and wouldn’t impress any of our other beloved browsers.
Exploring Alternatives: From Selenide to JavaScript
At this point, I decided to abandon the Selenide/Java route and dive deeper into the underlying technologies. I transitioned from Selenide to Selenium and eventually found myself delving into JavaScript.
Initially, I thought I could quickly whip up a dirty script to find a JavaScript variable and inject my value directly. However, I quickly realized that this wouldn’t work with React. Once again, I was forced to abandon my favorite shortcuts and follow best practices for simulating events on the input element.
The Final Solution: Executing JavaScript with Selenide
After much trial and error, I came up with a solution that involved executing JavaScript with Selenium. Here’s the code snippet that finally did the trick:
Selenide.webdriver().driver().executeJavaScript(
"var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\").set;"
+ "nativeInputValueSetter.call(arguments[0], arguments[1]);"
+ "var ev2 = new Event('change', { bubbles: true});"
+ "arguments[0].dispatchEvent(ev2);"
, input, formattedDate);
“Dirty Shortcuts” conclusion
In conclusion, navigating the complexities of HTML Date
input across different browsers and testing frameworks presented its fair share of challenges. From initially relying on Selenide’s setValue
method to exploring the JavaScript and ultimately executing custom scripts, it is a journey of trial and error. While shortcuts can be tempting, following best practices often proves to be the most reliable approach in the long run.