11import { MockedViewTimeline , mockViewTimeline } from './ViewTimeline' ;
22
3+ // Create framework-agnostic mock functions
4+ const createMockFunction = ( ) => {
5+ const calls : unknown [ ] [ ] = [ ] ;
6+ const mockFn = ( ...args : unknown [ ] ) => {
7+ calls . push ( args ) ;
8+ return undefined ;
9+ } ;
10+ mockFn . mock = { calls } ;
11+ return mockFn ;
12+ } ;
13+
314// Mock IntersectionObserver for testing
4- const mockIntersectionObserver = jest . fn ( ) . mockImplementation ( ( ) => ( {
5- observe : jest . fn ( ) ,
6- disconnect : jest . fn ( ) ,
7- unobserve : jest . fn ( )
8- } ) ) ;
15+ const mockObserve = createMockFunction ( ) ;
16+ const mockDisconnect = createMockFunction ( ) ;
17+ const mockUnobserve = createMockFunction ( ) ;
18+
19+ const mockIntersectionObserver = function ( callback : IntersectionObserverCallback , options ?: IntersectionObserverInit ) {
20+ // Store callback and options for testing
21+ const calls = mockIntersectionObserver . mock . calls ;
22+ calls . push ( [ callback , options ] ) ;
23+
24+ const instance = {
25+ observe : mockObserve ,
26+ disconnect : mockDisconnect ,
27+ unobserve : mockUnobserve
28+ } ;
29+
30+ mockIntersectionObserver . mock . results . push ( { value : instance } ) ;
31+ return instance ;
32+ } ;
33+
34+ mockIntersectionObserver . mock = {
35+ calls : [ ] as unknown [ ] [ ] ,
36+ results : [ ] as { value : { observe : typeof mockObserve ; disconnect : typeof mockDisconnect ; unobserve : typeof mockUnobserve } } [ ]
37+ } ;
938
1039// Store original IntersectionObserver
1140const originalIntersectionObserver = global . IntersectionObserver ;
1241
1342describe ( 'ViewTimeline' , ( ) => {
1443 beforeEach ( ( ) => {
44+ // Reset mock calls
45+ mockObserve . mock . calls . length = 0 ;
46+ mockDisconnect . mock . calls . length = 0 ;
47+ mockUnobserve . mock . calls . length = 0 ;
48+ mockIntersectionObserver . mock . calls . length = 0 ;
49+ mockIntersectionObserver . mock . results . length = 0 ;
50+
1551 // Mock IntersectionObserver
16- global . IntersectionObserver = mockIntersectionObserver ;
52+ global . IntersectionObserver = mockIntersectionObserver as unknown as typeof IntersectionObserver ;
1753 mockViewTimeline ( ) ;
1854 } ) ;
1955
@@ -26,7 +62,12 @@ describe('ViewTimeline', () => {
2662 delete ( window as Record < string , unknown > ) . ViewTimeline ;
2763 }
2864
29- jest . clearAllMocks ( ) ;
65+ // Clear mock calls
66+ mockObserve . mock . calls . length = 0 ;
67+ mockDisconnect . mock . calls . length = 0 ;
68+ mockUnobserve . mock . calls . length = 0 ;
69+ mockIntersectionObserver . mock . calls . length = 0 ;
70+ mockIntersectionObserver . mock . results . length = 0 ;
3071 } ) ;
3172
3273 it ( 'should be available globally after mocking' , ( ) => {
@@ -45,7 +86,7 @@ describe('ViewTimeline', () => {
4586
4687 it ( 'should throw error when subject is missing' , ( ) => {
4788 expect ( ( ) => {
48- new ViewTimeline ( { } as Parameters < ViewTimelineConstructor > [ 0 ] ) ;
89+ new ViewTimeline ( { } as { subject : Element ; axis ?: 'block' | 'inline' | 'x' | 'y' ; inset ?: string | Array < string > ; } ) ;
4990 } ) . toThrow ( 'ViewTimeline requires a valid Element as subject' ) ;
5091 } ) ;
5192
@@ -58,22 +99,20 @@ describe('ViewTimeline', () => {
5899 it ( 'should throw error for invalid axis parameter' , ( ) => {
59100 const mockElement = document . createElement ( 'div' ) ;
60101 expect ( ( ) => {
61- new ViewTimeline ( {
62- subject : mockElement ,
63- axis : 'invalid' as 'block' | 'inline' | 'x' | 'y'
102+ new ViewTimeline ( {
103+ subject : mockElement ,
104+ axis : 'invalid' as 'block' | 'inline' | 'x' | 'y'
64105 } ) ;
65106 } ) . toThrow ( 'Invalid axis value: invalid' ) ;
66107 } ) ;
67108
68- it ( 'should create a ViewTimeline with custom options ' , ( ) => {
109+ it ( 'should create ViewTimeline with custom axis ' , ( ) => {
69110 const mockElement = document . createElement ( 'div' ) ;
70- const timeline = new ViewTimeline ( {
71- subject : mockElement ,
72- axis : 'inline' ,
73- inset : [ '10px' , '20px' ]
111+ const timeline = new ViewTimeline ( {
112+ subject : mockElement ,
113+ axis : 'inline'
74114 } ) ;
75115
76- expect ( timeline . subject ) . toBe ( mockElement ) ;
77116 expect ( timeline . axis ) . toBe ( 'inline' ) ;
78117 } ) ;
79118
@@ -89,8 +128,9 @@ describe('ViewTimeline', () => {
89128 const mockElement = document . createElement ( 'div' ) ;
90129 new ViewTimeline ( { subject : mockElement } ) ;
91130
92- expect ( mockIntersectionObserver ) . toHaveBeenCalledWith (
93- expect . any ( Function ) ,
131+ expect ( mockIntersectionObserver . mock . calls . length ) . toBe ( 1 ) ;
132+ expect ( typeof mockIntersectionObserver . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'function' ) ;
133+ expect ( mockIntersectionObserver . mock . calls [ 0 ] [ 1 ] ) . toEqual (
94134 expect . objectContaining ( {
95135 root : null ,
96136 rootMargin : '0px' ,
@@ -106,8 +146,9 @@ describe('ViewTimeline', () => {
106146 inset : '10px 20px'
107147 } ) ;
108148
109- expect ( mockIntersectionObserver ) . toHaveBeenCalledWith (
110- expect . any ( Function ) ,
149+ expect ( mockIntersectionObserver . mock . calls . length ) . toBe ( 1 ) ;
150+ expect ( typeof mockIntersectionObserver . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'function' ) ;
151+ expect ( mockIntersectionObserver . mock . calls [ 0 ] [ 1 ] ) . toEqual (
111152 expect . objectContaining ( {
112153 rootMargin : '10px 20px'
113154 } )
@@ -121,8 +162,9 @@ describe('ViewTimeline', () => {
121162 inset : [ '10px' , '20px' , '30px' , '40px' ]
122163 } ) ;
123164
124- expect ( mockIntersectionObserver ) . toHaveBeenCalledWith (
125- expect . any ( Function ) ,
165+ expect ( mockIntersectionObserver . mock . calls . length ) . toBe ( 1 ) ;
166+ expect ( typeof mockIntersectionObserver . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'function' ) ;
167+ expect ( mockIntersectionObserver . mock . calls [ 0 ] [ 1 ] ) . toEqual (
126168 expect . objectContaining ( {
127169 rootMargin : '10px 20px 30px 40px'
128170 } )
@@ -143,14 +185,11 @@ describe('ViewTimeline', () => {
143185 it ( 'should support disconnect method to clean up observer' , ( ) => {
144186 const mockElement = document . createElement ( 'div' ) ;
145187 const timeline = new ViewTimeline ( { subject : mockElement } ) ;
146-
147- // Get the mock observer instance
148- const observerInstance = mockIntersectionObserver . mock . results [ 0 ] . value ;
149188
150189 // Call disconnect
151190 timeline . disconnect ( ) ;
152191
153192 // Should have called disconnect on the observer
154- expect ( observerInstance . disconnect ) . toHaveBeenCalled ( ) ;
193+ expect ( mockDisconnect . mock . calls . length ) . toBe ( 1 ) ;
155194 } ) ;
156195} ) ;
0 commit comments