@testing-library/user-event version: 12.6.0@testing-library/react version 11.2.1jsdom version 16.4.0Relevant code or config:
describe("demo", () => {
const text = "2001:db8:ac10:fd01::20";
test("time type", () => {
render(<input data-testid="input" type="text" />);
const input = screen.getByTestId('input');
const before = new Date();
userEvent.type(input, text);
console.log(`type took ${new Date() - before}ms`);
expect(input.value).toEqual(text);
});
test("time delayed type", async () => {
render(<input data-testid="input" type="text" />);
const input = screen.getByTestId('input');
const before = new Date();
await userEvent.type(input, text, {
delay: Number.MIN_VALUE,
});
console.log(`delayed type took ${new Date() - before}ms`);
expect(input.value).toEqual(text);
});
test("time paste", () => {
render(<input data-testid="input" type="text" />);
const input = screen.getByTestId('input');
const before = new Date();
userEvent.paste(input, text);
console.log(`paste took ${new Date() - before}ms`);
expect(input.value).toEqual(text);
});
});
Problem description:
Running the above test suite with yarn test --no-cache logs the following values on my machine:
type took 29ms
delayed type took 63ms
paste took 1ms
The results are fairly consistent between reruns (plus-minus a few ms).
The performance difference is starker with longer strings: replacing the input text with const text = "2001:db8:ac10:fd01::20".repeat(100);, the results are as follows:
type took 1380ms
delayed type took 5940ms
paste took 1ms
I understand that some of this difference stems from the letter-by-letter nature of type() which is crucial for certain test scenarios. For the time being however, type() is too slow for many of the tests we run and we've had to opt for paste() instead.
I haven't profiled type()'s internals so I don't know what the source of the performance penalty is.
I don't think there is much to gain optimizing the test utility code for performance.
After all we're talking about miliseconds in a test environment that can run multiple tests parallel.
The approach here is to trade manual labor (analyzing code) for automated labor (running test containers) by running these utilities in the first place.
If you put in the work and optimize some part of the code, a PR will be welcome.
But keep in mind we'll err on the side of maintainability.
I don't think the scale of the problem is as low as you make it to be. If you do ten type() calls within one test you're already getting close to a second and with anything larger you can quickly reach Jest's default timeout of 5 seconds. Choosing to not look into this is fair, but I don't think downplaying the problem is beneficial.
For context, in a perfect world I would expect type() with no delay to be on the same scale as paste(), or at least in the same order of magnitude. Right now it can be several orders of magnitude slower, easily reaching the default time limit.
Don't get me wrong. I see that you can't type a book in 5sec default timeout.
But I just checked on my local machine. I can repeat your userEvent.type(input, '2001:db8:ac10:fd01::20') 308 times before hitting the timeout.
I don't see any test that would benefit from doing a character by character and event by event simulation of typing more than that.
userEvent.paste provides a completely different abstraction. No keydown..keypress..keyup etc. for each character.
If you want to test your user typing, it is no better than calling fireEvent.input directly.
What userEvent.type does for you on the other hand is exactly this: Simulate every event that would happen if a user went on and typed every character in your input string one by one.
Most helpful comment
I don't think the scale of the problem is as low as you make it to be. If you do ten
type()calls within one test you're already getting close to a second and with anything larger you can quickly reach Jest's default timeout of 5 seconds. Choosing to not look into this is fair, but I don't think downplaying the problem is beneficial.For context, in a perfect world I would expect
type()with no delay to be on the same scale aspaste(), or at least in the same order of magnitude. Right now it can be several orders of magnitude slower, easily reaching the default time limit.