1- import React , { ReactHTML , RefCallback , useEffect , useRef } from "react" ;
1+ import React , { Component , ReactHTML , RefCallback , useEffect , useRef } from "react" ;
22import { FC } from "react" ;
33
4- export type MockedComponent < PropType > = jest . MockedFunction < FC < PropType > > ;
4+ export type MockedComponent < PropType > = jest . MockedFunction < FC < PropType > > | jest . Mock < Component < PropType > > ;
55
66export type MockedElement < PropType = { } > = HTMLElement & {
77 props : PropType ,
@@ -10,7 +10,9 @@ export type MockedElement<PropType = {}> = HTMLElement & {
1010
1111export const mockElementTestId = 'rtl-mock-element' ;
1212
13- function ensureIsMock < PropType > ( mockedComponent : FC < PropType > ) {
13+ type FunctionOrClassComponent < PropType > = FC < PropType > | ( new ( props : PropType ) => Component < PropType > ) ;
14+
15+ function ensureIsMock < PropType > ( mockedComponent : FunctionOrClassComponent < PropType > ) {
1416 if ( ! jest . isMockFunction ( mockedComponent ) ) {
1517 throw new Error ( `${ mockedComponent . name } cannot be setup because it is not a Jest mock. Call "jest.mock('path/to/component')" first` ) ;
1618 }
@@ -23,10 +25,8 @@ export interface MockComponentOptions {
2325 element ?: keyof ReactHTML ;
2426}
2527
26- export function setupMockComponent < PropType > ( mockedComponent : FC < PropType > , options ?: MockComponentOptions ) {
27- ensureIsMock ( mockedComponent ) ;
28-
29- const mockImplementation : FC < PropType > = ( props ) => {
28+ function createMockComponent < PropType > ( mockedComponent : MockedComponent < PropType > , options ?: MockComponentOptions ) : FC < PropType > {
29+ const MockImplementation : FC < PropType > = ( props ) => {
3030 const mockedElmentRef = useRef < MockedElement < PropType > | null > ( null ) ;
3131 useEffect ( ( ) => {
3232 if ( mockedElmentRef . current ) {
@@ -37,7 +37,7 @@ export function setupMockComponent<PropType>(mockedComponent: FC<PropType>, opti
3737 const ref : RefCallback < HTMLDivElement > = ( el ) => {
3838 mockedElmentRef . current = el as unknown as MockedElement < PropType > ;
3939 if ( mockedElmentRef . current ) {
40- mockedElmentRef . current . component = comp ;
40+ mockedElmentRef . current . component = mockedComponent ; //TODO: fix me
4141 }
4242 } ;
4343
@@ -47,7 +47,29 @@ export function setupMockComponent<PropType>(mockedComponent: FC<PropType>, opti
4747 'data-testid' : mockElementTestId ,
4848 } , props . children ) ;
4949 } ;
50+ return MockImplementation ;
51+ }
5052
51- const comp = mockedComponent as MockedComponent < PropType > ;
52- comp . mockImplementation ( mockImplementation ) ;
53- }
53+ export function setupMockComponent < PropType > ( mockedComponent : FunctionOrClassComponent < PropType > , options ?: MockComponentOptions ) {
54+ ensureIsMock ( mockedComponent ) ;
55+ const MockImplementation = createMockComponent ( mockedComponent as MockedComponent < PropType > , options ) ;
56+ if ( isClassComponent ( mockedComponent ) ) {
57+ setupClassComponent ( MockImplementation , mockedComponent as jest . Mock < Component < PropType > > ) ;
58+ } else {
59+ const mockFunctionComponent = mockedComponent as jest . MockedFunction < FC < PropType > > ;
60+ mockFunctionComponent . mockImplementation ( MockImplementation ) ;
61+ }
62+ }
63+
64+ function setupClassComponent < PropType > ( MockImplementation : FC < PropType > , mockedComponent : jest . Mock < Component < PropType > > ) {
65+ class MockClassComponentWrapper extends Component < PropType > {
66+ render ( ) {
67+ return < MockImplementation { ...this . props } /> ;
68+ }
69+ }
70+ mockedComponent . mockImplementation ( ( props : PropType ) => new MockClassComponentWrapper ( props ) ) ;
71+ }
72+
73+ function isClassComponent < PropType > ( mockedComponent : FunctionOrClassComponent < PropType > ) {
74+ return 'isReactComponent' in mockedComponent . prototype ;
75+ }
0 commit comments