@@ -65,35 +65,58 @@ function fn() {
6565function createSmartSpy ( realSpy : jest . SpyInstance ) : SmartSpy {
6666 return new Proxy ( realSpy as object , {
6767 get ( target , prop ) {
68- // Only implement the methods we actually use
69- if ( prop === 'mockImplementation' ) {
70- return ( fn : ( ) => void ) => {
71- ( target as jest . SpyInstance ) . mockImplementation ( fn ) ;
72- return createSmartSpy ( target as jest . SpyInstance ) ;
73- } ;
74- }
75- if ( prop === 'toHaveBeenCalledWith' ) {
76- return ( ...args : unknown [ ] ) => {
77- // Jest SpyInstance doesn't have toHaveBeenCalledWith as a method,
78- // it's available through expect(spy).toHaveBeenCalledWith()
79- // For compatibility, we'll check if the method exists and call it
80- const spy = target as Record < string , unknown > ;
81- if ( typeof spy . toHaveBeenCalledWith === 'function' ) {
82- return (
83- spy . toHaveBeenCalledWith as ( ...args : unknown [ ] ) => unknown
84- ) ( ...args ) ;
85- }
86- return undefined ;
87- } ;
88- }
89- if ( prop === 'mockRestore' ) {
90- return ( ) => {
91- ( target as jest . SpyInstance ) . mockRestore ( ) ;
92- } ;
93- }
68+ // Switch on the specific methods we need to implement
69+ switch ( prop ) {
70+ case 'mockImplementation' :
71+ return ( fn : ( ) => void ) => {
72+ ( target as jest . SpyInstance ) . mockImplementation ( fn ) ;
73+ return createSmartSpy ( target as jest . SpyInstance ) ;
74+ } ;
75+
76+ case 'toHaveBeenCalledWith' :
77+ return ( ...args : unknown [ ] ) => {
78+ // Jest SpyInstance doesn't have toHaveBeenCalledWith as a method,
79+ // but Vitest spies do. For compatibility, we implement it by checking
80+ // the spy's call history manually to match Vitest's behavior.
81+ const jestSpy = target as jest . SpyInstance ;
9482
95- // For everything else, just pass through to the real spy
96- return ( target as Record < string | symbol , unknown > ) [ prop ] ;
83+ // Check if any call matches the expected arguments
84+ const calls = jestSpy . mock . calls ;
85+ const hasMatchingCall = calls . some ( ( call : unknown [ ] ) => {
86+ if ( call . length !== args . length ) return false ;
87+ return call . every ( ( arg : unknown , index : number ) => {
88+ // Use Jest's deep equality matching
89+ try {
90+ expect ( arg ) . toEqual ( args [ index ] ) ;
91+ return true ;
92+ } catch {
93+ return false ;
94+ }
95+ } ) ;
96+ } ) ;
97+
98+ if ( ! hasMatchingCall ) {
99+ throw new Error (
100+ `Expected spy to have been called with [${ args . map ( ( arg : unknown ) => JSON . stringify ( arg ) ) . join ( ', ' ) } ], ` +
101+ `but it was called with: ${ calls
102+ . map (
103+ ( call : unknown [ ] ) =>
104+ `[${ call . map ( ( arg : unknown ) => JSON . stringify ( arg ) ) . join ( ', ' ) } ]`
105+ )
106+ . join ( ', ' ) } `
107+ ) ;
108+ }
109+ } ;
110+
111+ case 'mockRestore' :
112+ return ( ) => {
113+ ( target as jest . SpyInstance ) . mockRestore ( ) ;
114+ } ;
115+
116+ default :
117+ // For everything else, just pass through to the real spy
118+ return ( target as Record < string | symbol , unknown > ) [ prop ] ;
119+ }
97120 } ,
98121 } ) as SmartSpy ;
99122}
0 commit comments