Skip to content

Commit 6b73d5d

Browse files
committed
Fork dispatchEvent, fix and add tests
1 parent e6e144c commit 6b73d5d

File tree

4 files changed

+827
-86
lines changed

4 files changed

+827
-86
lines changed

packages/internal-test-utils/ReactInternalTestUtils.js

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as SchedulerMock from 'scheduler/unstable_mock';
99
import {diff} from 'jest-diff';
1010
import {equals} from '@jest/expect-utils';
1111
import enqueueTask from './enqueueTask';
12+
import simulateBrowserEventDispatch from './simulateBrowserEventDispatch';
1213

1314
export {act} from './internalAct';
1415

@@ -267,37 +268,37 @@ ${diff(expectedLog, actualLog)}
267268

268269
// Simulates dispatching events, waiting for microtasks in between.
269270
// This matches the browser behavior, which will flush microtasks
270-
// between each event handler.
271-
export async function dispatchAndWaitForDiscrete(
271+
// between each event handler. This will allow discrete events to
272+
// flush between events across different event handlers.
273+
export async function simulateEventDispatch(
272274
node: Node,
273275
eventType: string,
274276
): Promise<void> {
275-
assertYieldsWereCleared(waitForDiscrete);
276-
277-
// Bubbling phase
278-
// Walk the path from the element to the document and dispatch
279-
// the event on each node, flushing microtasks in between.
277+
// Ensure the node is in the document.
280278
for (let current = node; current; current = current.parentNode) {
281-
const customEvent = new Event(eventType, {
282-
bubbles: false,
283-
cancelable: true,
284-
});
285-
286-
Object.defineProperty(customEvent, 'eventPhase', {
287-
// Avoid going through the capture/bubbling phases,
288-
// since we're doing it manually.
289-
value: Event.AT_TARGET,
290-
});
291-
292-
Object.defineProperty(customEvent, 'target', {
293-
// Override the target to the node on which we dispatched the event.
294-
value: node,
295-
});
296-
297-
// Dispatch the event on the target
298-
current.dispatchEvent(customEvent);
299-
300-
// Flush microtasks
301-
await waitForMicrotasks();
279+
if (current === document) {
280+
break;
281+
} else if (current.parentNode == null) {
282+
return;
283+
}
284+
}
285+
286+
const customEvent = new Event(eventType, {
287+
bubbles: true,
288+
});
289+
290+
Object.defineProperty(customEvent, 'target', {
291+
// Override the target to the node on which we dispatched the event.
292+
value: node,
293+
});
294+
295+
const impl = Object.getOwnPropertySymbols(node)[0];
296+
const oldDispatch = node[impl].dispatchEvent;
297+
try {
298+
node[impl].dispatchEvent = simulateBrowserEventDispatch;
299+
300+
await node.dispatchEvent(customEvent);
301+
} finally {
302+
node[impl].dispatchEvent = oldDispatch;
302303
}
303304
}

0 commit comments

Comments
 (0)