mardi 19 novembre 2019

Testing with @testing-library/user-event to select multiple options doesn't send correct values in "onChange" callback?

A simple multiple select component:

import React from 'react'

type Props = {
  onSelectedValuesChange: (value: string[]) => void
}

export default function MultiSelect({onSelectedValuesChange}: Props) {

  function onSelectOptions(event: React.ChangeEvent<HTMLSelectElement>) {
    const selectedOptions = event.target.selectedOptions;
    const selectedValues = Array.from(selectedOptions).map((it) => it.value);
    console.log("### selected values: ", selectedValues);
    onSelectedValuesChange(selectedValues);
  }


  return <select multiple data-testid="select-multiple"
                 onChange={onSelectOptions} style=>
    <option data-testid="val1" value="1">1</option>
    <option data-testid="val2" value="2">2</option>
    <option data-testid="val3" value="3">3</option>
  </select>
};

When user selects any options, it will send selected values to onSelectedValuesChange callback.

I want to test it and use @testing-library/user-event to simulate user selecting options.

const mockOnChange = jest.fn()
const {getByTestId} = render(<MultiSelect onSelectedValuesChange={mockOnChange}/>)

userEvent.selectOptions(getByTestId("select-multiple"), ["1", "3"]);

// (1) here are correct
expect((getByTestId("val1") as HTMLOptionElement).selected).toBe(true);
expect((getByTestId("val2") as HTMLOptionElement).selected).toBe(false);
expect((getByTestId("val3") as HTMLOptionElement).selected).toBe(true);

// (2) but here is failed ???
expect(mockOnChange).toHaveBeenLastCalledWith(["1", "3"]);

Part (1) in code is working as expected, but part (2) is failed. The mockOnChange callback only gets ["1"] as passing parameters.

Here is also some messages in console may be useful:

    expect(jest.fn()).toHaveBeenLastCalledWith(...expected)

    Expected: ["1", "3"]
    Received
           1: ["1"]
    ->     2
              Array [
                "1",
            -   "3",
              ],

    Number of calls: 2

      18 | 
      19 |     // but here is failed ???
    > 20 |     expect(mockOnChange).toHaveBeenLastCalledWith(["1", "3"]);
         |                          ^
      21 |   });
      22 | })
      23 | 

      at Object.it (src/MultiSelect.test.tsx:20:26)

  console.log src/MultiSelect.tsx:12
    ### selected values:  [ '1' ]

  console.log src/MultiSelect.tsx:12
    ### selected values:  [ '1' ]

We can see the onSelectOptions has been called 2 times, but the arguments are always ['1'].

Do I misused anything?

Here is a small but complete demo for this issue: https://github.com/freewind-demos/typescript-react-testing-library--user-event--multiple-select--demo

Aucun commentaire:

Enregistrer un commentaire