Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Nylas Java SDK Changelog


## [Unreleased]

### Added
* Support for `logo` field in `EmailTemplate` class to specify a custom logo URL for booking emails
* Support for `show_nylas_branding` field in `EmailTemplate` class to control Nylas branding visibility in booking emails

## [2.10.0] - Release 2025-06-12

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,61 @@ data class EmailTemplate(
*/
@Json(name = "booking_confirmed")
val bookingConfirmed: BookingConfirmedTemplate? = null,
)
/**
* URL of a custom logo to appear in booking emails.
*/
@Json(name = "logo")
val logo: String? = null,
/**
* Boolean flag to toggle Nylas branding visibility.
*/
@Json(name = "show_nylas_branding")
val showNylasBranding: Boolean? = null,
) {
/**
* Builder for [EmailTemplate].
*/
class Builder {
private var bookingConfirmed: BookingConfirmedTemplate? = null
private var logo: String? = null
private var showNylasBranding: Boolean? = null

/**
* Set the configurable settings specifically for booking confirmed emails.
*
* @param bookingConfirmed Configurable settings specifically for booking confirmed emails.
* @return The builder.
*/
fun bookingConfirmed(bookingConfirmed: BookingConfirmedTemplate) = apply { this.bookingConfirmed = bookingConfirmed }

/**
* Set the URL of a custom logo to appear in booking emails.
*
* @param logo URL of a custom logo to appear in booking emails.
* @return The builder.
*/
fun logo(logo: String) = apply { this.logo = logo }

/**
* Set the boolean flag to toggle Nylas branding visibility.
*
* @param showNylasBranding Boolean flag to toggle Nylas branding visibility.
* @return The builder.
*/
fun showNylasBranding(showNylasBranding: Boolean) = apply { this.showNylasBranding = showNylasBranding }

/**
* Build the [EmailTemplate].
*
* @return The [EmailTemplate]
*/
fun build() = EmailTemplate(
bookingConfirmed,
logo,
showNylasBranding,
)
}
}

/**
* Class representation of booking confirmed template settings.
Expand Down
128 changes: 128 additions & 0 deletions src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,54 @@ class ConfigurationsTest {
assertEquals("Test", config.participants.first().name)
assertEquals("", config.participants.first().timezone)
}

@Test
fun `EmailTemplate with new fields serializes properly`() {
val adapter = JsonHelper.moshi().adapter(EmailTemplate::class.java)
val jsonBuffer = Buffer().writeUtf8(
"""
{
"booking_confirmed": {
"title": "Custom Booking Title",
"body": "Thank you for booking with us!"
},
"logo": "https://example.com/logo.png",
"show_nylas_branding": false
}
""".trimIndent(),
)

val emailTemplate = adapter.fromJson(jsonBuffer)!!
assertIs<EmailTemplate>(emailTemplate)
assertEquals("https://example.com/logo.png", emailTemplate.logo)
assertEquals(false, emailTemplate.showNylasBranding)
assertEquals("Custom Booking Title", emailTemplate.bookingConfirmed?.title)
assertEquals("Thank you for booking with us!", emailTemplate.bookingConfirmed?.body)

// Test serialization back to JSON
val serializedJson = adapter.toJson(emailTemplate)
assert(serializedJson.contains("\"logo\":\"https://example.com/logo.png\""))
assert(serializedJson.contains("\"show_nylas_branding\":false"))
}

@Test
fun `EmailTemplate Builder works correctly`() {
val bookingConfirmed = BookingConfirmedTemplate(
title = "Custom Title",
body = "Custom Body",
)

val emailTemplate = EmailTemplate.Builder()
.bookingConfirmed(bookingConfirmed)
.logo("https://company.com/logo.svg")
.showNylasBranding(true)
.build()

assertEquals("https://company.com/logo.svg", emailTemplate.logo)
assertEquals(true, emailTemplate.showNylasBranding)
assertEquals("Custom Title", emailTemplate.bookingConfirmed?.title)
assertEquals("Custom Body", emailTemplate.bookingConfirmed?.body)
}
}

@Nested
Expand Down Expand Up @@ -402,5 +450,85 @@ class ConfigurationsTest {
assertEquals("v3/grants/$grantId/scheduling/configurations/$configId", pathCaptor.firstValue)
assertEquals(DeleteResponse::class.java, typeCaptor.firstValue)
}

@Test
fun `creating a configuration with custom email template calls requests with the correct params`() {
val adapter = JsonHelper.moshi().adapter(CreateConfigurationRequest::class.java)
val participantCalendarIds = ArrayList<String>()
participantCalendarIds.add("primary")

val configurationAvailabilityParticipant = ConfigurationAvailabilityParticipant.Builder().calendarIds(participantCalendarIds).build()

val configurationBookingParticipant = ConfigurationBookingParticipant.Builder().calendarId("primary").build()

val configurationParticipant = ConfigurationParticipant.Builder("test@nylas.com")
.availability(configurationAvailabilityParticipant)
.booking(configurationBookingParticipant)
.name("Test Participant")
.isOrganizer(true)
.build()

val configurationAvailability = ConfigurationAvailability.Builder().intervalMinutes(30).build()

val configurationEventBooking = ConfigurationEventBooking.Builder().title("Test Event Booking").build()

// Create EmailTemplate with new logo and showNylasBranding fields
val emailTemplate = EmailTemplate.Builder()
.logo("https://company.com/custom-logo.png")
.showNylasBranding(false)
.bookingConfirmed(
BookingConfirmedTemplate(
title = "Your Meeting is Confirmed",
body = "Thank you for booking! We look forward to meeting with you.",
),
)
.build()

// Create scheduler settings with the email template
val schedulerSettings = ConfigurationSchedulerSettings.Builder()
.emailTemplate(emailTemplate)
.availableDaysInFuture(14)
.minBookingNotice(120)
.build()

val participants = ArrayList<ConfigurationParticipant>()
participants.add(configurationParticipant)

val createConfigurationRequest = CreateConfigurationRequest.Builder(
participants,
configurationAvailability,
configurationEventBooking,
)
.name("Configuration with Custom Email Template")
.scheduler(schedulerSettings)
.build()

configurations.create(grantId, createConfigurationRequest)

val pathCaptor = argumentCaptor<String>()
val typeCaptor = argumentCaptor<Type>()
val requestBodyCaptor = argumentCaptor<String>()
val queryParamCaptor = argumentCaptor<ListConfigurationsQueryParams>()
val overrideParamCaptor = argumentCaptor<RequestOverrides>()
verify(mockNylasClient).executePost<Response<Configuration>>(
pathCaptor.capture(),
typeCaptor.capture(),
requestBodyCaptor.capture(),
queryParamCaptor.capture(),
overrideParamCaptor.capture(),
)

assertEquals("v3/grants/$grantId/scheduling/configurations", pathCaptor.firstValue)
assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue)

val serializedRequest = adapter.toJson(createConfigurationRequest)
assertEquals(serializedRequest, requestBodyCaptor.firstValue)

// Verify that the JSON contains the new EmailTemplate fields
assert(serializedRequest.contains("\"logo\":\"https://company.com/custom-logo.png\""))
assert(serializedRequest.contains("\"show_nylas_branding\":false"))
assert(serializedRequest.contains("\"booking_confirmed\""))
assert(serializedRequest.contains("Your Meeting is Confirmed"))
}
}
}
Loading