mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
149 lines
4.1 KiB
JavaScript
149 lines
4.1 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
|
|
import {disableStringRefs} from 'shared/ReactFeatureFlags';
|
|
const {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');
|
|
|
|
import isArray from 'shared/isArray';
|
|
|
|
function captureAssertion(fn) {
|
|
// Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
|
|
// assertion; if it throws, we capture the error and return it, so the stack
|
|
// trace presented to the user points to the original assertion in the
|
|
// test file.
|
|
try {
|
|
fn();
|
|
} catch (error) {
|
|
return {
|
|
pass: false,
|
|
message: () => error.message,
|
|
};
|
|
}
|
|
return {pass: true};
|
|
}
|
|
|
|
function assertYieldsWereCleared(root) {
|
|
const Scheduler = root._Scheduler;
|
|
const actualYields = Scheduler.unstable_clearLog();
|
|
if (actualYields.length !== 0) {
|
|
const error = Error(
|
|
'Log of yielded values is not empty. ' +
|
|
'Call expect(ReactTestRenderer).unstable_toHaveYielded(...) first.',
|
|
);
|
|
Error.captureStackTrace(error, assertYieldsWereCleared);
|
|
throw error;
|
|
}
|
|
assertConsoleLogsCleared();
|
|
}
|
|
|
|
function createJSXElementForTestComparison(type, props) {
|
|
if (__DEV__) {
|
|
const element = {
|
|
$$typeof: REACT_ELEMENT_TYPE,
|
|
type: type,
|
|
key: null,
|
|
props: props,
|
|
_owner: null,
|
|
_store: __DEV__ ? {} : undefined,
|
|
};
|
|
Object.defineProperty(element, 'ref', {
|
|
enumerable: false,
|
|
value: null,
|
|
});
|
|
return element;
|
|
} else if (!__DEV__ && disableStringRefs) {
|
|
return {
|
|
$$typeof: REACT_ELEMENT_TYPE,
|
|
type: type,
|
|
key: null,
|
|
ref: null,
|
|
props: props,
|
|
};
|
|
} else {
|
|
return {
|
|
$$typeof: REACT_ELEMENT_TYPE,
|
|
type: type,
|
|
key: null,
|
|
ref: null,
|
|
props: props,
|
|
_owner: null,
|
|
_store: __DEV__ ? {} : undefined,
|
|
};
|
|
}
|
|
}
|
|
|
|
export function unstable_toMatchRenderedOutput(root, expectedJSX) {
|
|
assertYieldsWereCleared(root);
|
|
const actualJSON = root.toJSON();
|
|
|
|
let actualJSX;
|
|
if (actualJSON === null || typeof actualJSON === 'string') {
|
|
actualJSX = actualJSON;
|
|
} else if (isArray(actualJSON)) {
|
|
if (actualJSON.length === 0) {
|
|
actualJSX = null;
|
|
} else if (actualJSON.length === 1) {
|
|
actualJSX = jsonChildToJSXChild(actualJSON[0]);
|
|
} else {
|
|
const actualJSXChildren = jsonChildrenToJSXChildren(actualJSON);
|
|
if (actualJSXChildren === null || typeof actualJSXChildren === 'string') {
|
|
actualJSX = actualJSXChildren;
|
|
} else {
|
|
actualJSX = createJSXElementForTestComparison(REACT_FRAGMENT_TYPE, {
|
|
children: actualJSXChildren,
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
actualJSX = jsonChildToJSXChild(actualJSON);
|
|
}
|
|
|
|
return captureAssertion(() => {
|
|
expect(actualJSX).toEqual(expectedJSX);
|
|
});
|
|
}
|
|
|
|
function jsonChildToJSXChild(jsonChild) {
|
|
if (jsonChild === null || typeof jsonChild === 'string') {
|
|
return jsonChild;
|
|
} else {
|
|
const jsxChildren = jsonChildrenToJSXChildren(jsonChild.children);
|
|
return createJSXElementForTestComparison(
|
|
jsonChild.type,
|
|
jsxChildren === null
|
|
? jsonChild.props
|
|
: {...jsonChild.props, children: jsxChildren},
|
|
);
|
|
}
|
|
}
|
|
|
|
function jsonChildrenToJSXChildren(jsonChildren) {
|
|
if (jsonChildren !== null) {
|
|
if (jsonChildren.length === 1) {
|
|
return jsonChildToJSXChild(jsonChildren[0]);
|
|
} else if (jsonChildren.length > 1) {
|
|
const jsxChildren = [];
|
|
let allJSXChildrenAreStrings = true;
|
|
let jsxChildrenString = '';
|
|
for (let i = 0; i < jsonChildren.length; i++) {
|
|
const jsxChild = jsonChildToJSXChild(jsonChildren[i]);
|
|
jsxChildren.push(jsxChild);
|
|
if (allJSXChildrenAreStrings) {
|
|
if (typeof jsxChild === 'string') {
|
|
jsxChildrenString += jsxChild;
|
|
} else if (jsxChild !== null) {
|
|
allJSXChildrenAreStrings = false;
|
|
}
|
|
}
|
|
}
|
|
return allJSXChildrenAreStrings ? jsxChildrenString : jsxChildren;
|
|
}
|
|
}
|
|
return null;
|
|
}
|