Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,102 @@ describe('Braze Cloud Mode (Actions)', () => {
])
})
})

it('should send subscription_groups with user profile updates', async () => {
nock('https://rest.iad-01.braze.com').post('/users/track').reply(200, {})

const event = createTestEvent({
type: 'identify',
userId: 'user1234',
traits: {
email: 'test@example.com',
firstName: 'John',
subscription_groups: [
{
subscription_group_id: 'newsletter_123',
subscription_state: 'subscribed'
},
{
subscription_group_id: 'promotional_456',
subscription_state: 'unsubscribed'
}
]
},
receivedAt
})

const responses = await testDestination.testAction('updateUserProfile', {
event,
settings,
mapping: {
external_id: 'user1234',
email: 'test@example.com',
first_name: 'John',
subscription_groups: { '@path': '$.traits.subscription_groups'}
}
})

expect(responses.length).toBe(1)
expect(responses[0].status).toBe(200)
expect(responses[0].data).toMatchObject({})
expect(responses[0].options.json).toMatchObject({
attributes: expect.arrayContaining([
expect.objectContaining({
external_id: 'user1234',
email: 'test@example.com',
first_name: 'John',
subscription_groups: [
{
subscription_group_id: 'newsletter_123',
subscription_state: 'subscribed'
},
{
subscription_group_id: 'promotional_456',
subscription_state: 'unsubscribed'
}
]
})
])
})
})

it('should handle empty subscription_groups array', async () => {
nock('https://rest.iad-01.braze.com').post('/users/track').reply(200, {})

const event = createTestEvent({
type: 'identify',
userId: 'user1234',
traits: {
email: 'test@example.com',
subscription_groups: []
},
receivedAt
})

const responses = await testDestination.testAction('updateUserProfile', {
event,
settings,
mapping: {
external_id: 'user1234',
email: 'test@example.com',
subscription_groups: { '@path': '$.traits.subscription_groups'}
}
})

expect(responses.length).toBe(1)
expect(responses[0].status).toBe(200)
expect(responses[0].options.json).toMatchObject({
attributes: expect.arrayContaining([
expect.objectContaining({
external_id: 'user1234',
email: 'test@example.com'
}),
expect.not.objectContaining({
subscription_groups: []
})
])
})
})
})

describe('trackEvent', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ describe('MultiStatus', () => {
},
braze_id: {
'@path': '$.traits.brazeId'
},
subscription_groups: {
'@path': '$.traits.subscription_groups'
}
}

Expand Down Expand Up @@ -757,6 +760,86 @@ describe('MultiStatus', () => {
}
])
})

it('should successfully handle a batch of events with subscription details, even if one fails validation', async () => {
nock(settings.endpoint).post('/users/track').reply(201, {})

const events: SegmentEvent[] = [
// Valid Event
createTestEvent({
type: 'identify',
receivedAt,
traits: {
firstName: 'Example',
lastName: 'User',
externalId: 'test-external-id',
subscription_groups: [
{
subscription_group_id: 'newsletter_123',
subscription_state: 'subscribed'
},
{
subscription_group_id: 'promotional_456',
subscription_state: 'unsubscribed'
}
]
}
}),
createTestEvent({
type: 'identify',
receivedAt,
traits: {
firstName: 'Example',
lastName: 'User',
email: 'user@example.com',
subscription_groups: [
{
subscription_group_id: 'newsletter_9898'
}
]
}
}),
// Event without any user identifier
createTestEvent({
type: 'identify',
receivedAt,
traits: {
firstName: 'Example',
lastName: 'User',
email: 'user@example.com',
subscription_groups: [
{
subscription_group_id: 'newsletter_9898',
subscription_state: 'unsubscribed'
}
]
}
})
]

const response = await testDestination.executeBatch('updateUserProfile', {
events,
settings,
mapping
})

expect(response[0]).toMatchObject({
status: 200,
body: 'success'
})

expect(response[1]).toMatchObject({
status: 400,
errortype: 'PAYLOAD_VALIDATION_FAILED',
errormessage: 'The value at /subscription_groups/0 is missing the required field \'subscription_state\'.',
errorreporter: 'INTEGRATIONS'
})

expect(response[2]).toMatchObject({
status: 200,
body: 'success'
})
})
})

describe('syncMode', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ Object {
"token": "M8rtOywDKgN((jhUBk9",
},
],
"subscription_groups": Array [
Object {
"subscription_group_id": "M8rtOywDKgN((jhUBk9",
"subscription_state": "unsubscribed",
},
],
"testType": "M8rtOywDKgN((jhUBk9",
"time_zone": "M8rtOywDKgN((jhUBk9",
"twitter": Object {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,31 @@ const action: ActionDefinition<Settings, Payload> = {
}
}
},
subscription_groups: {
label: 'Subscription Groups',
description: 'Array of objects used to manage a user\'s subscription status for specific subscription groups.',
type: 'object',
multiple: true,
defaultObjectUI: 'keyvalue',
properties: {
subscription_group_id: {
label: 'Subscription Group ID',
description: 'The identifier for the subscription group',
type: 'string',
required: true
},
subscription_state: {
label: 'Subscription State',
description: 'The user\'s subscription status: "subscribed" or "unsubscribed"',
type: 'string',
required: true,
choices: [
{ label: 'Subscribed', value: 'subscribed' },
{ label: 'Unsubscribed', value: 'unsubscribed' }
]
}
}
},
custom_attributes: {
label: 'Custom Attributes',
description: 'Hash of custom attributes to send to Braze',
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,31 @@ const action: ActionDefinition<Settings, Payload> = {
}
}
},
subscription_groups: {
label: 'Subscription Groups',
description: 'Array of objects used to manage a user\'s subscription status for specific subscription groups.',
type: 'object',
defaultObjectUI: 'keyvalue',
multiple: true,
properties: {
subscription_group_id: {
label: 'Subscription Group ID',
description: 'The identifier for the subscription group',
type: 'string',
required: true
},
subscription_state: {
label: 'Subscription State',
description: 'The user\'s subscription status: "subscribed" or "unsubscribed"',
type: 'string',
required: true,
choices: [
{ label: 'Subscribed', value: 'subscribed' },
{ label: 'Unsubscribed', value: 'unsubscribed' }
]
}
}
},
custom_attributes: {
label: 'Custom Attributes',
description: 'Hash of custom attributes to send to Braze',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ export function updateUserProfile(
push_tokens: payload.push_tokens,
time_zone: payload.time_zone,
twitter: payload.twitter,
...(typeof payload.subscription_groups === 'object' && Array.isArray(payload.subscription_groups) && payload.subscription_groups.length>0 ? { subscription_groups: payload.subscription_groups } : {}),
_update_existing_only: updateExistingOnly
}
]
Expand Down Expand Up @@ -513,6 +514,7 @@ export async function updateBatchedUserProfile(
push_tokens: payload.push_tokens,
time_zone: payload.time_zone,
twitter: payload.twitter,
...(typeof payload.subscription_groups === 'object' && Array.isArray(payload.subscription_groups) && payload.subscription_groups.length>0 ? { subscription_groups: payload.subscription_groups } : {}),
_update_existing_only: updateExistingOnly
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading