|
1 | 1 | import { ReactTestInstance } from 'react-test-renderer';
|
2 | 2 | import { jestFakeTimersAreEnabled } from '../../helpers/timers';
|
3 |
| -import { PressOptions, press, longPress } from '../press'; |
4 |
| -import { TypeOptions, type } from '../type'; |
| 3 | +import { wrapAsync } from '../../helpers/wrap-async'; |
5 | 4 | import { clear } from '../clear';
|
| 5 | +import { PressOptions, press, longPress } from '../press'; |
6 | 6 | import { ScrollToOptions, scrollTo } from '../scroll';
|
| 7 | +import { TypeOptions, type } from '../type'; |
| 8 | +import { wait } from '../utils'; |
7 | 9 |
|
8 | 10 | export interface UserEventSetupOptions {
|
9 | 11 | /**
|
@@ -141,15 +143,42 @@ function createInstance(config: UserEventConfig): UserEventInstance {
|
141 | 143 | config,
|
142 | 144 | } as UserEventInstance;
|
143 | 145 |
|
144 |
| - // We need to bind these functions, as they access the config through 'this.config'. |
| 146 | + // Bind interactions to given User Event instance. |
145 | 147 | const api = {
|
146 |
| - press: press.bind(instance), |
147 |
| - longPress: longPress.bind(instance), |
148 |
| - type: type.bind(instance), |
149 |
| - clear: clear.bind(instance), |
150 |
| - scrollTo: scrollTo.bind(instance), |
| 148 | + press: wrapAndBindImpl(instance, press), |
| 149 | + longPress: wrapAndBindImpl(instance, longPress), |
| 150 | + type: wrapAndBindImpl(instance, type), |
| 151 | + clear: wrapAndBindImpl(instance, clear), |
| 152 | + scrollTo: wrapAndBindImpl(instance, scrollTo), |
151 | 153 | };
|
152 | 154 |
|
153 | 155 | Object.assign(instance, api);
|
154 | 156 | return instance;
|
155 | 157 | }
|
| 158 | + |
| 159 | +/** |
| 160 | + * Wraps user interaction with `wrapAsync` (temporarily disable `act` environment while |
| 161 | + * calling & resolving the async callback, then flush the microtask queue) |
| 162 | + * |
| 163 | + * This implementation is sourced from `testing-library/user-event` |
| 164 | + * @see https://github.com/testing-library/user-event/blob/7a305dee9ab833d6f338d567fc2e862b4838b76a/src/setup/setup.ts#L121 |
| 165 | + */ |
| 166 | +function wrapAndBindImpl< |
| 167 | + Args extends any[], |
| 168 | + Impl extends (this: UserEventInstance, ...args: Args) => Promise<unknown> |
| 169 | +>(instance: UserEventInstance, impl: Impl) { |
| 170 | + function method(...args: Args) { |
| 171 | + return wrapAsync(() => |
| 172 | + // eslint-disable-next-line promise/prefer-await-to-then |
| 173 | + impl.apply(instance, args).then(async (result) => { |
| 174 | + await wait(instance.config); |
| 175 | + return result; |
| 176 | + }) |
| 177 | + ); |
| 178 | + } |
| 179 | + |
| 180 | + // Copy implementation name to the returned function |
| 181 | + Object.defineProperty(method, 'name', { get: () => impl.name }); |
| 182 | + |
| 183 | + return method as Impl; |
| 184 | +} |
0 commit comments