refactor: cleanup renderer code

This commit is contained in:
Maciej Jastrzebski
2024-10-16 12:27:23 +02:00
parent 95030fb40f
commit 12b4f76a4f
8 changed files with 29 additions and 52 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Text } from 'react-native';
import { act, fireEvent, render, screen } from '../';
import '../matchers/extend-expect';
type UseEffectProps = { callback(): void };
const UseEffect = ({ callback }: UseEffectProps) => {
@@ -34,9 +35,9 @@ test('fireEvent should trigger useState', () => {
render(<Counter />);
const counter = screen.getByText(/Total count/i);
expect(counter.props.children).toEqual('Total count: 0');
expect(counter).toHaveTextContent('Total count: 0');
fireEvent.press(counter);
expect(counter.props.children).toEqual('Total count: 1');
expect(counter).toHaveTextContent('Total count: 1');
});
test('should be able to not await act', () => {
+3 -2
View File
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Text, TouchableOpacity, View, Pressable } from 'react-native';
import { fireEvent, render, waitFor, configure, screen } from '..';
import '../matchers/extend-expect';
class Banana extends React.Component<any> {
changeFresh = () => {
@@ -45,7 +46,7 @@ test('waits for element until it stops throwing', async () => {
const freshBananaText = await waitFor(() => screen.getByText('Fresh'));
expect(freshBananaText.props.children).toBe('Fresh');
expect(freshBananaText).toHaveTextContent('Fresh');
});
test('waits for element until timeout is met', async () => {
@@ -145,7 +146,7 @@ test.each([false, true])(
jest.advanceTimersByTime(300);
const freshBananaText = await waitFor(() => screen.getByText('Fresh'));
expect(freshBananaText.props.children).toBe('Fresh');
expect(freshBananaText).toHaveTextContent('Fresh');
},
);
+4 -1
View File
@@ -11,6 +11,7 @@ import redent from 'redent';
import { isValidElement } from '../helpers/component-tree';
import { defaultMapProps } from '../helpers/format-default';
import { HostElement, HostNode } from '../renderer/host-element';
import { getTextContent } from '../helpers/text-content';
class HostElementTypeError extends Error {
constructor(received: unknown, matcherFn: jest.CustomMatcher, context: jest.MatcherContext) {
@@ -72,6 +73,8 @@ export function formatElement(element: HostNode | null) {
const { children, ...props } = element.props;
const childrenToDisplay = typeof children === 'string' ? [children] : undefined;
const textContent = getTextContent(element);
return redent(
prettyFormat(
{
@@ -80,7 +83,7 @@ export function formatElement(element: HostNode | null) {
$$typeof: Symbol.for('react.test.json'),
type: element.type,
props: defaultMapProps(props),
children: childrenToDisplay,
children: element.children.filter((child) => typeof child === 'string'),
},
{
plugins: [plugins.ReactTestComponent, plugins.ReactElement],
+4 -3
View File
@@ -1,6 +1,7 @@
import React from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { render, screen } from '../..';
import '../../matchers/extend-expect';
const PLACEHOLDER_FRESHNESS = 'Add custom freshness';
const PLACEHOLDER_CHEF = 'Who inspected freshness?';
@@ -74,7 +75,7 @@ test('getByTestId, queryByTestId', () => {
render(<Banana />);
const component = screen.getByTestId('bananaFresh');
expect(component.props.children).toBe('not fresh');
expect(component).toHaveTextContent('not fresh');
expect(() => screen.getByTestId('InExistent')).toThrow(
'Unable to find an element with testID: InExistent',
);
@@ -95,8 +96,8 @@ test('getAllByTestId, queryAllByTestId', () => {
const textElements = screen.getAllByTestId('duplicateText');
expect(textElements.length).toBe(2);
expect(textElements[0].props.children).toBe('First Text');
expect(textElements[1].props.children).toBe('Second Text');
expect(textElements[0]).toHaveTextContent('First Text');
expect(textElements[1]).toHaveTextContent('Second Text');
expect(() => screen.getAllByTestId('nonExistentTestId')).toThrow(
'Unable to find an element with testID: nonExistentTestId',
);
+4 -3
View File
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Button, Image, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { getDefaultNormalizer, render, screen, within } from '../..';
import '../../matchers/extend-expect';
test('byText matches simple text', () => {
render(<Text testID="text">Hello World</Text>);
@@ -56,11 +57,11 @@ test('getByText, queryByText', () => {
render(<Banana />);
const button = screen.getByText(/change/i);
expect(button.props.children).toBe('Change freshness!');
expect(button).toHaveTextContent('Change freshness!');
const sameButton = screen.getByText('not fresh');
expect(sameButton.props.children).toBe('not fresh');
expect(sameButton).toHaveTextContent('not fresh');
expect(() => screen.getByText('InExistent')).toThrow(
'Unable to find an element with text: InExistent',
);
@@ -90,7 +91,7 @@ test('getByText, screen.queryByText with children as Array', () => {
render(<BananaStore />);
const threeBananaBunch = screen.getByText('There are 3 bananas in the bunch');
expect(threeBananaBunch.props.children).toEqual(['There are ', 3, ' bananas in the bunch']);
expect(threeBananaBunch).toHaveTextContent('There are 3 bananas in the bunch');
});
test('getAllByText, queryAllByText', () => {
+3 -3
View File
@@ -25,9 +25,9 @@ export class HostElement {
return {};
}
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
// const { children, ...restProps } = this.instance.props;
return this.instance.props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, ...restProps } = this.instance.props;
return restProps;
}
get children(): HostNode[] {
-13
View File
@@ -105,10 +105,6 @@ const hostConfig = {
_hostContext: HostContext,
internalHandle: OpaqueHandle,
): Instance {
//console.log('🔷 createInstance', type, props);
// console.log('- RootContainer:', rootContainer);
// console.log('- HostContext:', _hostContext);
// console.log('- InternalHandle:', internalHandle);
return {
tag: 'INSTANCE',
type,
@@ -162,8 +158,6 @@ const hostConfig = {
_rootContainer: Container,
_hostContext: HostContext,
): boolean {
// console.log('🔷 finalizeInitialChildren', type, props);
// console.log('🔷 - instance:', instance);
return false;
},
@@ -182,8 +176,6 @@ const hostConfig = {
_rootContainer: Container,
_hostContext: HostContext,
): UpdatePayload | null {
// console.log('🔷 prepareUpdate', type, newProps, oldProps);
// console.log('🔷 - instance:', instance);
return UPDATE_SIGNAL;
},
@@ -198,7 +190,6 @@ const hostConfig = {
*/
shouldSetTextContent(_type: Type, _props: Props): boolean {
// TODO: what should RN do here?
//console.log('🔷 shouldSetTextContent', type, props);
return false;
},
@@ -452,8 +443,6 @@ const hostConfig = {
_props: Props,
_internalHandle: OpaqueHandle,
): void {
// console.log('🔷 commitMount', type, props);
// console.log('🔷 - instance:', instance);
// noop
},
@@ -470,8 +459,6 @@ const hostConfig = {
nextProps: Props,
internalHandle: OpaqueHandle,
): void {
// console.log('🔷 commitMount', type, nextProps, _prevProps);
// console.log('🔷 - instance:', instance);
instance.type = type;
instance.props = nextProps;
instance.internalHandle = internalHandle;
+8 -25
View File
@@ -26,34 +26,18 @@ export function render(element: ReactElement): RenderResult {
false, // isStrictMode
null, // concurrentUpdatesByDefaultOverride
'id', // identifierPrefix
(_error) => {
// eslint-disable-next-line no-console
console.log('Recoverable Error', _error);
}, // onRecoverableError
(_error) => {}, // onRecoverableError
null, // transitionCallbacks
);
TestReconciler.updateContainer(element, containerFiber, null, () => {
// eslint-disable-next-line no-console
//console.log('Rendered', container?.children);
});
// update(newElement: React$Element<any>) {
// if (root == null || root.current == null) {
// return;
// }
// ReactReconciler.updateContainer(newElement, root, null, null);
// },
TestReconciler.updateContainer(element, containerFiber, null, null);
const update = (element: ReactElement) => {
if (containerFiber == null || container == null) {
return;
}
TestReconciler.updateContainer(element, containerFiber, null, () => {
// eslint-disable-next-line no-console
//console.log('Updated', container?.children);
});
TestReconciler.updateContainer(element, containerFiber, null, null);
};
const unmount = () => {
@@ -61,10 +45,7 @@ export function render(element: ReactElement): RenderResult {
return;
}
TestReconciler.updateContainer(null, containerFiber, null, () => {
// eslint-disable-next-line no-console
//console.log('Unmounted', container?.children);
});
TestReconciler.updateContainer(null, containerFiber, null, null);
container = null;
containerFiber = null;
@@ -79,14 +60,16 @@ export function render(element: ReactElement): RenderResult {
return renderToJson(container.children[0]);
}
// Taken from React Test Renderer
// TODO: When could that happen?
if (
container.children.length === 2 &&
container.children[0].isHidden === true &&
container.children[1].isHidden === false
) {
// Omit timed out children from output entirely, including the fact that we
// temporarily wrap fallback and timed out children in an array.
// Taken from React Test Renderer
// > Omit timed out children from output entirely, including the fact that we
// > temporarily wrap fallback and timed out children in an array.
return renderToJson(container.children[1]);
}