@@ -6,6 +6,38 @@ import { BookingStatus } from "@calcom/prisma/enums";
66
77import { test } from "./lib/fixtures" ;
88
9+ /**
10+ * Helper to retry network requests that may fail with transient errors like ECONNRESET
11+ */
12+ async function retryOnNetworkError < T > (
13+ fn : ( ) => Promise < T > ,
14+ maxRetries = 3 ,
15+ delayMs = 500
16+ ) : Promise < T > {
17+ let lastError : Error | undefined ;
18+ for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
19+ try {
20+ return await fn ( ) ;
21+ } catch ( error ) {
22+ lastError = error as Error ;
23+ const errorMessage = lastError . message || "" ;
24+ // Only retry on transient network errors
25+ const isRetryable =
26+ errorMessage . includes ( "ECONNRESET" ) ||
27+ errorMessage . includes ( "ECONNREFUSED" ) ||
28+ errorMessage . includes ( "ETIMEDOUT" ) ||
29+ errorMessage . includes ( "socket hang up" ) ;
30+
31+ if ( ! isRetryable || attempt === maxRetries ) {
32+ throw lastError ;
33+ }
34+ // Wait before retrying with exponential backoff
35+ await new Promise ( ( resolve ) => setTimeout ( resolve , delayMs * attempt ) ) ;
36+ }
37+ }
38+ throw lastError ;
39+ }
40+
941test . describe ( "Booking Confirmation and Rejection via API" , ( ) => {
1042 test . afterEach ( async ( { users } ) => {
1143 await users . deleteAll ( ) ;
@@ -64,9 +96,14 @@ test.describe("Booking Confirmation and Rejection via API", () => {
6496
6597 const url = `/api/verify-booking-token?action=accept&token=${ oneTimePassword } &bookingUid=${ booking . uid } &userId=${ organizer . id } ` ;
6698
67- const response = await page . request . get ( url , {
68- maxRedirects : 0 ,
69- } ) ;
99+ const response = await retryOnNetworkError (
100+ ( ) =>
101+ page . request . get ( url , {
102+ maxRedirects : 0 ,
103+ } ) ,
104+ 3 ,
105+ 500
106+ ) ;
70107
71108 expect ( response . status ( ) ) . toBe ( 303 ) ;
72109 const location = response . headers ( ) [ "location" ] ;
@@ -133,10 +170,15 @@ test.describe("Booking Confirmation and Rejection via API", () => {
133170
134171 const url = `/api/verify-booking-token?action=reject&token=${ oneTimePassword } &bookingUid=${ booking . uid } &userId=${ organizer . id } ` ;
135172
136- const response = await page . request . post ( url , {
137- data : { reason : "Not available at this time" } ,
138- maxRedirects : 0 ,
139- } ) ;
173+ const response = await retryOnNetworkError (
174+ ( ) =>
175+ page . request . post ( url , {
176+ data : { reason : "Not available at this time" } ,
177+ maxRedirects : 0 ,
178+ } ) ,
179+ 3 ,
180+ 500
181+ ) ;
140182
141183 expect ( response . status ( ) ) . toBe ( 303 ) ;
142184 const location = response . headers ( ) [ "location" ] ;
0 commit comments