Skip to content

Commit 5d9d352

Browse files
authored
Merge branch 'main' into all-contributors/add-xDisfigure
2 parents cee3f58 + 7b0643b commit 5d9d352

13 files changed

Lines changed: 111 additions & 31 deletions

File tree

.all-contributorsrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,16 @@
12071207
"contributions": [
12081208
"bug"
12091209
]
1210+
},
1211+
{
1212+
"login": "karolis-cekaitis",
1213+
"name": "Karolis Čekaitis",
1214+
"avatar_url": "https://avatars.githubusercontent.com/u/89905443?v=4",
1215+
"profile": "https://github.com/karolis-cekaitis",
1216+
"contributions": [
1217+
"bug",
1218+
"doc"
1219+
]
12101220
}
12111221
],
12121222
"commitConvention": "none",

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ Thanks goes to these wonderful people ([emoji key][emojis]):
165165
<td align="center"><a href="https://github.com/tbertrand7"><img src="https://avatars.githubusercontent.com/u/14081248?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tom Bertrand</b></sub></a><br /><a href="https://github.com/testing-library/user-event/issues?q=author%3Atbertrand7" title="Bug reports">🐛</a></td>
166166
<td align="center"><a href="https://justinrhall.dev"><img src="https://avatars.githubusercontent.com/u/1288694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="https://github.com/testing-library/user-event/issues?q=author%3AwKovacs64" title="Bug reports">🐛</a></td>
167167
<td align="center"><a href="https://github.com/xDisfigure"><img src="https://avatars.githubusercontent.com/u/7613287?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thomas ROCHA</b></sub></a><br /><a href="https://github.com/testing-library/user-event/issues?q=author%3AxDisfigure" title="Bug reports">🐛</a></td>
168+
<td align="center"><a href="https://github.com/karolis-cekaitis"><img src="https://avatars.githubusercontent.com/u/89905443?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Karolis Čekaitis</b></sub></a><br /><a href="https://github.com/testing-library/user-event/issues?q=author%3Akarolis-cekaitis" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/user-event/commits?author=karolis-cekaitis" title="Documentation">📖</a></td>
168169
</tr>
169170
</table>
170171

src/document/index.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import {dispatchUIEvent} from '../event'
22
import {Config} from '../setup'
33
import {prepareSelectionInterceptor} from './selection'
44
import {
5+
clearInitialValue,
56
getInitialValue,
67
prepareValueInterceptor,
7-
setInitialValue,
88
} from './value'
99

