Me pregunto si alguien tiene algunas buenas sugerencias sobre cómo descifrar esto. Obtuve estas utilidades auxiliares de prueba a las que he agregado algunos tipos:
import { jest } from '@jest/globals' import React from 'react' // https://learn.reactnativeschool.com/courses/781007/lectures/14173979 export function mockComponent(moduleName: string, propOverrideFn = (props: Record<string, any>) => ({})) { const RealComponent = jest.requireActual(moduleName) as React.ComponentType<any> const CustomizedComponent = (props: Record<string, any>) => { return React.createElement( 'CustomizedComponent', { ...props, ...propOverrideFn(props), }, props.children ) } CustomizedComponent.propTypes = RealComponent.propTypes return CustomizedComponent }Así que actualmente puedo llamarlo así
jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => { return mockComponent('react-native/Libraries/Components/Touchable/TouchableOpacity', (props) => { return { onPress: props.disabled ? () => {} : props.onPress } }) })Pero me gustaría poder llamarlo más como
jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => { return <MockComponent module='TouchableOpacity' onPress={props => props.disabled ? () => {} : props.onPress} /> })o
jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => { return <MockComponent module='TouchableOpacity' propOverride={props => ({onPress: props.disabled ? () => {} : props.onPress, ...props})} /> })Si observa React sin JSX , verá que la sintaxis inspirada en XML ( <MockComponent /> ) es la abreviatura de React.createElement('MockComponent') .
En este momento, si cambió el nombre de mockComponent a MockComponent e intentó usar la sintaxis de paréntesis angular, el primer problema es que su función recibe dos argumentos. Los componentes de reacción son componentes de clase que toman un argumento de constructor (accesorios) o componentes funcionales que toman un argumento (nuevamente, accesorios). El segundo problema es que su función devuelve un componente funcional React, cuando necesita devolver un elemento React renderizado .
Una forma de solucionar este problema es convertir mockComponent en un componente funcional de React y crear accesorios de module y propOverride del FC.
// https://learn.reactnativeschool.com/courses/781007/lectures/14173979 export function MockComponent(props) { const { moduleName, propOverrideFn, ...customComponentProps } = props; const RealComponent = jest.requireActual(moduleName) as React.ComponentType<any> const CustomizedComponent = (props: Record<string, any>) => { return React.createElement( 'CustomizedComponent', { ...props, ...propOverrideFn(props), }, props.children ) } CustomizedComponent.propTypes = RealComponent.propTypes return <CustomizedComponent {...customComponentProps} /> } Las diferencias son sutiles pero importantes. Aquí modifiqué MockComponent para tomar un argumento de prop singular para que sea compatible con React.createElement() . Esto lleva a la cuestión de cómo diferenciar los accesorios destinados al componente CustomizedComponent y lo que solían ser argumentos para mockComponent() . Aquí, utilizo los operadores de desestructuración y propagación de JavaScript para separar el module y propOverride de los accesorios previstos en el componente CustomizedComponent .
Por último, uso la sintaxis de distribución JSX para pasar los accesorios arbitrarios destinados a CustomizedComponent a Componente CustomizedComponent , y uso paréntesis angulares para representarlo (en lugar de devolver una función).
Lo dejaré como un ejercicio para que encuentre la definición de TypeScript adecuada para los accesorios de MockComponent. Simplemente puede definirlo como la unión de Record<string, any> y module y propOverride . Sin embargo, puede ser sofisticado y usar una definición de plantilla, de modo que MockComponent<Toolbar> sea una unión de module y propOverride y los accesorios de Toolbar .
Ah, y casi se me olvida. Su llamada de broma se vería como
jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => { (props) => { return <MockComponent module='TouchableOpacity' onPress={props => props.disabled ? () => {} : props.onPress} {...props} /> } })