Skip to content

Commit 28d6604

Browse files
authored
fix: log correct docs link for invalid key descriptors (#881)
1 parent e971a34 commit 28d6604

File tree

5 files changed

+64
-38
lines changed

5 files changed

+64
-38
lines changed

src/keyboard/parseKeyDef.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function parseKeyDef(keyboardMap: keyboardKey[], text: string) {
2727
releasePrevious,
2828
releaseSelf = true,
2929
repeat,
30-
} = readNextDescriptor(text)
30+
} = readNextDescriptor(text, 'keyboard')
3131

3232
const keyDef = keyboardMap.find(def => {
3333
if (type === '[') {

src/pointer/parseKeyDef.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export function parseKeyDef(pointerMap: pointerKey[], keys: string) {
1414
consumedLength,
1515
releasePrevious,
1616
releaseSelf = true,
17-
} = readNextDescriptor(keys)
17+
} = readNextDescriptor(keys, 'pointer')
1818
const keyDef = pointerMap.find(p => p.name === descriptor)
1919

2020
if (keyDef) {

src/utils/keyDef/readNextDescriptor.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ enum bracketDict {
33
'[' = ']',
44
}
55

6+
type Context = 'pointer' | 'keyboard'
7+
68
/**
79
* Read the next key definition from user input
810
*
@@ -14,7 +16,7 @@ enum bracketDict {
1416
* When keeping the key pressed you can choose how long the key is pressed `{descriptor>3}`.
1517
* You can then release the key per `{descriptor>3/}` or keep it pressed and continue with the next key.
1618
*/
17-
export function readNextDescriptor(text: string) {
19+
export function readNextDescriptor(text: string, context: Context) {
1820
let pos = 0
1921
const startBracket =
2022
text[pos] in bracketDict ? (text[pos] as keyof typeof bracketDict) : ''
@@ -27,14 +29,16 @@ export function readNextDescriptor(text: string) {
2729

2830
return {
2931
type,
30-
...(type === '' ? readPrintableChar(text, pos) : readTag(text, pos, type)),
32+
...(type === ''
33+
? readPrintableChar(text, pos, context)
34+
: readTag(text, pos, type, context)),
3135
}
3236
}
3337

34-
function readPrintableChar(text: string, pos: number) {
38+
function readPrintableChar(text: string, pos: number, context: Context) {
3539
const descriptor = text[pos]
3640

37-
assertDescriptor(descriptor, text, pos)
41+
assertDescriptor(descriptor, text, pos, context)
3842

3943
pos += descriptor.length
4044

@@ -51,6 +55,7 @@ function readTag(
5155
text: string,
5256
pos: number,
5357
startBracket: keyof typeof bracketDict,
58+
context: Context,
5459
) {
5560
const releasePreviousModifier = text[pos] === '/' ? '/' : ''
5661

@@ -64,7 +69,7 @@ function readTag(
6469
? text[pos]
6570
: text.slice(pos).match(startBracket === '{' ? /^\w+|^[^}>/]/ : /^\w+/)?.[0]
6671

67-
assertDescriptor(descriptor, text, pos)
72+
assertDescriptor(descriptor, text, pos, context)
6873

6974
pos += descriptor.length
7075

@@ -92,6 +97,7 @@ function readTag(
9297
.join(' or '),
9398
text[pos],
9499
text,
100+
context,
95101
),
96102
)
97103
}
@@ -111,9 +117,10 @@ function assertDescriptor(
111117
descriptor: string | undefined,
112118
text: string,
113119
pos: number,
120+
context: Context,
114121
): asserts descriptor is string {
115122
if (!descriptor) {
116-
throw new Error(getErrorMessage('key descriptor', text[pos], text))
123+
throw new Error(getErrorMessage('key descriptor', text[pos], text, context))
117124
}
118125
}
119126

@@ -131,8 +138,13 @@ function getErrorMessage(
131138
expected: string,
132139
found: string | undefined,
133140
text: string,
141+
context: Context,
134142
) {
135143
return `Expected ${expected} but found "${found ?? ''}" in "${text}"
136-
See https://github.com/testing-library/user-event/blob/main/README.md#keyboardtext-options
144+
See ${
145+
context === 'pointer'
146+
? `https://testing-library.com/docs/user-event/pointer#pressing-a-button-or-touching-the-screen`
147+
: `https://testing-library.com/docs/user-event/keyboard`
148+
}
137149
for more information about how userEvent parses your input.`
138150
}

tests/keyboard/parseKeyDef.ts

-29
Original file line numberDiff line numberDiff line change
@@ -110,32 +110,3 @@ cases(
110110
},
111111
},
112112
)
113-
114-
cases(
115-
'errors',
116-
({text, expectedError}) => {
117-
expect(() => parseKeyDef(defaultKeyMap, `${text}`)).toThrow(expectedError)
118-
},
119-
{
120-
'missing descriptor': {
121-
text: '',
122-
expectedError: 'but found "" in ""',
123-
},
124-
'missing closing bracket': {
125-
text: '{a)',
126-
expectedError: 'but found ")" in "{a)"',
127-
},
128-
'invalid repeat modifier': {
129-
text: '{a>e}',
130-
expectedError: 'but found "e" in "{a>e}"',
131-
},
132-
'missing bracket after repeat modifier': {
133-
text: '{a>3)',
134-
expectedError: 'but found ")" in "{a>3)"',
135-
},
136-
'unescaped modifier': {
137-
text: '{/>5}',
138-
expectedError: 'but found ">" in "{/>5}"',
139-
},
140-
},
141-
)
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import cases from 'jest-in-case'
2+
import {readNextDescriptor} from '#src/utils'
3+
import userEvent from '#src'
4+
5+
cases(
6+
'errors',
7+
({text, expectedError}) => {
8+
expect(() => readNextDescriptor(`${text}`, 'keyboard')).toThrow(
9+
expectedError,
10+
)
11+
},
12+
{
13+
'missing descriptor': {
14+
text: '',
15+
expectedError: 'but found "" in ""',
16+
},
17+
'missing closing bracket': {
18+
text: '{a)',
19+
expectedError: 'but found ")" in "{a)"',
20+
},
21+
'invalid repeat modifier': {
22+
text: '{a>e}',
23+
expectedError: 'but found "e" in "{a>e}"',
24+
},
25+
'missing bracket after repeat modifier': {
26+
text: '{a>3)',
27+
expectedError: 'but found ")" in "{a>3)"',
28+
},
29+
'unescaped modifier': {
30+
text: '{/>5}',
31+
expectedError: 'but found ">" in "{/>5}"',
32+
},
33+
},
34+
)
35+
36+
test('include appropriate docs link in error message', async () => {
37+
await expect(() => userEvent.keyboard('{')).rejects.toThrow(
38+
'docs/user-event/keyboard',
39+
)
40+
await expect(() => userEvent.pointer('{')).rejects.toThrow(
41+
'docs/user-event/pointer',
42+
)
43+
})

0 commit comments

Comments
 (0)