Skip to content

Commit

Permalink
feat: add capslock to userEvent.type (#507)
Browse files Browse the repository at this point in the history
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
  • Loading branch information
Sonic12040 and kentcdodds committed Nov 30, 2020
1 parent f7620ab commit 9344db6
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 18 deletions.
37 changes: 19 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,14 @@ import userEvent from '@testing-library/user-event'

// or

const { default: userEvent } = require('@testing-library/user-event')
const {default: userEvent} = require('@testing-library/user-event')
```

## API

Note: All userEvent methods are synchronous with one exception: when `delay`
with `userEvent.type` as described below). We also discourage using
`userEvent` inside `before/after` blocks at all, for important reasons
described in
with `userEvent.type` as described below). We also discourage using `userEvent`
inside `before/after` blocks at all, for important reasons described in
["Avoid Nesting When You're Testing"](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing).

### `click(element, eventInit, options)`
Expand Down Expand Up @@ -189,20 +188,21 @@ to `await`!

The following special character strings are supported:

| Text string | Key | Modifier | Notes |
| -------------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{enter}` | Enter | N/A | Will insert a newline character (`<textarea />` only). |
| `{space}` | `' '` | N/A | |
| `{esc}` | Escape | N/A | |
| `{backspace}` | Backspace | N/A | Will delete the previous character (or the characters within the `selectedRange`, see example below). |
| `{del}` | Delete | N/A | Will delete the next character (or the characters within the `selectedRange`, see example below) |
| `{selectall}` | N/A | N/A | Selects all the text of the element. Note that this will only work for elements that support selection ranges (so, not `email`, `password`, `number`, among others) |
| `{arrowleft}` | ArrowLeft | N/A | |
| `{arrowright}` | ArrowRight | N/A | |
| `{shift}` | Shift | `shiftKey` | Does **not** capitalize following characters. |
| `{ctrl}` | Control | `ctrlKey` | |
| `{alt}` | Alt | `altKey` | |
| `{meta}` | OS | `metaKey` | |
| Text string | Key | Modifier | Notes |
| -------------- | ---------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{enter}` | Enter | N/A | Will insert a newline character (`<textarea />` only). |
| `{space}` | `' '` | N/A | |
| `{esc}` | Escape | N/A | |
| `{backspace}` | Backspace | N/A | Will delete the previous character (or the characters within the `selectedRange`, see example below). |
| `{del}` | Delete | N/A | Will delete the next character (or the characters within the `selectedRange`, see example below) |
| `{selectall}` | N/A | N/A | Selects all the text of the element. Note that this will only work for elements that support selection ranges (so, not `email`, `password`, `number`, among others) |
| `{arrowleft}` | ArrowLeft | N/A | |
| `{arrowright}` | ArrowRight | N/A | |
| `{shift}` | Shift | `shiftKey` | Does **not** capitalize following characters. |
| `{ctrl}` | Control | `ctrlKey` | |
| `{alt}` | Alt | `altKey` | |
| `{meta}` | OS | `metaKey` | |
| `{capslock}` | CapsLock | `modifierCapsLock` | Fires both keydown and keyup when used (simulates a user clicking their "Caps Lock" button to enable caps lock). |

> **A note about modifiers:** Modifier keys (`{shift}`, `{ctrl}`, `{alt}`,
> `{meta}`) will activate their corresponding event modifiers for the duration
Expand Down Expand Up @@ -609,6 +609,7 @@ Thanks goes to these people ([emoji key][emojis]):

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
33 changes: 33 additions & 0 deletions src/__tests__/type-modifiers.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,39 @@ test('{shift}a{/shift}', () => {
`)
})

test('{capslock}a{/capslock}', () => {
const {element, getEventSnapshot} = setup('<input />')

userEvent.type(element, '{capslock}a{/capslock}')

expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="a"]
input[value=""] - pointerover
input[value=""] - pointerenter
input[value=""] - mouseover: Left (0)
input[value=""] - mouseenter: Left (0)
input[value=""] - pointermove
input[value=""] - mousemove: Left (0)
input[value=""] - pointerdown
input[value=""] - mousedown: Left (0)
input[value=""] - focus
input[value=""] - focusin
input[value=""] - pointerup
input[value=""] - mouseup: Left (0)
input[value=""] - click: Left (0)
input[value=""] - keydown: CapsLock (20)
input[value=""] - keyup: CapsLock (20)
input[value=""] - keydown: a (97)
input[value=""] - keypress: a (97)
input[value="a"] - input
"{CURSOR}" -> "a{CURSOR}"
input[value="a"] - keyup: a (97)
input[value="a"] - keydown: CapsLock (20)
input[value="a"] - keyup: CapsLock (20)
`)
})

test('a{enter}', () => {
const {element, getEventSnapshot} = setup('<input />')

Expand Down
41 changes: 41 additions & 0 deletions src/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,47 @@ const modifierCallbackMap = {
keyCode: 93,
modifierProperty: 'metaKey',
}),
// capslock is inline because of the need to fire both keydown and keyup on use, while preserving the modifier state.
'{capslock}': function capslockOn({currentElement, eventOverrides}) {
const newEventOverrides = {modifierCapsLock: true}

fireEvent.keyDown(currentElement(), {
key: 'CapsLock',
keyCode: 20,
which: 20,
...eventOverrides,
...newEventOverrides,
})
fireEvent.keyUp(currentElement(), {
key: 'CapsLock',
keyCode: 20,
which: 20,
...eventOverrides,
...newEventOverrides,
})

return {eventOverrides: newEventOverrides}
},
'{/capslock}': function capslockOff({currentElement, eventOverrides}) {
const newEventOverrides = {modifierCapsLock: false}

fireEvent.keyDown(currentElement(), {
key: 'CapsLock',
keyCode: 20,
which: 20,
...eventOverrides,
...newEventOverrides,
})
fireEvent.keyUp(currentElement(), {
key: 'CapsLock',
keyCode: 20,
which: 20,
...eventOverrides,
...newEventOverrides,
})

return {eventOverrides: newEventOverrides}
},
}

const specialCharCallbackMap = {
Expand Down

0 comments on commit 9344db6

Please sign in to comment.