Comments (34)
I would back using user-events as the new default. The philosophy of dom-testing-library is to test "the way a user would". A user certainly doesn't trigger separate DOM events, of which the user is usually even unaware (think a simple "hover" vs. all the mouseIn, mouseOver and their chains). Instead, if a user clicks on an input field, he would expect the input field to become active, along with any side effects that normally take place in the browser. So, I would replace the "old" way with this.
from dom-testing-library.
Hey @weyert, your test is firing change events at a button, not the input field. I believe that's the problem.
from dom-testing-library.
Just for me to understand, would this "user" library work somehow like this?
import React from "react";
import { render, fireEvent } from "react-testing-library";
import "jest-dom/extend-expect";
function App() {
return (
<React.Fragment>
<input data-testid="A" />
<input data-testid="B" />
</React.Fragment>
);
}
const userEvent = {
click(element) {
/* This is what really happens in my browser
* when I click on an element.
*
* Chrome 69.0.3497.92 (Official Build) (64-bit)
* OS X 10.11.6 (15G22010)
*
* mouseenter
* mouseover
* mousemove (a bunch of them)
* mousedown
* focus
* mouseup
* click
*
* If we fire the same events with fireEvent
* in the same exact order it doesn't work.
*
* This is because:
*
* 1. fireEvent.mouseOver also fires mouseenter
* although in the wrong order
* 2. fireEvent.focus does not set
* document.activeElement. I had to use
* element.focus()
*
* This is the best I could come up with
* to simulate the browser as closely as possible.
*/
const focusedElement = document.activeElement;
const wasAnotherElementFocused =
focusedElement !== document.body && focusedElement !== element;
if (wasAnotherElementFocused) {
fireEvent.mouseMove(focusedElement);
fireEvent.mouseLeave(focusedElement);
}
fireEvent.mouseOver(element);
fireEvent.mouseMove(element);
fireEvent.mouseDown(element);
element.focus();
fireEvent.mouseUp(element);
fireEvent.click(element);
wasAnotherElementFocused && focusedElement.blur();
}
};
test("events", () => {
const { getByTestId } = render(<App />);
userEvent.click(getByTestId("A"));
expect(getByTestId("A")).toHaveFocus();
userEvent.click(getByTestId("B"));
expect(getByTestId("B")).toHaveFocus();
expect(getByTestId("A")).not.toHaveFocus();
});
from dom-testing-library.
@alexkrolick, I'm going to be building a monorepo project at work (because I can't use semantic-release there) so we'll see how I enjoy it. My biggest hesitance for using monorepos is the semantic-release solution for monorepos seems slightly unmaintained and I'm worried about things that could come up. Dropping semantic-release from my workflow is kinda out of the question. I wouldn't have time to maintain the packages I do without semantic-release.
That said, I'll let you know what I think of my experience using a monorepo. If it's positive, then I'll see about trying to get semantic-release to work for a monorepo.
@Gpx, yes, I think that's exactly the kind of thing we're looking for ๐
from dom-testing-library.
@sompylasar yep you're right there are going to be many edge cases. As you suggested I intend to start by reviewing what other projects do and what browsers do.
Next, I'll take the new user events I create and put them in my test suite to see how it goes.
We'll probably need to sacrifice some events (I'm thinking of mousemove
for example) but I'll try to be as accurate as possible.
I'll keep you posted and I'm happy if somebody wants to contribute.
from dom-testing-library.
Hi everyone, a little update. I've started working on a library called user-event
. At the moment it supports only click
, dblClick
and type
but I've been testing it in my day to day job, and it seems quite useful.
I would much appreciate any feedback and especially bug reports. I believe many edge cases are not covered yet and at the moment I'm focusing only on the issues I find while working on my other projects.
Let me know what you think, and if you want to contribute you're more than welcome!
from dom-testing-library.
https://github.com/bigtestjs/interactor - an interesting library for simulating interactions, plus some Cypress like "interactability" detectors like isHidden, etc. Might be possible to get it to work with dom-testing-library somehow.
from dom-testing-library.
I'm happy to discuss this further, but let's open a new issue on user-event.
from dom-testing-library.
We're now working on merging user-event
back into dom-testing-library
in #616
from dom-testing-library.
Skimming over the Cypress API, these seem to be some of the most useful APIs provided and an idea of how they would act:
check
Focus, toggle-on
clear
Focus, select all, backspace
click
Click, focus
dblclick
Click, focus, 10ms delayed click
hover
As hover is a trusted event, it wouldn't be possible to activate the pseudo-class state of the element programmatically.
To address testing-library/jest-dom#53, you would need to programmatically apply the CSS of the hover pseudo-class to the element. Sounds challenging to do correctly.
select
Opening a select is a trusted event, so it wouldn't be possible programmatically.
Focus select, set option to selected
uncheck
Focus, toggle-off
type
Focus, add one character every 10ms
from dom-testing-library.
@Gpx Not to discourage you from doing what you're going to do, but there's a lot of corner cases, so please reuse the experience Cypress has collected over time in how this should work. Also puppeteer has an extensive user-simulating API to look at.
From my perspective the most accurate representation of user interactions with the UI is described in terms of the tools available to the user: 1) analyze the output: eyes or screenreaders to observe elements and move pointers on the screen, 2) produce the input: pointers, fingers, keyboards to interact with the screen. The input tools have state: the current coordinates and pressed/released for every button. The "click" action is actually a pointer click so it will be just optional focus of the element under the current coordinates and then click of the element under the current coordinates (also something may rerender on focus so click may hit a different element). Cypress has had a different approach last time I looked: to make as many shortcuts as possible (sacrificing the accuracy of representation), but still they try to emulate all events they can via the DOM.
from dom-testing-library.
I agree with @kentcdodds user-event is not mature enough. It still lacks some basic actions and more real-world testing.
As for including it in dom-testing-library, I'm not sure either. I think it shoudโat least in the beginningโbe an external library that offers an alternative to fireEvent
.
from dom-testing-library.
Amazing, thank you @kentcdodds. Clearly you are having a pair of fresh eyes!!
from dom-testing-library.
Closing this as we now have user-event
from dom-testing-library.
Also have a look at https://github.com/getgauge/taiko whose goal is to provide such a high-level API on top of a browser and a REPL to test it and record scripts.
I wish the very similar efforts dom-testing-library and cousins, Cypress, and now Taiko all put into making human-emulating APIs for webapp testing and automation could be united, but unfortunately Cypress is a not-so-modular-and-importable pile of CoffeeScript.
from dom-testing-library.
Yeah, I think that someone should develop a package separate from dom-testing-library that's intended to do this. Then dom-testing-library can just re-export that library (like we do with wait-for-element
).
Anyone want to do that? It'd probably be a lot of fun and I bet would get a lot of use. I just don't have time for it at the moment.
from dom-testing-library.
The very part that I wish could be reuse from Cypress is all the funky and often-simply-impossible-without-devtools-protocol but still useful emulation of the browser default behavior via just the DOM APIs (what dom-testing-library does as an infant compared to Cypress).
The part I wish could be reused from Taiko (although I read the code and it's not very robust yet) is the visually relative selectors by text (dom-testing-library kinda does by text, but not visually relative). I mean near
, above
, below
, I would also add alongVector(minDistance, maxDistance)
.
I agree with Kent that it should be a separate library.
from dom-testing-library.
@sompylasar Taiko looks amazing, but if I understand correctly since jsdom doesn't support "getBoundingClientRects", or "the ability to calculate where elements will be visually laid out as a result of CSS", we won't be able to do things like near/above/below. :-( Is there something that I'm missing?
It would be fantastic to have it in terms of testing the app like the user would. My team could possibly spend some time building a library like that, but if implementing layout in jsdom is prerequisite, that seems like way beyond our availability. :-(
from dom-testing-library.
a package separate from dom-testing-library
Are you sure you don't want to pursue the monorepo idea in #98? The cross-dependency between these packages is a bit hairy and some of the wrappers are undoubtedly already falling behind, depending on implementation.
from dom-testing-library.
I think that someone should develop a package separate from dom-testing-library that's intended to do this
Can I give it a shot?
from dom-testing-library.
Go for it!
from dom-testing-library.
Fantastic! That's a great start ๐ once we get more user actions in there, then we can pull that in and re-export it ๐ฏ
Circular dependencies are fun ๐ I'm pretty sure it works though.
from dom-testing-library.
I have had a look at the library and even when using that I am struggling to make onChange event handlers be called or the keydown events. I am not sure if something is broken or not. I have been able to make a reproducible sandbox which can be found at the link below. I have added some logs in my onChange
and onKeyDown
event handlers in my component MyField
when using it in the preview I am correctly receiving things like MyField.onFieldChange()
etc but not when running the tests.
I am a bit worried that my testing approach is wrong. I am trying to test things which I should test?
Sandbox URL: https://codesandbox.io/s/ol4qnvy669
from dom-testing-library.
I have created a PR for @Gpx library so that it will dispatch onKeyDown/onKeyUp and change correctly when you are using preventDefault()
in your code to block the entry of a character, you can find it here: testing-library/user-event#27
If this change is against the intended use of react-testing-library
let me know. I think when you a user types 1.5a
and your component does event.preventDefault()
on the a
then the type() should accordingly trigger 1.5
and not 1.5a
from dom-testing-library.
@kentcdodds do you think user-event is mature enough to include in the next release?
from dom-testing-library.
I'm not sure. I'm actually a bit concerned about this. One of the things I didn't like about enzyme was that there were a million ways to do things. If we include this in dom-testing-library then we have two ways to do things and I feel like it could get confusing. What do you all think?
from dom-testing-library.
I think there are inherently at least two ways to simulate user-originated events in the browser: 1) imitate them with variable precision via browser DOM API from within JS runtime (not all possible to implement, many shortcuts and hacks); 2) inject into browser user input queue as if an input device generated them, let the browser translate to DOM events (precise but requires browser automation API which either not available or is async).
from dom-testing-library.
I was under the impression that this would be the new default behavior, and that if someone would want to fire events the old way, they would just do it manually. That seems consistent with how dom-testing-library handles selection - if you want to select a class, use DOM methods directly.
from dom-testing-library.
I would like to see it support more typical user events (drag and drop, hover, etc), then I'd like to see it used in real codebases for a while to see how it works in practice and work out any issues/common questions. I'm a little hesitant, particularly when someone changes from fireEvent.change
to user.type
. Their change handler will get called once for every character typed rather than once for the event which is correct, but I think could lead to confusion.
from dom-testing-library.
Yes, I think it would be a good idea to mention the availability in the React and Dom testing library README that this helper library exists for some common user events :)
from dom-testing-library.
Yes, I agree @weyert. Will help with adoption. I would like to suggest that we refer to it as experimental until it gets more features and is more proven.
from dom-testing-library.
I think it would be great to expand on user-event
enough for it to be worth replacing fireEvent
. Are there any specific events we'd want to add (maybe all the ones from Cypress)? Since this initial discussion, selectOptions
has been added.
from dom-testing-library.
Where is the new issue? :D we are looking forward to it.
from dom-testing-library.
testing-library/user-event#183
from dom-testing-library.
Related Issues (20)
- Having a <p> inside a <label> breaks the query HOT 2
- Support complex aria-labelledby queries HOT 1
- Support abstract roles HOT 9
- findByRole() finds no candidates HOT 13
- getByText not working with multiline text
- `waitFor` doesn't advance time when using `jest` fake timers without injecting globals HOT 4
- `getByRole('insertion')` and `getByRole('deletion')` do not match semantic `<del>` and `<ins>` tags HOT 6
- getByRole('caption') does not find caption element HOT 12
- Images with an empty alt attribute are not being assigned `presentation` role (and are still being found by testing library even though they are hidden from the accessibility tree) HOT 4
- fireEvent doesn't work in pointer event HOT 2
- Github actions - tests pass but execution fails on Process completed with exit code 1. HOT 2
- *ByRole form seems not to find <form /> elements HOT 5
- v8.20.1 - invalid syntax reported by esprima-fb HOT 1
- ByRole doesn't find SVG's graphics-document role HOT 3
- when running vitest(using react-testing-library-dom) in git action, action exceeded the maximum execution time of xx minutes HOT 7
- Test fails if not wrapped into waitFor HOT 6
- can't run CodeSandbox tests (issue converting to devbox) HOT 3
- Queries having multiple types HOT 1
- getByText throwing when throwSuggestions is enforced recommending ambiguous getByRole('paragraph') approach. HOT 2
- `screen` incompatible with document.body.replaceWith() HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dom-testing-library.