Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into salesforce-custom-obj…
Browse files Browse the repository at this point in the history
…ect-external-id
  • Loading branch information
seg-leonelsanches committed Oct 21, 2024
2 parents 60826ff + 2574714 commit 487f516
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ext.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
cache: yarn

- name: Install
run: yarn install --frozen-lockfile --ignore-optional
run: yarn install --frozen-lockfile

- name: Test
run: yarn test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@segment/analytics-browser-actions-braze-cloud-plugins",
"version": "1.73.0",
"version": "1.74.0",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand All @@ -15,7 +15,7 @@
},
"typings": "./dist/esm",
"dependencies": {
"@segment/analytics-browser-actions-braze": "^1.73.0",
"@segment/analytics-browser-actions-braze": "^1.74.0",
"@segment/browser-destination-runtime": "^1.67.0"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@segment/analytics-browser-actions-braze",
"version": "1.73.0",
"version": "1.74.0",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,180 @@ testSdkVersions.forEach((sdkVersion) => {
expect(brazeLogPurchase.mock.calls[1]).toMatchSnapshot()
})
})

describe('trackPurchase', () => {
const defaultMapping = {
purchaseProperties: {
'@path': '$.properties'
},
products: [
{
product_id: {
'@path': '$.properties.products.0.sku'
},
price: {
'@path': '$.properties.products.0.price'
},
currency: {
'@path': '$.properties.products.0.currency'
},
quantity: {
'@path': '$.properties.products.0.quantity'
}
}
]
}

it('TrackPurchase with default mapping', async () => {
const initializeSpy = jest.spyOn(destination, 'initialize')
const [trackPurchase] = await brazeDestination({
api_key: 'b_123',
endpoint: 'endpoint',
sdkVersion: '5.4',
doNotLoadFontAwesome: true,
subscriptions: [
{
partnerAction: 'trackPurchase',
name: 'Log Purchase',
enabled: true,
subscribe: 'type = "track"',
mapping: {
purchaseProperties: {
'@path': '$.properties'
},
products: {
'@path': '$.properties.products'
}
}
}
]
})

await trackPurchase.load(Context.system(), new Analytics({ writeKey: '123' }))

const { instance: braze } = await initializeSpy.mock.results[0].value
const brazeLogPurchase = jest.spyOn(braze, 'logPurchase').mockReturnValue(true)

const productProperties = {
banana: 'yellow',
products: [
{
product_id: 'p_123',
price: 100
},
{
product_id: 'p_456',
price: 488,
currency: 'USD',
quantity: 3
}
]
}

await trackPurchase.track?.(
new Context({
type: 'track',
name: 'Order Completed',
properties: productProperties
})
)

expect(brazeLogPurchase).toHaveBeenCalledTimes(2)
expect(brazeLogPurchase).toHaveBeenCalledWith('p_123', 100, 'USD', 1, productProperties)
expect(brazeLogPurchase).toHaveBeenCalledWith('p_456', 488, 'USD', 3, productProperties)
})

it('Should map product properties', async () => {
const initializeSpy = jest.spyOn(destination, 'initialize')
const [trackPurchase] = await brazeDestination({
api_key: 'b_123',
endpoint: 'endpoint',
sdkVersion: '5.4',
doNotLoadFontAwesome: true,
subscriptions: [
{
partnerAction: 'trackPurchase',
name: 'Log Purchase',
enabled: true,
subscribe: 'type = "track"',
mapping: defaultMapping
}
]
})

await trackPurchase.load(Context.system(), new Analytics({ writeKey: '123' }))

const { instance: braze } = await initializeSpy.mock.results[0].value
const brazeLogPurchase = jest.spyOn(braze, 'logPurchase').mockReturnValue(true)

await trackPurchase.track?.(
new Context({
type: 'track',
name: 'Order Completed',
properties: {
banana: 'yellow',
products: [
{
sku: 'sku_123',
price: 399,
currency: 'BGP',
quantity: 2
}
]
}
})
)

expect(brazeLogPurchase).toHaveBeenCalledTimes(1)
expect(brazeLogPurchase).toHaveBeenCalledWith('sku_123', 399, 'BGP', 2, {
banana: 'yellow',
products: [{ sku: 'sku_123', price: 399, currency: 'BGP', quantity: 2 }]
})
})

it('TrackPurchase with only product required properties', async () => {
const initializeSpy = jest.spyOn(destination, 'initialize')
const [trackPurchase] = await brazeDestination({
api_key: 'b_123',
endpoint: 'endpoint',
sdkVersion: '5.4',
doNotLoadFontAwesome: true,
subscriptions: [
{
partnerAction: 'trackPurchase',
name: 'Log Purchase',
enabled: true,
subscribe: 'type = "track"',
mapping: defaultMapping
}
]
})

await trackPurchase.load(Context.system(), new Analytics({ writeKey: '123' }))

const { instance: braze } = await initializeSpy.mock.results[0].value
const brazeLogPurchase = jest.spyOn(braze, 'logPurchase').mockReturnValue(true)

await trackPurchase.track?.(
new Context({
type: 'track',
name: 'Order Completed',
properties: {
banana: 'yellow',
products: [
{
sku: 'sku_123',
price: 100
}
]
}
})
)

expect(brazeLogPurchase).toHaveBeenCalledTimes(1)
expect(brazeLogPurchase).toHaveBeenCalledWith('sku_123', 100, 'USD', 1, {
banana: 'yellow',
products: [{ sku: 'sku_123', price: 100 }]
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,19 @@ const action: BrowserActionDefinition<Settings, BrazeDestinationClient, Payload>
const reservedKeys = Object.keys(action.fields.products.properties ?? {})
const purchaseProperties = omit(payload.purchaseProperties, reservedKeys)

if (purchaseProperties?.products && Array.isArray(purchaseProperties?.products)) {
purchaseProperties?.products?.forEach((product) => {
const result = client.instance.logPurchase(
(product.product_id as string | number).toString(),
product.price,
product.currency ?? 'USD',
product.quantity ?? 1,
purchaseProperties
)
payload.products?.forEach((product) => {
const result = client.instance.logPurchase(
(product.product_id as string | number).toString(),
product.price,
product.currency ?? 'USD',
product.quantity ?? 1,
purchaseProperties
)

if (!result) {
console.warn('Braze failed to attach purchase to the session for product ', product.productId)
}
})
}
if (!result) {
console.warn('Braze failed to attach purchase to the session for product ', product.product_id)
}
})
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@segment/analytics-browser-actions-intercom",
"version": "1.71.0",
"version": "1.72.0",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Subscription } from '@segment/browser-destination-runtime/types'
import { Analytics, Context } from '@segment/analytics-next'
import intercomDestination, { destination } from '../index'
import nock from 'nock'

const subscriptions: Subscription[] = [
{
Expand All @@ -26,6 +27,10 @@ const subscriptions: Subscription[] = [
]

describe('Intercom (actions)', () => {
beforeEach(() => {
nock('https://api-iam.intercom.io').get('/').reply(200)
})

test('loads Intercom with just appID', async () => {
const [event] = await intercomDestination({
appId: 'topSecretKey',
Expand Down
2 changes: 1 addition & 1 deletion packages/destination-actions/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@segment/action-destinations",
"description": "Destination Actions engine and definitions.",
"version": "3.335.0",
"version": "3.336.0",
"repository": {
"type": "git",
"url": "https://github.com/segmentio/action-destinations",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const HSPropTypeFieldType = {
NumberNumber: 'number:number',
DateTimeDate: 'datetime:date',
DateDate: 'date:date',
EnumerationBooleanCheckbox: 'enumeration:booleancheckbox'
EnumerationBooleanCheckbox: 'enumeration:booleancheckbox',
StringTextArea: 'string:textarea'
} as const

export type HSPropTypeFieldType = typeof HSPropTypeFieldType[keyof typeof HSPropTypeFieldType]
Expand All @@ -49,7 +50,8 @@ export const HSPropFieldType = {
Number: 'number',
Date: 'date',
BooleanCheckbox: 'booleancheckbox',
Select: 'select'
Select: 'select',
TextArea: 'textarea'
} as const

export type HSPropFieldType = typeof HSPropFieldType[keyof typeof HSPropFieldType]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ function formatHS(type: HSPropType, fieldType: HSPropFieldType): HSPropTypeField
return HSPropTypeFieldType.DateTimeDate
} else if (type === 'enumeration' && fieldType === 'booleancheckbox') {
return HSPropTypeFieldType.EnumerationBooleanCheckbox
} else if (type === 'string' && fieldType === 'textarea') {
return HSPropTypeFieldType.StringTextArea
}
throw new IntegrationError('Property type not supported', 'HUBSPOT_PROPERTY_TYPE_NOT_SUPPORTED', 400)
}
Expand Down Expand Up @@ -602,6 +604,16 @@ function checkForIncompatiblePropTypes(prop: Prop, hubspotProp?: Result) {
return
}

if (
hubspotProp.fieldType === 'textarea' &&
hubspotProp.type === 'string' &&
prop.fieldType === 'text' &&
prop.type === 'string'
) {
// string:text is OK to match to string:textarea
return
}

throw new IntegrationError(
`Payload property with name ${prop.name} has a different type to the property in HubSpot. Expected: type = ${prop.type} fieldType = ${prop.fieldType}. Received: type = ${hubspotProp.type} fieldType = ${hubspotProp.fieldType}`,
'HUBSPOT_PROPERTY_TYPE_MISMATCH',
Expand Down Expand Up @@ -638,6 +650,7 @@ export async function createProperties(client: Client, schemaDiff: SchemaDiff, p
fieldType: 'number'
}
case HSPropTypeFieldType.StringText:
case HSPropTypeFieldType.StringTextArea:
return {
name: prop.name,
label: prop.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('Mixpanel.groupIdentifyUser', () => {
const event = createTestEvent({
timestamp,
groupId: 'test-group-id',
traits: { hello: 'world', company: 'Mixpanel', name: 'test' }
traits: { hello: 'world', company: 'Mixpanel', name: 'test', created_at: timestamp }
})

nock('https://api.mixpanel.com').post('/groups').reply(200, {})
Expand All @@ -40,7 +40,8 @@ describe('Mixpanel.groupIdentifyUser', () => {
$set: {
hello: 'world',
company: 'Mixpanel',
$name: 'test'
$name: 'test',
$created: timestamp
}
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ const action: ActionDefinition<Settings, Payload> = {
const group_id = payload.traits[group_key] || payload.group_id

const traits = {
...omit(payload.traits, ['name']),
$name: payload.traits.name // transform to Mixpanel reserved property
...omit(payload.traits, ['created', 'createdAt', 'created_at', 'name']),
// transform to Mixpanel reserved property
$name: payload.traits.name,
$created: payload.traits.created ?? payload.traits.createdAt ?? payload.traits.created_at
}
const data = {
$token: settings.projectToken,
Expand Down
Loading

0 comments on commit 487f516

Please sign in to comment.