@@ -129,6 +129,46 @@ function mockRunOnceAndAbort(abort: AbortController) {
129129 runSpy . mockImplementationOnce ( ( ) => makeAbortRunner ( abort ) ) ;
130130}
131131
132+ async function expectOffsetConfirmationSkipped ( offset : number | null ) {
133+ readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( offset ) ;
134+ const abort = new AbortController ( ) ;
135+ api . getUpdates . mockReset ( ) ;
136+ api . deleteWebhook . mockReset ( ) ;
137+ api . deleteWebhook . mockResolvedValueOnce ( true ) ;
138+ mockRunOnceAndAbort ( abort ) ;
139+
140+ await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
141+
142+ expect ( api . getUpdates ) . not . toHaveBeenCalled ( ) ;
143+ }
144+
145+ async function runMonitorAndCaptureStartupOrder ( params ?: { persistedOffset ?: number | null } ) {
146+ if ( params && "persistedOffset" in params ) {
147+ readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( params . persistedOffset ?? null ) ;
148+ }
149+ const abort = new AbortController ( ) ;
150+ const order : string [ ] = [ ] ;
151+ api . getUpdates . mockReset ( ) ;
152+ api . deleteWebhook . mockReset ( ) ;
153+ api . deleteWebhook . mockImplementationOnce ( async ( ) => {
154+ order . push ( "deleteWebhook" ) ;
155+ return true ;
156+ } ) ;
157+ if ( typeof params ?. persistedOffset === "number" ) {
158+ api . getUpdates . mockImplementationOnce ( async ( ) => {
159+ order . push ( "getUpdates" ) ;
160+ return [ ] ;
161+ } ) ;
162+ }
163+ runSpy . mockImplementationOnce ( ( ) => {
164+ order . push ( "run" ) ;
165+ return makeAbortRunner ( abort ) ;
166+ } ) ;
167+
168+ await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
169+ return { order } ;
170+ }
171+
132172function mockRunOnceWithStalledPollingRunner ( ) : {
133173 stop : ReturnType < typeof vi . fn < ( ) => void | Promise < void > > > ;
134174} {
@@ -349,19 +389,7 @@ describe("monitorTelegramProvider (grammY)", () => {
349389 } ) ;
350390
351391 it ( "deletes webhook before starting polling" , async ( ) => {
352- const abort = new AbortController ( ) ;
353- const order : string [ ] = [ ] ;
354- api . deleteWebhook . mockReset ( ) ;
355- api . deleteWebhook . mockImplementationOnce ( async ( ) => {
356- order . push ( "deleteWebhook" ) ;
357- return true ;
358- } ) ;
359- runSpy . mockImplementationOnce ( ( ) => {
360- order . push ( "run" ) ;
361- return makeAbortRunner ( abort ) ;
362- } ) ;
363-
364- await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
392+ const { order } = await runMonitorAndCaptureStartupOrder ( ) ;
365393
366394 expect ( api . deleteWebhook ) . toHaveBeenCalledWith ( { drop_pending_updates : false } ) ;
367395 expect ( order ) . toEqual ( [ "deleteWebhook" , "run" ] ) ;
@@ -577,67 +605,24 @@ describe("monitorTelegramProvider (grammY)", () => {
577605 } ) ;
578606
579607 it ( "confirms persisted offset with Telegram before starting runner" , async ( ) => {
580- readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( 549076203 ) ;
581- const abort = new AbortController ( ) ;
582- const order : string [ ] = [ ] ;
583- api . getUpdates . mockReset ( ) ;
584- api . getUpdates . mockImplementationOnce ( async ( ) => {
585- order . push ( "getUpdates" ) ;
586- return [ ] ;
587- } ) ;
588- api . deleteWebhook . mockReset ( ) ;
589- api . deleteWebhook . mockImplementationOnce ( async ( ) => {
590- order . push ( "deleteWebhook" ) ;
591- return true ;
608+ const { order } = await runMonitorAndCaptureStartupOrder ( {
609+ persistedOffset : 549076203 ,
592610 } ) ;
593- runSpy . mockImplementationOnce ( ( ) => {
594- order . push ( "run" ) ;
595- return makeAbortRunner ( abort ) ;
596- } ) ;
597-
598- await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
599611
600612 expect ( api . getUpdates ) . toHaveBeenCalledWith ( { offset : 549076204 , limit : 1 , timeout : 0 } ) ;
601613 expect ( order ) . toEqual ( [ "deleteWebhook" , "getUpdates" , "run" ] ) ;
602614 } ) ;
603615
604616 it ( "skips offset confirmation when no persisted offset exists" , async ( ) => {
605- readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( null ) ;
606- const abort = new AbortController ( ) ;
607- api . getUpdates . mockReset ( ) ;
608- api . deleteWebhook . mockReset ( ) ;
609- api . deleteWebhook . mockResolvedValueOnce ( true ) ;
610- mockRunOnceAndAbort ( abort ) ;
611-
612- await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
613-
614- expect ( api . getUpdates ) . not . toHaveBeenCalled ( ) ;
617+ await expectOffsetConfirmationSkipped ( null ) ;
615618 } ) ;
616619
617620 it ( "skips offset confirmation when persisted offset is invalid" , async ( ) => {
618- readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( - 1 as number ) ;
619- const abort = new AbortController ( ) ;
620- api . getUpdates . mockReset ( ) ;
621- api . deleteWebhook . mockReset ( ) ;
622- api . deleteWebhook . mockResolvedValueOnce ( true ) ;
623- mockRunOnceAndAbort ( abort ) ;
624-
625- await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
626-
627- expect ( api . getUpdates ) . not . toHaveBeenCalled ( ) ;
621+ await expectOffsetConfirmationSkipped ( - 1 ) ;
628622 } ) ;
629623
630624 it ( "skips offset confirmation when persisted offset cannot be safely incremented" , async ( ) => {
631- readTelegramUpdateOffsetSpy . mockResolvedValueOnce ( Number . MAX_SAFE_INTEGER ) ;
632- const abort = new AbortController ( ) ;
633- api . getUpdates . mockReset ( ) ;
634- api . deleteWebhook . mockReset ( ) ;
635- api . deleteWebhook . mockResolvedValueOnce ( true ) ;
636- mockRunOnceAndAbort ( abort ) ;
637-
638- await monitorTelegramProvider ( { token : "tok" , abortSignal : abort . signal } ) ;
639-
640- expect ( api . getUpdates ) . not . toHaveBeenCalled ( ) ;
625+ await expectOffsetConfirmationSkipped ( Number . MAX_SAFE_INTEGER ) ;
641626 } ) ;
642627
643628 it ( "resets webhookCleared latch on 409 conflict so deleteWebhook re-runs" , async ( ) => {
0 commit comments