Skip to content

Commit

Permalink
STRATCONN-4169 | Events to Klaviyo destination is failing for delivery (
Browse files Browse the repository at this point in the history
#2407)

* STRATCONN-4169 | Events to Klaviyo destination is failing for  delivery

* used dayjs library to convert the timestamp to ISO String

* Updated unit test case

---------

Co-authored-by: Gaurav Kochar <[email protected]>
  • Loading branch information
Innovative-GauravKochar and Gaurav Kochar authored Oct 1, 2024
1 parent 504702a commit 3fefc02
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Order Completed should not pass time property in API when it is not mapped 1`] = `"{\\"data\\":{\\"type\\":\\"event\\",\\"attributes\\":{\\"properties\\":{\\"key\\":\\"value\\"},\\"value\\":10,\\"metric\\":{\\"data\\":{\\"type\\":\\"metric\\",\\"attributes\\":{\\"name\\":\\"Order Completed\\"}}},\\"profile\\":{\\"data\\":{\\"type\\":\\"profile\\",\\"attributes\\":{\\"anonymous_id\\":\\"an0nym0u51d\\"}}}}}}"`;

exports[`Order Completed should not throw an error when the time property has more than three digits in the milliseconds and should convert the time to ISO format. 1`] = `"{\\"data\\":{\\"type\\":\\"event\\",\\"attributes\\":{\\"properties\\":{\\"key\\":\\"value\\"},\\"time\\":\\"2024-07-22T20:08:49.891Z\\",\\"value\\":10,\\"metric\\":{\\"data\\":{\\"type\\":\\"metric\\",\\"attributes\\":{\\"name\\":\\"Order Completed\\"}}},\\"profile\\":{\\"data\\":{\\"type\\":\\"profile\\",\\"attributes\\":{\\"anonymous_id\\":\\"an0nym0u51d\\"}}}}}}"`;

exports[`Order Completed should successfully convert the timestamp for the time property to ISO format. 1`] = `"{\\"data\\":{\\"type\\":\\"event\\",\\"attributes\\":{\\"properties\\":{\\"key\\":\\"value\\"},\\"time\\":\\"2024-07-22T20:08:49.890Z\\",\\"value\\":10,\\"metric\\":{\\"data\\":{\\"type\\":\\"metric\\",\\"attributes\\":{\\"name\\":\\"Order Completed\\"}}},\\"profile\\":{\\"data\\":{\\"type\\":\\"profile\\",\\"attributes\\":{\\"anonymous_id\\":\\"an0nym0u51d\\"}}}}}}"`;
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ const createRequestBody = (
properties: Record<string, any>,
value: number,
metricName: string,
profile: Record<string, any>
profile: Record<string, any>,
time?: string
) => ({
data: {
type: 'event',
attributes: {
properties,
value,
time,
metric: createMetric(metricName),
profile: {
data: {
Expand Down Expand Up @@ -209,4 +211,69 @@ describe('Order Completed', () => {

await expect(testDestination.testAction(`orderCompleted`, { event, mapping, settings })).resolves.not.toThrowError()
})

it('should not throw an error when the time property has more than three digits in the milliseconds and should convert the time to ISO format.', async () => {
const profile = { anonymous_id: 'an0nym0u51d' }
const properties = { key: 'value' }
const metricName = 'Order Completed'
const value = 10
const eventName = 'Order Completed'
const time = '2024-07-22T20:08:49.891Z' // convert the timestamp from '2024-07-22T20:08:49.89191341Z'
const timestamp = '2024-07-22T20:08:49.89191341Z'
const requestBody = createRequestBody(properties, value, metricName, profile, time)

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp
})

const mapping = { profile, metric_name: metricName, properties, value, event_name: eventName, time: timestamp }
const res = await testDestination.testAction('orderCompleted', { event, mapping, settings })
expect(res[0].options.body).toMatchSnapshot()
})

it('should successfully convert the timestamp for the time property to ISO format.', async () => {
const profile = { anonymous_id: 'an0nym0u51d' }
const properties = { key: 'value' }
const metricName = 'Order Completed'
const value = 10
const eventName = 'Order Completed'
const time = '2024-07-22T20:08:49.890Z'
const timestamp = '2024-07-22T20:08:49.89Z'
const requestBody = createRequestBody(properties, value, metricName, profile, time)

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp
})

const mapping = { profile, metric_name: metricName, properties, value, event_name: eventName, time: timestamp }
const res = await testDestination.testAction('orderCompleted', { event, mapping, settings })
expect(res[0].options.body).toMatchSnapshot()
})
it('should not pass time property in API when it is not mapped', async () => {
const profile = { anonymous_id: 'an0nym0u51d' }
const properties = { key: 'value' }
const metricName = 'Order Completed'
const value = 10
const eventName = 'Order Completed'
const timestamp = '2024-07-22T20:08:49.89191341Z'
const requestBody = createRequestBody(properties, value, metricName, profile)

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp
})

const mapping = { profile, metric_name: metricName, properties, value, event_name: eventName }

const res = await testDestination.testAction('orderCompleted', { event, mapping, settings })
expect(res[0].options.body).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import { API_URL } from '../config'
import { EventData } from '../types'
import { v4 as uuidv4 } from '@lukeed/uuid'
import { validatePhoneNumber } from '../functions'
import dayjs from 'dayjs'

const createEventData = (payload: Payload) => ({
data: {
type: 'event',
attributes: {
properties: { ...payload.properties },
time: payload.time,
time: payload.time ? dayjs(payload.time).toISOString() : undefined,
value: payload.value,
unique_id: payload.unique_id,
metric: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Track Event should not pass time property in API when it is not mapped or defined 1`] = `"{\\"data\\":{\\"type\\":\\"event\\",\\"attributes\\":{\\"properties\\":{\\"key\\":\\"value\\"},\\"value\\":10,\\"unique_id\\":\\"text-example-xyz\\",\\"metric\\":{\\"data\\":{\\"type\\":\\"metric\\",\\"attributes\\":{\\"name\\":\\"event_name\\"}}},\\"profile\\":{\\"data\\":{\\"type\\":\\"profile\\",\\"attributes\\":{\\"anonymous_id\\":\\"an0nym0u51d\\"}}}}}}"`;

