-1

I'm automating a test using Selenium (Node.js) and trying to set a value for a datetime-local input. The UI visually shows the correct date/time, but when I inspect the element after driver.sleep(), the input has no value attribute at all. If I manually pick a date using the browser picker, then the value attribute appears. So Selenium is updating the UI, but the actual React state is not being updated.

React code:

<div>
  <label className="text-sm text-gray-600" htmlFor="start_time">
    Start Time
  </label>
  <input
    type="datetime-local"
    id="start_time"
    value={form.start_time}
    onChange={(e) => setForm({ ...form, start_time: e.target.value })}
    className="w-full border rounded px-3 py-2"
  />
</div>

Selenium code:

const startInput = await driver.findElement(
  By.xpath(
    "//label[contains(text(), 'Start Time')]/following-sibling::input[@type='datetime-local']"
  )
);

await driver.executeScript(
  "arguments[0].value = arguments[1]; arguments[0].dispatchEvent(new Event('input', { bubbles: true })); arguments[0].dispatchEvent(new Event('change', { bubbles: true }));",
  startInput,
  "2025-11-19T13:45"
);

Why is Selenium able to visually change the value, but React does not register the change?

3
  • 1
    I think some of the behavior depends on the browser. If I remember right, only choosing from the calendar will fire the change event. It's probably checking/validating the actual control when you synthetically generate the change event, and then canceling it. So I believe in certain browsers you won't ever have a change event until the calendar has been opened and a selection made. You might try just "arguments[0].value = arguments[1];" and then submit the form. Use the .submit() convenience method on the input. Ex: startInput.submit(); after waiting for script. Commented Nov 20 at 18:16
  • 1
    For my SPA's I usually invalidate typing and only allow arrowup and arrowdown in a type="date" input. (onKeyDown) Otherwise it doesn't seem to fire a change. (This pretty much forces the user to make a selection from the calendar...) Commented Nov 20 at 18:20
  • 1
    you might also try this without dispatchEvent(new Event('input'... and/or also waiting for return values for each step to make sure the events aren't being handled async when dispatched... Commented Nov 20 at 18:27

2 Answers 2

0

When you run:

arguments[0].value = arguments[1];

You are mutating the DOM directly, but React does not look at the DOM to decide state.

React only updates when the onChange event comes from a real user interaction, with the actual event properties it expects.

Selenium’s synthetic events don't trigger React’s internal “value tracker”, so React thinks:

“No change happened, keep using the old state value.”

That’s why the visual field shows your injected value, but the DOM + React state still have an empty value.

Sign up to request clarification or add additional context in comments.

Comments

0
Correct way: Set the value via React's native setter

React overrides the element’s value property internally.
You need to call the original setter so React’s “value tracker” updates.

Use this:

await driver.executeScript(`
  const input = arguments[0];
  const value = arguments[1];

  const nativeSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    "value"
  ).set;

  nativeSetter.call(input, value);

  input.dispatchEvent(new Event("input", { bubbles: true }));
  input.dispatchEvent(new Event("change", { bubbles: true }));
`, startInput, "

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.