diff --git a/src/__tests__/act.test.tsx b/src/__tests__/act.test.tsx index 379eecc4..36a10f8b 100644 --- a/src/__tests__/act.test.tsx +++ b/src/__tests__/act.test.tsx @@ -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(); 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', () => { diff --git a/src/__tests__/wait-for.test.tsx b/src/__tests__/wait-for.test.tsx index 5eaa0190..9c9bdb37 100644 --- a/src/__tests__/wait-for.test.tsx +++ b/src/__tests__/wait-for.test.tsx @@ -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 { 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'); }, ); diff --git a/src/matchers/utils.tsx b/src/matchers/utils.tsx index 66402bee..77737a0b 100644 --- a/src/matchers/utils.tsx +++ b/src/matchers/utils.tsx @@ -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], diff --git a/src/queries/__tests__/test-id.test.tsx b/src/queries/__tests__/test-id.test.tsx index 349a8034..700b214f 100644 --- a/src/queries/__tests__/test-id.test.tsx +++ b/src/queries/__tests__/test-id.test.tsx @@ -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(); 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', ); diff --git a/src/queries/__tests__/text.test.tsx b/src/queries/__tests__/text.test.tsx index 089ed279..433886d4 100644 --- a/src/queries/__tests__/text.test.tsx +++ b/src/queries/__tests__/text.test.tsx @@ -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(Hello World); @@ -56,11 +57,11 @@ test('getByText, queryByText', () => { render(); 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(); 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', () => { diff --git a/src/renderer/host-element.ts b/src/renderer/host-element.ts index f4c682f7..2dd486e8 100644 --- a/src/renderer/host-element.ts +++ b/src/renderer/host-element.ts @@ -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[] { diff --git a/src/renderer/reconciler.ts b/src/renderer/reconciler.ts index 20484e2f..a44431f3 100644 --- a/src/renderer/reconciler.ts +++ b/src/renderer/reconciler.ts @@ -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; diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 1f0c1877..d91f905c 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -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) { - // 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]); }