user-event icon indicating copy to clipboard operation
user-event copied to clipboard

`userEvent.type` and `userEvent.paste` set incorrect time to `<input type="time">`

Open samulisuomi opened this issue 3 years ago • 5 comments

Reproduction example

https://codesandbox.io/s/dreamy-kirch-3wpvc8

Prerequisites

  1. Render an <input type="time"> element (doesn't seem to matter if step, min or max are defined or not)
  2. Try to set that input's value with userEvent.type(thatInput, '12:34:56')

Expected behavior

The value should be set to "12:34:56".

Actual behavior

The value is set to "12:59" (which in my Chrome gets rendered as 12.59.00)

User-event version

14.4.3

(I did test many versions in the Codesandbox all the way down to 12.8.3 and the same bug appeared)

Environment

Browser locale:

> navigator.languages[0]
'en-US'
> new Date().toLocaleDateString()
'12/23/2022'
> new Date().toLocaleTimeString()
'12:13:57 PM'

(these are the same in the tests and the real browser)

In the macOS Language & Region settings I tried both United States and Finland as my region. It does change the appearance of the time input but otherwise the behavior is exactly the same.

Additional context

  • An example test: https://codesandbox.io/s/dreamy-kirch-3wpvc8?file=/src/Foo.test.tsx
  • The component also allows you to test triggering userEvent.type in the real browser: https://codesandbox.io/s/dreamy-kirch-3wpvc8?file=/src/Foo.tsx
    • I originally encountered this problem in our test suite but also wanted to double-check if the behavior was the same in the real browser. Seems like so.

Here's how the component renders for me:

https://user-images.githubusercontent.com/3490745/209317238-b2c63bc4-ab51-4a1b-9d3f-254fdf9b3593.mov

  • If I switch my macOS Region to United States (the screen recording is on Finland), the .s are replaced with :s but otherwise the behavior is the same.
  • Using or not using const user = await userEvent.setup() doesn't seem to make a difference.
  • If I change "12:34:56" in userEvent.type(timeInput, "12:34:56") to any of these values, there is still always the issue of the minutes populating incorrectly to 59:
    • "12.34.56"
    • "123456"
    • "01:23:45"
    • "012345"
  • Chrome, Safari and Firefox all behave the same, at least on mac.

I'm totally prepared that I'm just using the lib wrong but at least the current behavior is very surprising. I also did read a few of the older time input related issues and assumed it should now work with userEvent.type (because I didn't find any other relevant issues after https://github.com/testing-library/user-event/issues/484).

Edit:

I also noticed the same issue persists if I replace .type with .click + .paste:

await userEvent.clear(timeInput);
await userEvent.click(timeInput);
await userEvent.paste("12:34:56");

https://codesandbox.io/s/dreamy-kirch-3wpvc8-click-and-paste-v4wn2e?file=/src/Foo.tsx

Seems like both .type and .paste hit this function which probably explains why the behavior is shared in both: https://github.com/testing-library/user-event/blob/1aa2027e5ec445ab413808556efa7763b65053d3/src/utils/edit/timeValue.ts#L3

I'll edit the title.

samulisuomi avatar Dec 23 '22 10:12 samulisuomi

The browser implementations changed a lot since this feature was added. As the Chrome implementation has been copied by other major browser vendors, I think we could mimic that. Some aspects of time input are still a mess in browsers though.

ph-fritsche avatar Dec 23 '22 11:12 ph-fritsche

Shouldn't this still count as a bug if the latest-ish Chrome, Firefox and Safari all behave the same?

Also do you happen to know any workarounds? fireEvent.change doesn't seem to work either (nothing happens). That also seems to hit buildTimeValue anyway.

samulisuomi avatar Dec 23 '22 11:12 samulisuomi

"accuracy" does not mean it's correct or that we shouldn't fix it. Just that it's more an unimplemented aspect than an outright wrong behavior violating some specs.

ph-fritsche avatar Dec 23 '22 12:12 ph-fritsche

Also do you happen to know any workarounds? fireEvent.change doesn't seem to work either (nothing happens). That also seems to hit buildTimeValue anyway.

Your codesandbox wasn't using fireEvent correctly. It works if you do this:

fireEvent.change(timeInput, { target: { value: "12:34:56" } });

spudly avatar Jan 06 '23 20:01 spudly

Your codesandbox wasn't using fireEvent correctly. It works if you do this:

fireEvent.change(timeInput, { target: { value: "12:34:56" } });

Woops, thank you @spudly!

samulisuomi avatar Jan 09 '23 14:01 samulisuomi