1010
const isPrepared = Symbol('Node prepared with document state workarounds')
@@ -45,8 +45,11 @@ export function prepareDocument(document: Document) {
4545
e => {
4646
const el = e.target as HTMLInputElement
4747
const initialValue = getInitialValue(el)
48-
if (typeof initialValue === 'string' && el.value !== initialValue) {
49-
dispatchUIEvent({} as Config, el, 'change')
48+
if (initialValue !== undefined) {
49+
if (el.value !== initialValue) {
50+
dispatchUIEvent({} as Config, el, 'change')
51+
}
52+
clearInitialValue(el)
5053
}
5154
},
5255
{
@@ -59,10 +62,6 @@ export function prepareDocument(document: Document) {
5962
}
6063

6164
function prepareElement(el: Node | HTMLInputElement) {
62-
if ('value' in el) {
63-
setInitialValue(el)
64-
}
65-
6665
if (el[isPrepared]) {
6766
return
6867
}
@@ -75,6 +74,12 @@ function prepareElement(el: Node | HTMLInputElement) {
7574
el[isPrepared] = isPrepared
7675
}
7776

78-
export {getUIValue, setUIValue, startTrackValue, endTrackValue} from './value'
77+
export {
78+
getUIValue,
79+
setUIValue,
80+
startTrackValue,
81+
endTrackValue,
82+
clearInitialValue,
83+
} from './value'
7984
export {getUISelection, setUISelection} from './selection'
8085
export type {UISelectionRange} from './selection'

src/document/interceptor.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export function prepareInterceptor<
2828
*/
2929
applyNative?: boolean
3030
realArgs?: ImplReturn<ElementType[PropName]>
31+
then?: () => void
3132
},
3233
) {
3334
const prototypeDescriptor = Object.getOwnPropertyDescriptor(
@@ -49,7 +50,11 @@ export function prepareInterceptor<
4950
this: ElementType,
5051
...args: Params<ElementType[PropName]>
5152
) {
52-
const {applyNative = true, realArgs} = interceptorImpl.call(this, ...args)
53+
const {
54+
applyNative = true,
55+
realArgs,
56+
then,
57+
} = interceptorImpl.call(this, ...args)
5358

5459
const realFunc = ((!applyNative && objectDescriptor) ||
5560
(prototypeDescriptor as PropertyDescriptor))[target] as (
@@ -62,6 +67,8 @@ export function prepareInterceptor<
6267
} else {
6368
realFunc.call(this, ...realArgs)
6469
}
70+
71+
then?.()
6572
}
6673
;(intercept as Interceptable)[Interceptor] = Interceptor
6774

src/document/value.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ function valueInterceptor(
3232
if (isUI) {
3333
this[UIValue] = String(v)
3434
setPreviousValue(this, String(this.value))
35-
} else {
36-
trackOrSetValue(this, String(v))
3735
}
3836

3937
return {
4038
applyNative: !!isUI,
4139
realArgs: sanitizeValue(this, v),
40+
then: isUI ? undefined : () => trackOrSetValue(this, String(v)),
4241
}
4342
}
4443

@@ -66,6 +65,10 @@ export function setUIValue(
6665
element: HTMLInputElement | HTMLTextAreaElement,
6766
value: string,
6867
) {
68+
if (element[InitialValue] === undefined) {
69+
element[InitialValue] = element.value
70+
}
71+
6972
element.value = {
7073
[UIValue]: UIValue,
7174
toString: () => value,
@@ -78,10 +81,10 @@ export function getUIValue(element: HTMLInputElement | HTMLTextAreaElement) {
7881
: String(element[UIValue])
7982
}
8083

81-
export function setInitialValue(
84+
export function clearInitialValue(
8285
element: HTMLInputElement | HTMLTextAreaElement,
8386
) {
84-
element[InitialValue] = element.value
87+
element[InitialValue] = undefined
8588
}
8689

8790
export function getInitialValue(
@@ -123,7 +126,6 @@ function setCleanValue(
123126
v: string,
124127
) {
125128
element[UIValue] = undefined
126-
element[InitialValue] = v
127129

128130
// Programmatically setting the value property
129131
// moves the cursor to the end of the input.

src/keyboard/keyboardAction.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ export async function keyboardAction(
2222
for (let i = 0; i < actions.length; i++) {
2323
await keyboardKeyAction(config, actions[i])
2424

25-
if (typeof config.delay === 'number' && i < actions.length - 1) {
26-
await wait(config.delay)
25+
if (i < actions.length - 1) {
26+
await wait(config)
2727
}
2828
}
2929
}
@@ -32,7 +32,7 @@ async function keyboardKeyAction(
3232
config: Config,
3333
{keyDef, releasePrevious, releaseSelf, repeat}: KeyboardAction,
3434
) {
35-
const {document, keyboardState, delay} = config
35+
const {document, keyboardState} = config
3636
const getCurrentElement = () => getActive(document)
3737

3838
// Release the key automatically if it was pressed before.
@@ -50,8 +50,8 @@ async function keyboardKeyAction(
5050
await keypress(keyDef, getCurrentElement, config)
5151
}
5252

53-
if (typeof delay === 'number' && i < repeat) {
54-
await wait(delay)
53+
if (i < repeat) {
54+
await wait(config)
5555
}
5656
}
5757

src/options.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ export interface Options {
120120
* Defaults to `true` when calling the APIs per `setup`.
121121
*/
122122
writeToClipboard?: boolean
123+
124+
/**
125+
* A function to be called internally to advance your fake timers (if applicable)
126+
*
127+
* @example jest.advanceTimersByTime
128+
*/
129+
advanceTimers?: ((delay: number) => Promise<void>) | ((delay: number) => void)
123130
}
124131

125132
/**
@@ -137,6 +144,7 @@ export const defaultOptionsDirect: Required<Options> = {
137144
skipClick: false,
138145
skipHover: false,
139146
writeToClipboard: false,
147+
advanceTimers: () => Promise.resolve(),
140148
}
141149

142150
/**

src/pointer/pointerAction.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ export async function pointerAction(config: Config, actions: PointerAction[]) {
3737
? pointerPress(config, {...action, target, coords})
3838
: pointerMove(config, {...action, target, coords}))
3939

40-
if (typeof config.delay === 'number') {
41-
if (i < actions.length - 1) {
42-
await wait(config.delay)
43-
}
40+
if (i < actions.length - 1) {
41+
await wait(config)
4442
}
4543
}
4644

src/utils/edit/input.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
clearInitialValue,
23
endTrackValue,
34
getUIValue,
45
setUIValue,
@@ -128,7 +129,7 @@ function editInputElement(
128129
) {
129130
let dataToInsert = data
130131
const spaceUntilMaxLength = getSpaceUntilMaxLength(element)
131-
if (spaceUntilMaxLength !== undefined) {
132+
if (spaceUntilMaxLength !== undefined && data.length > 0) {
132133
if (spaceUntilMaxLength > 0) {
133134
dataToInsert = data.substring(0, spaceUntilMaxLength)
134135
} else {
@@ -169,6 +170,7 @@ function editInputElement(
169170
if (isValidDateOrTimeValue(element, newValue)) {
170171
commitInput(config, element, newOffset, {})
171172
dispatchUIEvent(config, element, 'change')
173+
clearInitialValue(element)
172174
}
173175
} else {
174176
commitInput(config, element, newOffset, {

src/utils/misc/wait.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1-
export function wait(time?: number) {
2-
return new Promise<void>(resolve => setTimeout(() => resolve(), time))
1+
import {Config} from '../../setup'
2+
3+
export function wait(config: Config) {
4+
const delay = config.delay
5+
if (typeof delay !== 'number') {
6+
return
7+
}
8+
return Promise.all([
9+
new Promise<void>(resolve => setTimeout(() => resolve(), delay)),
10+
config.advanceTimers(delay),
11+
])
312
}

0 commit comments

Comments
 (0)