exports[`Track Event should not throw an error when the time property has more than three digits in the milliseconds and should convert the time to ISO format. 1`] = `"{\\"data\\":{\\"type\\":\\"event\\",\\"attributes\\":{\\"properties\\":{\\"key\\":\\"value\\"},\\"time\\":\\"2024-09-11T20:08:49.891Z\\",\\"value\\":10,\\"unique_id\\":\\"text-example-xyz\\",\\"metric\\":{\\"data\\":{\\"type\\":\\"metric\\",\\"attributes\\":{\\"name\\":\\"event_name\\"}}},\\"profile\\":{\\"data\\":{\\"type\\":\\"profile\\",\\"attributes\\":{\\"anonymous_id\\":\\"an0nym0u51d\\"}}}}}}"`;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export const settings = {
}

describe('Track Event', () => {
beforeEach(() => {
nock.cleanAll()
jest.resetAllMocks()
})

it('should throw error if no profile identifiers are provided', async () => {
const event = createTestEvent({
type: 'track'
Expand Down Expand Up @@ -238,4 +243,148 @@ describe('Track Event', () => {
testDestination.testAction('trackEvent', { event, mapping, settings, useDefaultMappings: true })
).rejects.toThrowError('Internal Server Error')
})

it('should successfully convert the timestamp for the time property to ISO format.', async () => {
const requestBody = {
data: {
type: 'event',
attributes: {
properties: { key: 'value' },
time: '2024-07-22T20:08:49.790Z',
value: 10,
unique_id: 'text-example-xyz',
metric: {
data: {
type: 'metric',
attributes: {
name: 'event_name'
}
}
},
profile: {
data: {
type: 'profile',
attributes: {
anonymous_id: 'an0nym0u51d'
}
}
}
}
}
}

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp: '2024-07-22T20:08:49.79Z'
})

const mapping = {
profile: { anonymous_id: 'an0nym0u51d' },
metric_name: 'event_name',
properties: { key: 'value' },
value: 10,
unique_id: 'text-example-xyz'
}

await expect(
testDestination.testAction('trackEvent', { event, mapping, settings, useDefaultMappings: true })
).resolves.not.toThrowError()
})
it('should not throw an error when the time property has more than three digits in the milliseconds and should convert the time to ISO format.', async () => {
const timestamp = '2024-09-11T20:08:49.8919123123Z'
const requestBody = {
data: {
type: 'event',
attributes: {
properties: { key: 'value' },
time: '2024-09-11T20:08:49.891Z', // convert the timestamp from '2024-07-22T20:08:49.89191341Z'
value: 10,
unique_id: 'text-example-xyz',
metric: {
data: {
type: 'metric',
attributes: {
name: 'event_name'
}
}
},
profile: {
data: {
type: 'profile',
attributes: {
anonymous_id: 'an0nym0u51d'
}
}
}
}
}
}

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp
})

const mapping = {
profile: { anonymous_id: 'an0nym0u51d' },
metric_name: 'event_name',
properties: { key: 'value' },
value: 10,
unique_id: 'text-example-xyz'
}

const res = await testDestination.testAction('trackEvent', { event, mapping, settings, useDefaultMappings: true })
expect(res[0].options.body).toMatchSnapshot()
})

it('should not pass time property in API when it is not mapped or defined', async () => {
const requestBody = {
data: {
type: 'event',
attributes: {
properties: { key: 'value' },
value: 10,
unique_id: 'text-example-xyz',
metric: {
data: {
type: 'metric',
attributes: {
name: 'event_name'
}
}
},
profile: {
data: {
type: 'profile',
attributes: {
anonymous_id: 'an0nym0u51d'
}
}
}
}
}
}

nock(`${API_URL}`).post('/events/', requestBody).reply(200, {})

const event = createTestEvent({
type: 'track',
timestamp: '2024-07-22T20:08:49.79Z'
})

const mapping = {
profile: { anonymous_id: 'an0nym0u51d' },
metric_name: 'event_name',
properties: { key: 'value' },
value: 10,
unique_id: 'text-example-xyz'
}

const res = await testDestination.testAction('trackEvent', { event, mapping, settings })
expect(res[0].options.body).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Payload } from './generated-types'
import { PayloadValidationError } from '@segment/actions-core'
import { API_URL } from '../config'
import { validatePhoneNumber } from '../functions'
import dayjs from 'dayjs'

const action: ActionDefinition<Settings, Payload> = {
title: 'Track Event',
Expand Down Expand Up @@ -98,13 +99,12 @@ const action: ActionDefinition<Settings, Payload> = {
if (phone_number && !validatePhoneNumber(phone_number)) {
throw new PayloadValidationError(`${phone_number} is not a valid E.164 phone number.`)
}

const eventData = {
data: {
type: 'event',
attributes: {
properties: { ...payload.properties },
time: payload.time,
time: payload?.time ? dayjs(payload.time).toISOString() : undefined,
value: payload.value,
unique_id: payload.unique_id,
metric: {
Expand Down

0 comments on commit 3fefc02

Please sign in to comment.