Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Fixes

- `[expect]` Fix `bigint` error ([#15702](https://github.com/jestjs/jest/pull/15702))
- `[pretty-format]` Fix support for React 19 ([#15729](https://github.com/jestjs/jest/pull/15729))

## 30.0.4

Expand Down
4 changes: 1 addition & 3 deletions packages/pretty-format/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@
"author": "James Kyle <[email protected]>",
"dependencies": {
"@jest/schemas": "workspace:*",
"ansi-styles": "^5.2.0",
"react-is": "^18.3.1"
"ansi-styles": "^5.2.0"
},
"devDependencies": {
"@types/react": "^18.3.23",
"@types/react-is": "^18.3.1",
"@types/react-test-renderer": "^18.3.1",
"immutable": "^5.1.2",
"jest-util": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/pretty-format/src/plugins/ReactElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/

import * as ReactIs from 'react-is';
import type {Config, NewPlugin, Printer, Refs} from '../types';
import * as ReactIs from './lib/ReactIs';
import {
printChildren,
printElement,
Expand Down
170 changes: 170 additions & 0 deletions packages/pretty-format/src/plugins/lib/ReactIs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
// This file is mostly copy-pasted from the original react-is library,
// with some modifications to support React versions < 19.
// https://github.com/facebook/react/blob/main/packages/react-is/src/ReactIs.js

// Customizations:
// - Added support for REACT_LEGACY_ELEMENT_TYPE wherever REACT_ELEMENT_TYPE is used.
// - Added support for REACT_PROVIDER_TYPE wherever REACT_CONTEXT_TYPE is used.
// - Added support for REACT_SERVER_CONTEXT_TYPE in typeOf function with the same logic as REACT_CONTEXT_TYPE.
// - Added support for REACT_OFFSCREEN_TYPE in isValidElementType function.
// - TypeScript type `mixed` replaced with `any`.

// Types collected from https://github.com/facebook/react/blob/main/packages/shared/ReactSymbols.js
const REACT_LEGACY_ELEMENT_TYPE: symbol = Symbol.for('react.element');
const REACT_ELEMENT_TYPE: symbol = Symbol.for('react.transitional.element');
const REACT_PORTAL_TYPE: symbol = Symbol.for('react.portal');
const REACT_FRAGMENT_TYPE: symbol = Symbol.for('react.fragment');
const REACT_STRICT_MODE_TYPE: symbol = Symbol.for('react.strict_mode');
const REACT_PROFILER_TYPE: symbol = Symbol.for('react.profiler');
const REACT_CONSUMER_TYPE: symbol = Symbol.for('react.consumer');
const REACT_CONTEXT_TYPE: symbol = Symbol.for('react.context');
const REACT_FORWARD_REF_TYPE: symbol = Symbol.for('react.forward_ref');
const REACT_SUSPENSE_TYPE: symbol = Symbol.for('react.suspense');
const REACT_SUSPENSE_LIST_TYPE: symbol = Symbol.for('react.suspense_list');
const REACT_MEMO_TYPE: symbol = Symbol.for('react.memo');
const REACT_LAZY_TYPE: symbol = Symbol.for('react.lazy');
const REACT_VIEW_TRANSITION_TYPE: symbol = Symbol.for('react.view_transition');
const REACT_CLIENT_REFERENCE: symbol = Symbol.for('react.client.reference');

// Legacy types not present in React 19+
const REACT_PROVIDER_TYPE: symbol = Symbol.for('react.provider');
const REACT_SERVER_CONTEXT_TYPE: symbol = Symbol.for('react.server_context');
const REACT_OFFSCREEN_TYPE: symbol = Symbol.for('react.offscreen');

// Below is a copy of ReactIs.js with customizations listed above.

export function typeOf(object: any): any {
if (typeof object === 'object' && object !== null) {
const $$typeof = object.$$typeof;
switch ($$typeof) {
case REACT_LEGACY_ELEMENT_TYPE:
case REACT_ELEMENT_TYPE:
const type = object.type;

switch (type) {
case REACT_FRAGMENT_TYPE:
case REACT_PROFILER_TYPE:
case REACT_STRICT_MODE_TYPE:
case REACT_SUSPENSE_TYPE:
case REACT_SUSPENSE_LIST_TYPE:
case REACT_VIEW_TRANSITION_TYPE:
return type;
default:
const $$typeofType = type && type.$$typeof;

switch ($$typeofType) {
case REACT_PROVIDER_TYPE:
case REACT_CONTEXT_TYPE:
case REACT_SERVER_CONTEXT_TYPE:
case REACT_FORWARD_REF_TYPE:
case REACT_LAZY_TYPE:
case REACT_MEMO_TYPE:
return $$typeofType;
case REACT_CONSUMER_TYPE:
return $$typeofType;

Check warning on line 65 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L64-L65

Added lines #L64 - L65 were not covered by tests
// Fall through
default:
return $$typeof;
}
}
case REACT_PORTAL_TYPE:
return $$typeof;

Check warning on line 72 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L71-L72

Added lines #L71 - L72 were not covered by tests
}
}

return undefined;

Check warning on line 76 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L76

Added line #L76 was not covered by tests
}

export const ContextConsumer: symbol = REACT_CONSUMER_TYPE;
export const ContextProvider: symbol = REACT_CONTEXT_TYPE;
export const Element = REACT_ELEMENT_TYPE;
export const ForwardRef = REACT_FORWARD_REF_TYPE;
export const Fragment = REACT_FRAGMENT_TYPE;
export const Lazy = REACT_LAZY_TYPE;
export const Memo = REACT_MEMO_TYPE;
export const Portal = REACT_PORTAL_TYPE;
export const Profiler = REACT_PROFILER_TYPE;
export const StrictMode = REACT_STRICT_MODE_TYPE;
export const Suspense = REACT_SUSPENSE_TYPE;
export const SuspenseList = REACT_SUSPENSE_LIST_TYPE;

export function isValidElementType(type: any): boolean {

Check warning on line 92 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L92

Added line #L92 was not covered by tests
if (typeof type === 'string' || typeof type === 'function') {
return true;

Check warning on line 94 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L94

Added line #L94 was not covered by tests
}

// Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
if (
type === REACT_FRAGMENT_TYPE ||
type === REACT_PROFILER_TYPE ||
type === REACT_STRICT_MODE_TYPE ||
type === REACT_SUSPENSE_TYPE ||
type === REACT_SUSPENSE_LIST_TYPE ||
type === REACT_OFFSCREEN_TYPE

Check warning on line 104 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L100-L104

Added lines #L100 - L104 were not covered by tests
) {
return true;

Check warning on line 106 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L106

Added line #L106 was not covered by tests
}

if (typeof type === 'object' && type !== null) {
if (
type.$$typeof === REACT_LAZY_TYPE ||
type.$$typeof === REACT_MEMO_TYPE ||
type.$$typeof === REACT_PROVIDER_TYPE ||
type.$$typeof === REACT_CONTEXT_TYPE ||
type.$$typeof === REACT_CONSUMER_TYPE ||
type.$$typeof === REACT_FORWARD_REF_TYPE ||

Check warning on line 116 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L112-L116

Added lines #L112 - L116 were not covered by tests
// This needs to include all possible module reference object
// types supported by any Flight configuration anywhere since
// we don't know which Flight build this will end up being used
// with.
type.$$typeof === REACT_CLIENT_REFERENCE ||
type.getModuleId !== undefined

Check warning on line 122 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L121-L122

Added lines #L121 - L122 were not covered by tests
) {
return true;

Check warning on line 124 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L124

Added line #L124 was not covered by tests
}
}

return false;

Check warning on line 128 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L128

Added line #L128 was not covered by tests
}

export function isContextConsumer(object: any): boolean {
return typeOf(object) === REACT_CONSUMER_TYPE;
}
export function isContextProvider(object: any): boolean {
return [REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE].includes(typeOf(object));
}
export function isElement(object: any): boolean {
return (
typeof object === 'object' &&
object !== null &&
[REACT_ELEMENT_TYPE, REACT_LEGACY_ELEMENT_TYPE].includes(object.$$typeof)
);
}
export function isForwardRef(object: any): boolean {
return typeOf(object) === REACT_FORWARD_REF_TYPE;
}
export function isFragment(object: any): boolean {
return typeOf(object) === REACT_FRAGMENT_TYPE;
}
export function isLazy(object: any): boolean {
return typeOf(object) === REACT_LAZY_TYPE;

Check warning on line 151 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L150-L151

Added lines #L150 - L151 were not covered by tests
}
export function isMemo(object: any): boolean {
return typeOf(object) === REACT_MEMO_TYPE;
}
export function isPortal(object: any): boolean {
return typeOf(object) === REACT_PORTAL_TYPE;

Check warning on line 157 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L156-L157

Added lines #L156 - L157 were not covered by tests
}
export function isProfiler(object: any): boolean {
return typeOf(object) === REACT_PROFILER_TYPE;

Check warning on line 160 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L159-L160

Added lines #L159 - L160 were not covered by tests
}
export function isStrictMode(object: any): boolean {
return typeOf(object) === REACT_STRICT_MODE_TYPE;

Check warning on line 163 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L162-L163

Added lines #L162 - L163 were not covered by tests
}
export function isSuspense(object: any): boolean {
return typeOf(object) === REACT_SUSPENSE_TYPE;
}
export function isSuspenseList(object: any): boolean {
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;

Check warning on line 169 in packages/pretty-format/src/plugins/lib/ReactIs.ts

View check run for this annotation

Codecov / codecov/patch

packages/pretty-format/src/plugins/lib/ReactIs.ts#L168-L169

Added lines #L168 - L169 were not covered by tests
}
11 changes: 0 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6390,15 +6390,6 @@ __metadata:
languageName: node
linkType: hard

"@types/react-is@npm:^18.3.1":
version: 18.3.1
resolution: "@types/react-is@npm:18.3.1"
dependencies:
"@types/react": "npm:^18"
checksum: 10/ccb79d6e196a5232cde8ccb255ec97e062801a3dafeff3816130fb5ad6b9a87f7c0806ab35bc00890a229773228ef217d0390839b68c705d3add2f798b5fcf82
languageName: node
linkType: hard

"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.7":
version: 5.0.11
resolution: "@types/react-router-config@npm:5.0.11"
Expand Down Expand Up @@ -18234,14 +18225,12 @@ __metadata:
dependencies:
"@jest/schemas": "workspace:*"
"@types/react": "npm:^18.3.23"
"@types/react-is": "npm:^18.3.1"
"@types/react-test-renderer": "npm:^18.3.1"
ansi-styles: "npm:^5.2.0"
immutable: "npm:^5.1.2"
jest-util: "workspace:*"
react: "npm:18.3.1"
react-dom: "npm:18.3.1"
react-is: "npm:^18.3.1"
react-test-renderer: "npm:18.3.1"
languageName: unknown
linkType: soft
Expand Down
Loading