Skip to content

Commit 029df96

Browse files
committed
CUST-5221: add "destroy" with json-body to booking deletion
1 parent fd861fb commit 029df96

File tree

4 files changed

+120
-1
lines changed

4 files changed

+120
-1
lines changed

src/main/kotlin/com/nylas/NylasClient.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,28 @@ open class NylasClient(
276276
return executeRequest(url, HttpMethod.DELETE, null, resultType, overrides)
277277
}
278278

279+
/**
280+
* Execute a DELETE request to the Nylas API with a JSON request body.
281+
* @param path The path to request.
282+
* @param resultType The type of the response body.
283+
* @param requestBody The request body.
284+
* @param queryParams The query parameters.
285+
* @param overrides The request overrides.
286+
* @suppress Not for public use.
287+
*/
288+
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
289+
open fun <T> executeDelete(
290+
path: String,
291+
resultType: Type,
292+
requestBody: String,
293+
queryParams: IQueryParams? = null,
294+
overrides: RequestOverrides? = null,
295+
): T {
296+
val url = buildUrl(path, queryParams, overrides)
297+
val jsonBody = JsonHelper.jsonRequestBody(requestBody)
298+
return executeRequest(url, HttpMethod.DELETE, jsonBody, resultType, overrides)
299+
}
300+
279301
/**
280302
* Execute a request with a form-body payload to the Nylas API.
281303
* @param path The path to request.

src/main/kotlin/com/nylas/resources/Bookings.kt

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,57 @@ class Bookings(client: NylasClient) : Resource<Booking>(client, Booking::class.j
9494
}
9595

9696
/**
97-
* Destroy a booking
97+
* Destroy a booking with a request body.
98+
*
99+
* This is a convenience overload for callers who need to send a
100+
* [DestroyBookingRequest] but do not need query params or request overrides.
101+
* It delegates to the full request-body overload below.
102+
*
103+
* @param bookingId The ID of the booking to destroy.
104+
* @param requestBody The data to destroy the booking with.
105+
* @return The DeleteResponse object
106+
*/
107+
@Throws(NylasApiError::class, NylasSdkTimeoutError::class)
108+
fun destroy(
109+
bookingId: String,
110+
requestBody: DestroyBookingRequest,
111+
): DeleteResponse {
112+
return destroy(bookingId, requestBody, null, null)
113+
}
114+
115+
/**
116+
* Destroy a booking with a request body.
117+
*
118+
* This is the full request-body overload used for cancellation flows that
119+
* need to send fields such as `cancellation_reason` while still supporting
120+
* optional query params and request overrides.
121+
*
122+
* @param bookingId The ID of the booking to destroy.
123+
* @param requestBody The data to destroy the booking with.
124+
* @param queryParams Optional query parameters to apply
125+
* @param overrides Optional request overrides to apply
126+
* @return The DeleteResponse object
127+
*/
128+
@Throws(NylasApiError::class, NylasSdkTimeoutError::class)
129+
fun destroy(
130+
bookingId: String,
131+
requestBody: DestroyBookingRequest,
132+
queryParams: DestroyBookingQueryParams?,
133+
overrides: RequestOverrides?,
134+
): DeleteResponse {
135+
val path = String.format("v3/scheduling/bookings/%s", bookingId)
136+
val adapter = JsonHelper.moshi().adapter(DestroyBookingRequest::class.java)
137+
val serializedRequestBody = adapter.toJson(requestBody)
138+
return client.executeDelete(path, DeleteResponse::class.java, serializedRequestBody, queryParams, overrides)
139+
}
140+
141+
/**
142+
* Destroy a booking using the legacy no-body behavior.
143+
*
144+
* This overload is kept for backward compatibility with existing SDK users.
145+
* It preserves the previous method shape and sends the DELETE request without
146+
* a request body.
147+
*
98148
* @param bookingId The ID of the booking to destroy.
99149
* @param queryParams Optional query parameters to apply
100150
* @param overrides Optional request overrides to apply

src/test/kotlin/com/nylas/NylasClientTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,23 @@ class NylasClientTest {
521521
assertEquals(capturedRequest.method, "DELETE")
522522
}
523523

524+
@Test
525+
fun `executeDelete with a request body should set up the request with the correct params`() {
526+
val deleteBody = "{ \"cancellation_reason\": \"No longer available\" }"
527+
val type = JsonHelper.mapTypeOf(String::class.java, String::class.java)
528+
whenever(mockResponseBody.source()).thenReturn(Buffer().writeUtf8("{ \"foo\": \"bar\" }"))
529+
nylasClient.executeDelete<Map<String, String>>("test/path", type, deleteBody)
530+
531+
val requestCaptor = argumentCaptor<Request>()
532+
verify(mockHttpClient).newCall(requestCaptor.capture())
533+
val capturedRequest = requestCaptor.firstValue
534+
val requestBodyBuffer = capturedRequest.body.asString()
535+
536+
assertEquals(capturedRequest.url.toString(), "https://api.us.nylas.com/test/path")
537+
assertEquals(capturedRequest.method, "DELETE")
538+
assertEquals(requestBodyBuffer, deleteBody)
539+
}
540+
524541
/**
525542
* Helper function to get the string value of a RequestBody
526543
* @return String value of the RequestBody

src/test/kotlin/com/nylas/resources/BookingsTest.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,35 @@ class BookingsTest {
185185
assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue)
186186
assertEquals(DeleteResponse::class.java, typeCaptor.firstValue)
187187
}
188+
189+
@Test
190+
fun `destroying a booking with a request body calls request with the correct params`() {
191+
val adapter = JsonHelper.moshi().adapter(DestroyBookingRequest::class.java)
192+
val bookingId = "booking-id"
193+
val requestBody = DestroyBookingRequest("No longer available")
194+
val queryParams = DestroyBookingQueryParams.Builder()
195+
.configurationId("config-id")
196+
.build()
197+
198+
bookings.destroy(bookingId, requestBody, queryParams, null)
199+
200+
val pathCaptor = argumentCaptor<String>()
201+
val typeCaptor = argumentCaptor<Type>()
202+
val requestBodyCaptor = argumentCaptor<String>()
203+
val queryParamCaptor = argumentCaptor<DestroyBookingQueryParams>()
204+
val overrideParamCaptor = argumentCaptor<RequestOverrides>()
205+
verify(mockNylasClient).executeDelete<DeleteResponse>(
206+
pathCaptor.capture(),
207+
typeCaptor.capture(),
208+
requestBodyCaptor.capture(),
209+
queryParamCaptor.capture(),
210+
overrideParamCaptor.capture(),
211+
)
212+
213+
assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue)
214+
assertEquals(DeleteResponse::class.java, typeCaptor.firstValue)
215+
assertEquals(adapter.toJson(requestBody), requestBodyCaptor.firstValue)
216+
assertEquals(queryParams, queryParamCaptor.firstValue)
217+
}
188218
}
189219
}

0 commit comments

Comments
 (0)