Setting React element values directly from Selenium
I love Selenium, but there are a few things that it still handles poorly. Interacting with non-standard web native inputs is one of those items, for example color pickers, date inputs.
You can usually get around these by simply setting the value using the executeScript method. But this doesn’t work so easily if you are testing against React. This function will directly set an input’s value and trigger the React change event so state updates are made.
This is in TypeScript, but translates pretty easily to JavaScript.
export async function setReactElementValue(driver: WebDriver, element: WebElement, value: string): Promise<void> {
await driver.executeScript(`const valueSetter = Object.getOwnPropertyDescriptor(arguments[0], 'value').set;
const prototype = Object.getPrototypeOf(arguments[0]);
const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
if (valueSetter && valueSetter !== prototypeValueSetter) {
prototypeValueSetter.call(arguments[0], '${value}');
} else {
valueSetter.call(arguments[0], '${value}');
}
arguments[0].dispatchEvent(new Event('input', { bubbles: true }));`,
element,
);
}
Hopefully this saves someone time!
Thanks man! Really help, you save my day!
Thanks, Nick Korbel. I’m confirming that your method worked for me in C#. I’ve been struggling with this for months and enabling ReactTestUtils wasn’t an option.
“`
public void SetReactElementValue(By locator, string value){
string script = $@”
const valueSetter = Object.getOwnPropertyDescriptor(arguments[0], ‘value’).set;
const prototype = Object.getPrototypeOf(arguments[0]);
const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, ‘value’).set;
if (valueSetter && valueSetter !== prototypeValueSetter) {{
prototypeValueSetter.call(arguments[0], ‘{value}’);
}} else {{
valueSetter.call(arguments[0], ‘{value}’);
}}
arguments[0].dispatchEvent(new Event(‘input’, {{ bubbles: true }}));”;
_webDriver.ExecuteScript(script, _webDriver.FindElement(locator));
}
“`