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

Arrow keys on radio buttons are backwards

Open joshferrell opened this issue 1 year ago • 0 comments

Reproduction example

https://codesandbox.io/p/devbox/github/joshferrell/user-event-radio-demo/tree/main/

Prerequisites

Create a series of radio inputs

<label><input type="radio" name="group" value="a" />A</label>
<label><input type="radio" name="group" value="d" />D</label>
<label><input type="radio" name="group" value="e" />E</label>

Create a test that confirms radio behavior using the userEvent keyboard function

describe('Radio implementation', () => {
    test.each([
      {
        name: "per [ArrowDown]",
        focus: 'A',
        key: "[ArrowDown]",
        expectedTarget: 'D',
      },
      {
        name: "per [ArrowLeft]",
        focus: 'D',
        key: "[ArrowLeft]",
        expectedTarget: 'A',
      },
      {
        name: "per [ArrowRight]",
        focus: 'A',
        key: "[ArrowRight]",
        expectedTarget: 'D',
      },
      {
        name: "per [ArrowUp]",
        focus: 'D',
        key: "[ArrowUp]",
        expectedTarget: 'A',
      },
      {
        name: "forward around the corner",
        focus: 'E',
        key: "[ArrowRight]",
        expectedTarget: 'A',
      },
      {
        name: "backward around the corner",
        focus: 'A',
        key: "[ArrowUp]",
        expectedTarget: 'E',
      },
    ])('$name', async ({ focus, key, expectedTarget }) => {
      const user = userEvent.setup()
        render(<App />)
        screen.getByLabelText(focus).focus()
        await user.keyboard(key)
        expect(screen.getByLabelText(expectedTarget)).toHaveFocus()
    })
})

Expected behavior

Behavior

Arrow Right

If A is selected and ArrowRight is pressed, D should be selected If E is selected and ArrowRight is pressed, A should be selected

Arrow Down

If A is selected and ArrowDown is pressed, D should be selected If E is selected and ArrowDown is pressed, A should be selected

Arrow Left

If D is selected and ArrowLeft is pressed, A should be selected If A is selected and ArrowLeft is pressed, E should be selected

Arrow Up

If D is selected and ArrowUp is pressed, A should be selected If A is selected and ArrowUp is pressed, E should be selected

Actual behavior

Behavior

Arrow Right

If A is selected and ArrowRight is pressed, E is selected If E is selected and ArrowRight is pressed, D is selected

Arrow Down

If A is selected and ArrowDown is pressed, D is selected If E is selected and ArrowDown is pressed, A is selected

Arrow Left

If D is selected and ArrowLeft is pressed, E is selected If A is selected and ArrowLeft is pressed, D is selected

Arrow Up

If D is selected and ArrowUp is pressed, A is selected If A is selected and ArrowUp is pressed, E is selected

User-event version

14.5.2

Environment

Testing Library framework: @testing-library/[email protected] and @testing-library/user-event:14.5.2

JS framework: [email protected]

Test environment: [email protected] Also ran in the user-event test suite and had the same issue

DOM implementation: [email protected]

Additional context

There are two issues with the current implementation of the keyboard event and handling radios.

  1. The walk radio function does not quit the for loop if it finds the next element
  2. Arrow Down and Arrow Up directions are inverted.

joshferrell avatar Feb 27 '24 04:02 joshferrell