Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Remove react 17 compat from react-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-page committed Aug 21, 2024
1 parent d8f377c commit df5d12a
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 113 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-spiders-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/react-testing': major
---

Remove React 17 compatability
68 changes: 0 additions & 68 deletions packages/react-testing/src/compat.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,5 @@
import ReactDOM from 'react-dom';
import React from 'react';
import type {Root as ReactRoot} from 'react-dom/client';
import {act as oldAct} from 'react-dom/test-utils';

import type {ReactInstance, Fiber} from './types';

export function getInternals(instance: ReactInstance): Fiber {
// In React 17+ _reactInternalFiber was renamed to _reactInternals. As such we need to handle both APIs to maintain support.

if ('_reactInternalFiber' in instance) {
return instance._reactInternalFiber;
}

return instance._reactInternals;
}

/** Shim to provide createRoot backwards compatibility for React < 18 */
function createRootShim(element: HTMLElement): ReactRoot {
/* eslint-disable react/no-deprecated */
return {
render(children: React.ReactChild | Iterable<React.ReactNode>): void {
ReactDOM.render(children as any, element as any);
},
unmount(): void {
ReactDOM.unmountComponentAtNode(element as any);
},
};
/* eslint-enable react/no-deprecated */
}

/** Uses React >= 18 createRoot if available or falls back to shim*/
export function createRoot(element: HTMLElement): ReactRoot {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
return require('react-dom/client').createRoot(element);
} catch {
return createRootShim(element);
}
}

export const isLegacyReact = parseInt(React.version, 10) < 18;

export const act: typeof oldAct = (() => {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -50,30 +9,3 @@ export const act: typeof oldAct = (() => {
return oldAct;
}
})();

// https://github.com/facebook/react/blob/12adaffef7105e2714f82651ea51936c563fe15c/packages/shared/enqueueTask.js#L13
let enqueueTaskImpl: any = null;

export function enqueueTask(task: (v: any) => void) {
if (enqueueTaskImpl === null) {
try {
// read require off the module object to get around the bundlers.
// we don't want them to detect a require and bundle a Node polyfill.
const requireString = `require${Math.random()}`.slice(0, 7);
const nodeRequire = module && module[requireString];
// assuming we're in node, let's try to get node's
// version of setImmediate, bypassing fake timers if any.
enqueueTaskImpl = nodeRequire.call(module, 'timers').setImmediate;
} catch (_err) {
// we're in a browser
// we can't use regular timers because they may still be faked
// so we try MessageChannel+postMessage instead
enqueueTaskImpl = function (callback: () => void) {
const channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage(undefined);
};
}
}
return enqueueTaskImpl!(task);
}
16 changes: 3 additions & 13 deletions packages/react-testing/src/root.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import React from 'react';
import {createRoot} from 'react-dom/client';
import {flushSync} from 'react-dom';
import type {Root as ReactRoot} from 'react-dom/client';
import {findCurrentFiberUsingSlowPath} from 'react-reconciler/reflection.js';

import {TestWrapper} from './TestWrapper';
import {Element} from './element';
import {
createRoot,
getInternals,
enqueueTask,
isLegacyReact,
act,
} from './compat';
import {act} from './compat';
import type {
Fiber,
Node,
Expand Down Expand Up @@ -316,11 +311,6 @@ export class Root<Props> implements Node<Props> {
this.destroyed = true;
await mountedPromise;
this.actCallbacks.forEach((callback) => callback());

if (isLegacyReact) {
// flush macro task for react 17 only
await new Promise((resolve) => enqueueTask(resolve));
}
}

setProps(props: Partial<Props>) {
Expand All @@ -346,7 +336,7 @@ export class Root<Props> implements Node<Props> {
if (this.wrapper == null) {
this.root = null;
} else if (this.mounted) {
const rootFiber = getInternals(this.wrapper.rootRef as any);
const rootFiber = (this.wrapper.rootRef as any)._reactInternals;
const topElement = fiberToElement(
findCurrentFiberUsingSlowPath(rootFiber),
this,
Expand Down
14 changes: 0 additions & 14 deletions packages/react-testing/src/tests/compat.test.tsx

This file was deleted.

11 changes: 0 additions & 11 deletions packages/react-testing/src/tests/root.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@ describe('Root', () => {
await destroyAll();
});

it('works with react 16 style nodes', () => {
const root = new Root(<div />);

// in React 17 _reactInternalFiber is renamed to _reactInternals
const rootRef = (root as any).wrapper.rootRef;
rootRef._reactInternalFiber = rootRef._reactInternals;
delete rootRef._reactInternals;

expect(() => root.act(() => {})).not.toThrow();
});

it('delegates calls to the root element', () => {
const root = new Root(<div />);

Expand Down
10 changes: 3 additions & 7 deletions packages/react-testing/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,9 @@ export interface Fiber {
memoizedState: unknown;
}

export type ReactInstance =
| {
_reactInternals: Fiber;
}
| {
_reactInternalFiber: Fiber;
};
export interface ReactInstance {
_reactInternals: Fiber;
}

export type Predicate = (node: Node<unknown>) => boolean;

Expand Down

0 comments on commit df5d12a

Please sign in to comment.