Skip to content

Commit

Permalink
feat: 🎸 add options.delay for type()
Browse files Browse the repository at this point in the history
  • Loading branch information
Gpx committed Oct 21, 2018
1 parent 3511255 commit b0f2c3c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 46 deletions.
11 changes: 8 additions & 3 deletions README.md
Expand Up @@ -97,9 +97,7 @@ test("double click", () => {

### `type(element, text, [options])`

Writes `text` inside an `<input>` or a `<textarea>`. `options` accepts one
argument `allAtOnce` which is `false` by default. If it's set to `true` it will
write `text` at once rather than one character at the time.
Writes `text` inside an `<input>` or a `<textarea>`.

```jsx
import React from "react";
Expand All @@ -113,3 +111,10 @@ const { getByText } = test("click", () => {
userEvent.type(getByTestId("email"), "Hello, World!");
expect(getByTestId("email")).toHaveAttribute("value", "Hello, World!");
```

If `options.allAtOnce` is `true` type will write `text` at once rather than one
character at the time. `false` is the default value`.

`options.delay` is the number of milliseconds that pass between to characters
are typed. By default it's 0. You can use this option if your component has a
different behavior for fast or slow users.
70 changes: 35 additions & 35 deletions __tests__/type.js
@@ -1,14 +1,12 @@
import "jest-dom/extend-expect";

import { cleanup, render } from "react-testing-library";

import React from "react";
import { cleanup, render, wait } from "react-testing-library";
import "jest-dom/extend-expect";
import userEvent from "../src";

afterEach(cleanup);

describe("userEvent.type", () => {
it.each(["input", "textarea"])("should type text in <%s>", async type => {
it.each(["input", "textarea"])("should type text in <%s>", type => {
const onChange = jest.fn();
const { getByTestId } = render(
React.createElement(type, {
Expand All @@ -17,34 +15,28 @@ describe("userEvent.type", () => {
})
);
const text = "Hello, world!";
await userEvent.type(getByTestId("input"), text);
userEvent.type(getByTestId("input"), text);
expect(onChange).toHaveBeenCalledTimes(text.length);
expect(getByTestId("input")).toHaveProperty("value", text);
});

it.each(["input", "textarea"])(
"should not type <%s> when prevented",
async type => {
const onChange = jest.fn();
const onKeydown = jest
.fn()
.mockImplementation(event => event.preventDefault());
const { getByTestId } = render(
React.createElement(type, {
"data-testid": "input",
onKeyDown: onKeydown,
onChange: onChange
})
);
const text = "Hello, world!";
await userEvent.type(getByTestId("input"), text);
expect(onKeydown).toHaveBeenCalledTimes(text.length);
expect(onChange).toHaveBeenCalledTimes(0);
expect(getByTestId("input")).not.toHaveProperty("value", text);
}
);
it("should not type when event.preventDefault() is called", () => {
const onChange = jest.fn();
const onKeydown = jest
.fn()
.mockImplementation(event => event.preventDefault());
const { getByTestId } = render(
<input data-testid="input" onKeyDown={onKeydown} onChange={onChange} />
);
const text = "Hello, world!";
userEvent.type(getByTestId("input"), text);
expect(onKeydown).toHaveBeenCalledTimes(text.length);
expect(onChange).toHaveBeenCalledTimes(0);
expect(getByTestId("input")).not.toHaveProperty("value", text);
});

it("test delayed typing of text", async () => {
it("should delayed the typing when opts.dealy is not 0", async () => {
jest.useFakeTimers();
const onChange = jest.fn();
const { getByTestId } = render(
React.createElement("input", {
Expand All @@ -53,18 +45,26 @@ describe("userEvent.type", () => {
})
);
const text = "Hello, world!";
await userEvent.type(getByTestId("input"), text, {
allAtOnce: false,
delay: 10
const delay = 10;
userEvent.type(getByTestId("input"), text, {
delay
});
expect(onChange).not.toHaveBeenCalled();
expect(getByTestId("input")).not.toHaveProperty("value", text);

expect(onChange).toHaveBeenCalledTimes(text.length);
expect(getByTestId("input")).toHaveProperty("value", text);
for (let i = 0; i < text.length; i++) {
jest.advanceTimersByTime(delay);
await wait(() => expect(onChange).toHaveBeenCalledTimes(i + 1));
expect(getByTestId("input")).toHaveProperty(
"value",
text.slice(0, i + 1)
);
}
});

it.each(["input", "textarea"])(
"should type text in <%s> all at once",
async type => {
type => {
const onChange = jest.fn();
const { getByTestId } = render(
React.createElement(type, {
Expand All @@ -73,7 +73,7 @@ describe("userEvent.type", () => {
})
);
const text = "Hello, world!";
await userEvent.type(getByTestId("input"), text, {
userEvent.type(getByTestId("input"), text, {
allAtOnce: true
});

Expand Down
12 changes: 4 additions & 8 deletions src/index.js
@@ -1,8 +1,8 @@
import { fireEvent } from "dom-testing-library";

function delay(t, v) {
function wait(time) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, v), t);
setTimeout(() => resolve(), time);
});
}

Expand Down Expand Up @@ -135,11 +135,7 @@ const userEvent = {
};
const opts = Object.assign(defaultOpts, userOpts);
if (opts.allAtOnce) {
fireEvent.change(element, {
target: {
value: text
}
});
fireEvent.change(element, { target: { value: text } });
} else {
const typedCharacters = text.split("");

Expand All @@ -149,7 +145,7 @@ const userEvent = {
const key = char; // TODO: check if this also valid for characters with diacritic markers e.g. úé etc
const keyCode = char.charCodeAt(0);

if (opts.delay > 0) await delay(opts.delay);
if (opts.delay > 0) await wait(opts.delay);

const downEvent = fireEvent.keyDown(element, {
key: key,
Expand Down

0 comments on commit b0f2c3c

Please sign in to comment.