Giter Site home page Giter Site logo

testing-library / user-event Goto Github PK

View Code? Open in Web Editor NEW
2.2K 19.0 244.0 2.59 MB

πŸ• Simulate user events

Home Page: https://testing-library.com/user-event

License: MIT License

JavaScript 5.19% TypeScript 94.81%
testing javascript dom user-interaction ui frontend

user-event's Introduction

user-event

dog

Fire events the same way the user does


Read The Docs



Build Status Code Coverage version downloads MIT License All Contributors PRs Welcome Code of Conduct Discord

Watch on GitHub Star on GitHub Tweet

The problem

From testing-library/dom-testing-library#107:

[...] it is becoming apparent the need to express user actions on a web page using a higher-level abstraction than fireEvent

The solution

user-event tries to simulate the real events that would happen in the browser as the user interacts with it. For example userEvent.click(checkbox) would change the state of the checkbox.

The more your tests resemble the way your software is used, the more confidence they can give you.

Issues

Looking to contribute? Look for the Good First Issue label.

πŸ› Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

πŸ’‘ Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a πŸ‘. This helps maintainers prioritize what to work on.

See Feature Requests

❓ Questions

For questions related to using the library, please visit a support community instead of filing an issue on GitHub.

Contributors

We most sincerely thank the people who make this project possible. Contributions of any kind are welcome! πŸ’š

License

MIT

user-event's People

Contributors

afontcu avatar allcontributors[bot] avatar aprillion avatar benmonro avatar bozdoz avatar calebeby avatar daleseo avatar gentlemanhal avatar gpx avatar greenkeeper[bot] avatar hontas avatar juanca avatar kentcdodds avatar kt-weyert avatar lourenci avatar luistak avatar marcosvega91 avatar michaeldeboey avatar nickserv avatar pascalduez avatar patricklizon avatar ph-fritsche avatar raynos avatar robcaldecott avatar silouanwright avatar timdeschryver avatar vadimshvetsov avatar visualjerk avatar wachunga avatar ybentz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

user-event's Issues

.type doesn't work with vue-testing-library

Hi! First of all, thank you for your work on this repo!

I wanted to highlight that the current implementation of .type() isn't working when used with vue-testing-library.

Not quite sure why yet thou, I believe it has something to do with using fireEvent.change instead of fireEvent.input here. I have passing tests using fireEvent.input, and the minute I change them to use .change, they start failing. Is there any reason to prefer change event over input?

Thanks!

Entering a combination of valid and invalid characters in a number input returns an empty string

I expect that if you type something like

userEvent.type(input, "-1.0abc!@#");

in to a number input, input.value should equal "-1.0".
In this case, input.value equals ""

function PctInput({ onChange, value = 0, name, ...props }) {
  const format = x => significantFigures(2, decimalToPercent(x));
  const [displayValue, setDisplayValue] = React.useState(format(value));
  React.useEffect(() => {
    onChange({ [name]: percentToDecimal(displayValue) });
  }, [displayValue, onChange, name]);
  return (
    <Input
      type="number"
      name={name}
      value={displayValue}
      onChange={event => {
        setDisplayValue(event.target.value);
      }}
      {...props}
    />
  );
}

const setup = ({ value = 0, onChange = jest.fn(), ...props } = {}) => {
  const utils = render(
    <PctInput
      data-testid={"input"}
      onChange={onChange}
      value={value}
      {...props}
    />
  );
  utils.getByTestId("input").focus();
  return { input: document.activeElement || document.body, ...utils };
};

