@@ -102,16 +102,13 @@ describe('Incremental Sync', () => {
102102 ]
103103
104104 // Mock Stripe API for first sync - returns all products
105- const mockList = vitest . fn ( async function * ( ) {
106- for ( const product of allProducts ) {
107- yield product
108- }
105+ const listSpy = vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
106+ object : 'list' ,
107+ data : allProducts ,
108+ has_more : false ,
109+ url : '/v1/products' ,
109110 } )
110111
111- const listSpy = vitest
112- . spyOn ( stripeSync . stripe . products , 'list' )
113- . mockReturnValue ( mockList ( ) as unknown )
114-
115112 // First sync - no cursor, should fetch all
116113 await stripeSync . syncProducts ( )
117114
@@ -129,16 +126,13 @@ describe('Incremental Sync', () => {
129126 expect ( cursor ) . toBe ( 1705075200 ) // Max created from first sync
130127
131128 // Mock Stripe API for second sync - only returns new products
132- const mockListIncremental = vitest . fn ( async function * ( ) {
133- for ( const product of newProducts ) {
134- yield product
135- }
129+ const listSpyIncremental = vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
130+ object : 'list' ,
131+ data : newProducts ,
132+ has_more : false ,
133+ url : '/v1/products' ,
136134 } )
137135
138- const listSpyIncremental = vitest
139- . spyOn ( stripeSync . stripe . products , 'list' )
140- . mockReturnValue ( mockListIncremental ( ) as unknown )
141-
142136 // Second sync - should use cursor
143137 await stripeSync . syncProducts ( )
144138
@@ -167,14 +161,13 @@ describe('Incremental Sync', () => {
167161 name : `Product ${ i } ` ,
168162 } ) ) as Stripe . Product [ ]
169163
170- const mockList = vitest . fn ( async function * ( ) {
171- for ( const product of products ) {
172- yield product
173- }
164+ vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
165+ object : 'list' ,
166+ data : products ,
167+ has_more : false ,
168+ url : '/v1/products' ,
174169 } )
175170
176- vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockReturnValue ( mockList ( ) as unknown )
177-
178171 // Spy on updateObjectCursor (new observability method)
179172 const updateSpy = vitest . spyOn ( stripeSync . postgresClient , 'updateObjectCursor' )
180173
@@ -220,14 +213,13 @@ describe('Incremental Sync', () => {
220213 } as Stripe . Product ,
221214 ]
222215
223- const mockList = vitest . fn ( async function * ( ) {
224- for ( const product of products ) {
225- yield product
226- }
216+ vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
217+ object : 'list' ,
218+ data : products ,
219+ has_more : false ,
220+ url : '/v1/products' ,
227221 } )
228222
229- vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockReturnValue ( mockList ( ) as unknown )
230-
231223 await stripeSync . syncProducts ( )
232224
233225 const initialCursor = await getCursor ( 'products' )
@@ -267,13 +259,12 @@ describe('Incremental Sync', () => {
267259 } as Stripe . Product ,
268260 ]
269261
270- const mockSetupList = vitest . fn ( async function * ( ) {
271- for ( const product of setupProducts ) {
272- yield product
273- }
262+ vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
263+ object : 'list' ,
264+ data : setupProducts ,
265+ has_more : false ,
266+ url : '/v1/products' ,
274267 } )
275-
276- vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockReturnValue ( mockSetupList ( ) as unknown )
277268 await stripeSync . syncProducts ( )
278269
279270 // Verify cursor was set
@@ -292,16 +283,13 @@ describe('Incremental Sync', () => {
292283 } as Stripe . Product ,
293284 ]
294285
295- const mockList = vitest . fn ( async function * ( ) {
296- for ( const product of products ) {
297- yield product
298- }
286+ const listSpy = vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockResolvedValue ( {
287+ object : 'list' ,
288+ data : products ,
289+ has_more : false ,
290+ url : '/v1/products' ,
299291 } )
300292
301- const listSpy = vitest
302- . spyOn ( stripeSync . stripe . products , 'list' )
303- . mockReturnValue ( mockList ( ) as unknown )
304-
305293 // Call with explicit filter (earlier than cursor)
306294 await stripeSync . syncProducts ( {
307295 created : { gte : 1672531200 } ,
@@ -325,23 +313,36 @@ describe('Incremental Sync', () => {
325313 ]
326314
327315 let callCount = 0
328- const mockList = vitest . fn ( async function * ( ) {
329- for ( const product of products ) {
330- yield product
331- }
332- // Simulate error after yielding products
316+ let hasThrown = false
317+ vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockImplementation ( async ( ) => {
333318 callCount ++
334- if ( callCount === 1 ) {
319+ if ( callCount === 1 && ! hasThrown ) {
320+ // First page succeeds with products
321+ return {
322+ object : 'list' ,
323+ data : products ,
324+ has_more : true , // Indicate there's more (but second fetch will fail)
325+ url : '/v1/products' ,
326+ }
327+ } else if ( callCount === 2 && ! hasThrown ) {
328+ // Second fetch fails (only on first sync)
329+ hasThrown = true
335330 throw new Error ( 'Simulated sync error' )
331+ } else {
332+ // After first sync, just return products without more pages
333+ return {
334+ object : 'list' ,
335+ data : callCount === 1 ? products : [ ] ,
336+ has_more : false ,
337+ url : '/v1/products' ,
338+ }
336339 }
337340 } )
338341
339- vitest . spyOn ( stripeSync . stripe . products , 'list' ) . mockReturnValue ( mockList ( ) as unknown )
340-
341342 // First attempt should fail but save checkpoint
342343 await expect ( stripeSync . syncProducts ( ) ) . rejects . toThrow ( 'Simulated sync error' )
343344
344- // Cursor should be saved up to checkpoint
345+ // Cursor should be saved up to checkpoint (first product was processed successfully)
345346 const cursor = await getCursor ( 'products' )
346347 expect ( cursor ) . toBe ( 1704902400 )
347348
@@ -368,7 +369,7 @@ describe('Incremental Sync', () => {
368369 expect ( objStatus . rows [ 0 ] . status ) . toBe ( 'error' )
369370 expect ( objStatus . rows [ 0 ] . error_message ) . toContain ( 'Simulated sync error' )
370371
371- // Second attempt should succeed
372+ // Second attempt should succeed - reset callCount
372373 callCount = 0
373374 await stripeSync . syncProducts ( )
374375
0 commit comments