test("should only allow number inputs (0-9, -, .)", () => {
  const { input } = setup();
  userEvent.type(input, "-1.0abc!@#");
  expect(input.value).toEqual("-1.0");
});
 FAIL  app/scripts/components/Sidebar/StepSettingsSidebar/StepChildSettingsSection/TooltipOptions/PctInput.test.js
  ● should only allow number inputs (0-9, -, .)

    expect(received).toEqual(expected) // deep equality

    Expected: "-1.0"
    Received: ""

      20 |   const { input } = setup();
      21 |   userEvent.type(input, "-1.0abc!@#");
    > 22 |   expect(input.value).toEqual("-1.0");
         |                       ^
      23 | });
      24 | test("should allow user to delete all of the characters, one at a time", () => {
      25 |   const { input } = setup({

      at Object.toEqual (app/scripts/components/Sidebar/StepSettingsSidebar/StepChildSettingsSection/TooltipOptions/PctInput.test.js:22:23)

Type function isn’t awaiting

Hi!

I'm trying to simulate a user typing with userEvent.type as follows:

const startDateInput = getByTestId('startdate-input');

const ticketData = {
  startDate: '12/12/2020',
};

await userEvent.type(startDateInput, ticketData.startDate);

expect(await waitForElement(() => startDateInput)).toHaveValue(ticketData.startDate);

but I'm getting this:

expect(element).toHaveValue(12/12/2020)

Expected the element to have value:
      12/12/2020
Received:
      02/2_/____

> 49 |     expect(await waitForElement(() => startDateInput)).toHaveValue(ticketData.startDate);
                                                              ^

Any hints?

Package Version
@testing-library/jest-dom ^4.2.4
@testing-library/react ^9.3.3
@testing-library/user-event 7.1.2

When typing in a disabled input onChange is still called

Test:

import React from 'react'
import { render } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

    it('should not call onChange function when typing in a disabled field', () => {
        const onChange = jest.fn()
        const { getByPlaceholderText } = render(
            <input
                disabled
                id="test-id"
                name="test-name"
                onChange={onChange}
                placeholder="placeholder"
            />
        )
        userEvent.type(getByPlaceholderText('placeholder'), 'foo')
        expect(onChange).not.toHaveBeenCalled()
    })

I expect this test to succeed but it isn't.

Output:

    Expected mock function not to be called but it was called with:
      [{"_dispatchInstances": null, "_dispatchListeners": null, "_targetInst": null, "bubbles": null, "cancelable": null, "currentTarget": [Function currentTarget], "defaultPrevented": null, "dispatchConfig": null, "eventPhase": null, "isDefaultPrevented": [Function functionThatReturnsFalse], "isPropagationStopped": [Function functionThatReturnsFalse], "isTrusted": null, "nativeEvent": null, "target": null, "timeStamp": [Function timeStamp], "type": null}], [{"_dispatchInstances": null, "_dispatchListeners": null, "_targetInst": null, "bubbles": null, "cancelable": null, "currentTarget": [Function currentTarget], "defaultPrevented": null, "dispatchConfig": null, "eventPhase": null, "isDefaultPrevented": [Function functionThatReturnsFalse], "isPropagationStopped": [Function functionThatReturnsFalse], "isTrusted": null, "nativeEvent": null, "target": null, "timeStamp": [Function timeStamp], "type": null}], [{"_dispatchInstances": null, "_dispatchListeners": null, "_targetInst": null, "bubbles": null, "cancelable": null, "currentTarget": [Function currentTarget], "defaultPrevented": null, "dispatchConfig": null, "eventPhase": null, "isDefaultPrevented": [Function functionThatReturnsFalse], "isPropagationStopped": [Function functionThatReturnsFalse], "isTrusted": null, "nativeEvent": null, "target": null, "timeStamp": [Function timeStamp], "type": null}]

React onChange handler not called when type is used

Problem:
The type method does not cause the React onChange handler to be called.

This can be seen in this sandbox: https://codesandbox.io/s/zealous-sanderson-zqrg5?fontsize=14&module=%2Fsrc%2F__tests__%2FtypeTestThatFails.test.js&previewwindow=tests

Expected behaviour:
The onChange handler on the element being typed into is fired.

Potential solution:
I have managed to work around this using the react-trigger-change module. See this sandbox: https://codesandbox.io/s/zealous-sanderson-zqrg5?fontsize=14&module=%2Fsrc%2F__tests__%2FtypeTestWithWorkaround.test.js&previewwindow=tests

Emulation of 'Backspace' and other non alphanumeric buttons pressing.

Hi, guys!

I have a next question, which has come during usage of this cool library.
I have to simulate a user's "Backspace" button pressing and could not find how to do it with this library.
Unfortunately, the native testing-library fireEvent is not works for me, because I have an input which filters pressed keys in onKeyDown event handler and it also has onChange event handler which makes additional validation and further component mutations.
I use user-event to check that both events have been fires correclty and check the final value of input.

'Backspace' is also have to pass through this filter to erase typed data, but I couldn't find how to call it.

Could you please advice something?
Thank you.

userEvent.type does not triggers React onChange when the input has type

This might be related to #149

I am not sure if it is a problem of React, of jsdom, or there is one step wrong.
Given the following pseudo-code:

const inputWithoutType = render(
  <input onChange={onChangeWithoutType} />
);
const inputWithType = render(
  <input type="string" onChange={onChangeWithType} />
);

The userEvent.type(inputWithoutType, 'hello') triggers onChangeWithoutType. βœ…
The userEvent.type(inputWithType, 'hello') does not trigger onChangeWithType. ❌

You can find an example at:

Any idea what is going wrong?
Thanks!

should type be constrained by maxLength?

Is maxLength an attribute user-event should take into account?

If so, the following test should pass:

// __tests__/vue/type.js

test("maxlength", () => {
  const input = jest.fn();

  const maxlength = 10;

  const { getByTestId } = renderComponent('input',
    { input },
    { maxlength }
  );

  const text = "Hello, world!";
  userEvent.type(getByTestId("input"), text);

  expect(input).toHaveBeenCalledTimes(maxlength);
  expect(getByTestId("input")).toHaveProperty("value", text.slice(0, maxlength));
});

I'll be happy to implement it if you think it makes sense.

click sequence of events is different than browsers

I believe the sequence of events for click (and dblClick) is different that the one in browsers.

With this jsfiddle: https://jsfiddle.net/3r9oczkg/

We can see by:

1- focusing in the input
2- click on item 2

That after clicking on item 2 the blur / focus sequence is:

1- input blur
2- item 2 focus
3- item 2 click

Which means that the focusedElement blur event should happen BEFORE the item 2 focus and click events.

Fixing this would be very convenient for Components that rely on the right focus / blur order!

Thank you

Patrick

selectOptions by option content

https://github.com/testing-library/user-event#selectoptionselement-values

Users do not interact with <select/> elements by the option value because it is not visible. Users typically select by the text content of each option that they can see.

This is possibly a separate issue, but the current example in the readme is unclear about whether the option content or the value is used to select because the values and content are the same.

<option data-testid="val1" value="1">
  1
</option>

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

While the example is unclear, there is some text:
The values parameter can be either an array of values or a singular scalar value.

Error thrown when using react hooks

Description

Given a react component using hooks
When a you attempt to use a user event e.g. type
Then you receive the error below

Warning: An update to %s inside a test was not wrapped in act(...).

Reason

As far as I understand this is because we are using the fireEvent from @testing-library/dom directly and not from @testing-library/react which means that it is not being in act.

Solution

A possible solution would be to allow for the user to provide a fireEvent implementation or allow for this to be configured in test setup

Allow for non-fixed version of @testing-library/dom

Hi, thanks for this package, it's pretty awesome πŸ‘€ πŸŽ‰

I was wondering if the package.json could be updated to have a semver range for the @testing-library/dom dependency, rather than a fixed version: https://github.com/testing-library/user-event/blob/master/package.json#L56

Suggestion:

-    "@testing-library/dom": "5.1.1"
+    "@testing-library/dom": "^5.1.1"

This way I don't have to have multiple versions of @testing-library/dom installed, and you don't have to constantly update the version in your package.json πŸ˜„

Happy to submit a PR if you want

click should also trigger focusin and focusout

It would be awesome if click (and dblClick) also support focusin and focusout.

Event if they are not currently part of React: facebook/react#6410

You can still use it with document.addEventListener.

Calling focusin right after element.focus() and focusout right after fireEvent.blur(focusedElement) seems to work well.

Thank you,

Patrick

`selectOptions` with Angular

πŸ‘‹ first of all, great idea to create this library!

I recently found out about this library and was looking to use it with the Angular testing library.
To be able to do that I had to wrap the user events with some angular logic (has to do with the Angular change detection), so now I'm exposing these wrapped user events via the render function. But there's a problem with selectOptions. To work in Angular, it also needs to fire a change event (instead of just clicking on the option element).

Now my question, should I provide these user events in the Angular testing library myself, trying to keep a similar API? Or should we make the change in this library to be able to use it with Angular?

I'm fine either way, I just want to hear your opinions before I go through with the implementation πŸ™‚

Simulate keyboard shortcuts

Not sure if in this packages domain, but simulating shortcuts or hotkeys using this libary abstracting to something like userEvent.shortcut('ctrl+c') userEvent.shortcut('ctrl+alt+enter')

Check type with special characters

userEvent.type writes text correctly. But I'm not sure how it behaves with special characters like Γ¨ or πŸ‘ .

It would be good to have tests covering these cases

Support for unselect options?

selectOptions currently force selected to true as per coded at here.

Does it make sense to support toggleOptions so we can test for unselect as well?

Let me know if you need a hand.

tab with radio buttons

just discovered an issue w/ tab(). it does not account for radio buttons properly and needs to more closely resemble the browser in this respect.

fireEvent.focus should be discouraged

Describe the feature you'd like:

Discourage fireEvent.focus(element)

Suggested implementation:

Prefer element.focus()

Describe alternatives you've considered:

Don't use existing API or call element.focus() internally.

Teachability, Documentation, Adoption, Migration Strategy:

fireEvent.focus(element) will not move the focus to the element i.e. document.activeElement !== element. element.focus() will result in document.activeElement === element and dispatch the focus event. fireEvent.focus will also work on non-interactive elements whereas element.focus does not.

Showcase of fireEvent vs imperative focus

Merge into testing libraries and recommend over fireEvent

Now that this package is mentioned in the testing library docs, it would be nice to expand it enough to be recommended over fireEvent in most cases and include it in the original packages. We should think about what common user interactions are missing that are tricky to implement with fireEvent. Other testing tools like Cypress could be good inspiration.

userEvent.type not changing when is a empty string

I am experimenting this lib and may reached a possible bug. I have been writting a test for Input to check if erases it correctly and found something interesting.

import React from 'react';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

function Input(props) {
  return <input {...props} />;
}

it('should handle input erases', async () => {
    let value = '';
    const onChange = jest.fn(e => {
      value = e.target.value;
    });

    const { getByPlaceholderText, rerender } = render(
      <Input placeholder="Name" value={value} onChange={onChange} />
    );
    const input = getByPlaceholderText('Name');

    userEvent.type(input, 'test');

    // In order to see some "value" changes, we need to rerender the component
    rerender(<Input placeholder="Name" value={value} onChange={onChange} />);

    expect(input).toHaveAttribute('value', 'test');

    // When type empty string simulating an erase test will fail
    userEvent.type(input, '');
    // When using { allAtOnce: true } test will pass
    // userEvent.type(input, '', { allAtOnce: true });

    // In order to see some "value" changes, we need to rerender the component
    rerender(<Input placeholder="Name" value={value} onChange={onChange} />);

    expect(input).toHaveAttribute('value', '');
  });

When you use userEvent.type without { allAtOnce: true } on this case, the Input value will not get any updates. Looking at the type implementation I could identify what is possible wrong.

if (opts.allAtOnce) {
  if (element.readOnly) return;
  fireEvent.input(element, { target: { value: text } });
} else {
  let actuallyTyped = '';
  // If text is a empty string, actuallyTyped will never be used inside fireEvent.input
  for (let index = 0; index < text.length; index++) {
    ...
  }
}

If this is a real bug, I can help fix this! Maybe a naive solution could be adding a extra condition

if (opts.allAtOnce || text === '') 

What do you think guys?

Support "enter" keydown on button

In a browser, enter keydown trigger the click event of the button.

It would be nice if the user-event library support this behavior.

You can test the browser behavior here: https://codesandbox.io/s/jovial-glitter-jy883?from-embed

A naive implementation would be to add a keyDown function to user-event:

    keyDown(element, options) {
        fireEvent.keyDown(element, options);

        if (element.tagName === "BUTTON") {
            fireEvent.click(element);
        }
    }

Thank you,

Patrick

Include typings folder in npm publish.

Thanks for a helpful lib! It appears that the typings folder is not actually making it to npm, so the TS support isn't working. You can see that the typings folder isn't there by checking it out on runpkg: https://runpkg.com/?@testing-library/[email protected]/dist/index.js. Compare this to say, @testing-library/react, whose typings folder is published to npm: https://runpkg.com/?@testing-library/[email protected]/dist/index.js. Since there's no .npmignore nor a files field in the package.json, I believe everything that's on GitHub is ending up published to npm (which is strange that typings wouldn't also make it in this case), which even means your tests and source are getting bundled in folks' node_modules 😬 Finally, it appears the package.json version is out of lockstep with the npm published version. Happy to make a PR to help with these things if you like! Thanks again for a helpful lib.

arrow keys?

for the life of me I can't seem to be able to fire an event for a keypress with arrow keys on a radio button, is this a problem in jsdom, or am I crazy?

  fireEvent.keyPress(myRadioButton, { key: 'ArrowUp', which: 38, keyCode: 38 });

Tab action does not simulate focus/blur events

In browser when you call focus() or blur() on an element programmatically, focusin or focusout events bubble from the focused/blurred element. However in jsdom they do not.

If the application logic depends on these events, would be appropriate to simulate these events too, when calling userEvent.tab(), so that it's possible to test such logic in jsdom too.

click() doesn't quite work for div role="radio"

First, thanks for this library - great abstraction.

I just tried to use the userEvent.click() function on a radio button that is implemented as <div role="radio" /> (e.g. @palmerhq/radio-group) and it didn't quite yield the same expected behavior as directly calling fireEvent.click(). I see the click logic currently looks for <input type="radio" /> and calls clickBooleanElement, but this implementation of a radio button falls through to clickElement.

In the actual application, clicking said radio button moves the focus to an input field that becomes enabled when this radio button is selected. If I use fireEvent.click to select the radio button, asserting focus to be on the text input afterwards is successful. But using userEvent.click causes the focus assertion to fail.

The current published version of @testing-library/user-event results in the radio div retaining focus. I locally modified it to check for this type of element and call clickBooleanElement instead, but that doesn't seem to be quite right either. In that version, body ends up with focus.

Thoughts?

maxlength attribute is ignored

(Source: how to test input maxlength attribute).


  • dom-testing-library version: 5.6.1
  • react version: -
  • node version: 10.16
  • npm version: 6.9

Relevant code or config:

import { getByRole, fireEvent } from '@testing-library/dom'

test('maxlength', () => {
  const div = document.createElement('div')
  div.innerHTML = `<input type="text" maxlength="10" />`

  const input = getByRole(div, 'textbox')

  fireEvent.input(input, { target: { value: '01234657890123456789' }})

  expect(input.maxLength).toBe(10)
  expect(input.value).toBe('0123456789') // <-- fails
})

What happened:

Expected the test above to pass.

  ● maxlength

    expect(received).toBe(expected) // Object.is equality

    Expected: "0123456789"
    Received: "01234657890123456789"

      26 | 
      27 |   expect(input.maxLength).toBe(10)
    > 28 |   expect(input.value).toBe('0123456789') // <-- fails
         |                       ^
      29 | })
      30 | 

      at Object.toBe (src/Input.spec.js:16:23)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.332s, estimated 1s

This might be an expected behavior (not sure if an Event should honor maxlength attribute), but felt weird. I thought about this a bit and explore some ideas, but couldn't come up with a fix.

Tried with RTL and VTL and both failed too, obviously.

Disabled checkbox click still fires `onChange`

this PR on react-testing-library was an attempt to address this problem:
testing-library/dom-testing-library#217

but it was closed in favor of addressing in this library. From what I can tell, it has not been addressed in this library. In my test, I'm still seeing the onChange handler being called for an <input type="checkbox" disabled /> when I call userEvent.click(checkbox).
This is not how browsers behave, fwiw

Right click

Request for help on how to perform right click using this library or to have it added.

I'm writing tests against a component that uses the DetailsList component from office-ui-fabric-react and trying to have a right click register with the component. Using fireEvent does not work.

I had a similar issue trying to use fireEvent with a double click on the DetailsList. Using userEvent.dblClick registered with the DetailsList.

Thanks!

Invitation to move to testing-library org

It's up to you, but if you'd like, you're welcome to transfer this repository to the testing-library organization on GitHub. This will give your project more credibility as part of the testing-library family of projects with a unified mission of tools which help people avoid testing implementation details.

Again, totally up to you. I just want you to know we appreciate all you've done and you're welcome to join us if you like.

userEvent.tab

Add the ability to simulate a user tabbing through a UI for RTL: userEvent.tab(direction)

more of a question to see if you guys would be open to me opening a PR for userEvent.tab
from what I've read in threads on RTL and JSDOM, the ability to tab is not really supported by JSDOM. However, I came up with a working solution that simulates tabbing. I'd love to open a PR and contribute here, but before I do wanted to check to make sure you guys would be open to it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.