Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Testing snapshot for actions-kochava destination: event action - all fields 1`] = `
Object {
"action": "event",
"data": Object {
"app_tracking_transparency": Object {
"att": false,
"att_detail": "c)30knD9jX&cI",
"att_duration": 1955441609277.44,
"att_time": 1955441609277.44,
},
"app_version": "c)30knD9jX&cI",
"currency": "AMD",
"device_ids": Object {
"adid": "c)30knD9jX&cI",
"android_id": "c)30knD9jX&cI",
"idfa": "c)30knD9jX&cI",
"idfv": "c)30knD9jX&cI",
},
"device_limit_tracking": true,
"device_ua": "c)30knD9jX%26cI",
"device_ver": "c)30knD9jX&cI",
"event_data": Object {
"testType": "c)30knD9jX&cI",
},
"event_name": "c)30knD9jX&cI",
"origination_ip": "c)30knD9jX&cI",
"usertime": 1612137600,
},
"kochava_app_id": "c)30knD9jX&cI",
"kochava_device_id": "c)30knD9jX&cI",
}
`;

exports[`Testing snapshot for actions-kochava destination: event action - required fields 1`] = `
Object {
"action": "event",
"data": Object {
"device_ids": Object {
"adid": "c)30knD9jX&cI",
"android_id": "c)30knD9jX&cI",
"idfa": "c)30knD9jX&cI",
"idfv": "c)30knD9jX&cI",
},
"event_name": "c)30knD9jX&cI",
},
"kochava_app_id": "c)30knD9jX&cI",
"kochava_device_id": "c)30knD9jX&cI",
}
`;

exports[`Testing snapshot for actions-kochava destination: install action - all fields 1`] = `
Object {
"action": "install",
"data": Object {
"ad_services_token": "2m*qGXENfE",
"app_tracking_transparency": Object {
"att": true,
"att_detail": "2m*qGXENfE",
"att_duration": -32716306922864.64,
"att_time": -32716306922864.64,
},
"app_version": "2m*qGXENfE",
"device_ids": Object {
"adid": "2m*qGXENfE",
"android_id": "2m*qGXENfE",
"idfa": "2m*qGXENfE",
"idfv": "2m*qGXENfE",
},
"device_ua": "2m*qGXENfE",
"device_ver": "2m*qGXENfE",
"origination_ip": "2m*qGXENfE",
"usertime": 1612137600,
},
"kochava_app_id": "2m*qGXENfE",
"kochava_device_id": "2m*qGXENfE",
}
`;

exports[`Testing snapshot for actions-kochava destination: install action - required fields 1`] = `
Object {
"action": "install",
"data": Object {
"device_ids": Object {
"adid": "2m*qGXENfE",
"android_id": "2m*qGXENfE",
"idfa": "2m*qGXENfE",
"idfv": "2m*qGXENfE",
},
},
"kochava_app_id": "2m*qGXENfE",
"kochava_device_id": "2m*qGXENfE",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Destination from '../index'

describe('Kochava (Actions)', () => {
it('exposes the expected metadata', () => {
expect(Destination.name).toBe('Kochava (Actions)')
expect(Destination.slug).toBe('actions-kochava')
expect(Destination.mode).toBe('cloud')
})

it('registers the event and install actions', () => {
expect(Object.keys(Destination.actions)).toEqual(expect.arrayContaining(['event', 'install']))
})

it('requires the kochava_app_id setting', () => {
const fields = Destination.authentication?.fields
expect(fields?.kochava_app_id?.required).toBe(true)
})

it('defines presets for both actions', () => {
const partnerActions = (Destination.presets ?? []).map((p) => p.partnerAction)
expect(partnerActions).toEqual(expect.arrayContaining(['event', 'install']))
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { createTestEvent, createTestIntegration } from '@segment/actions-core'
import { generateTestData } from '../../../lib/test-data'
import destination from '../index'
import nock from 'nock'

const testDestination = createTestIntegration(destination)
const destinationSlug = 'actions-kochava'

describe(`Testing snapshot for ${destinationSlug} destination:`, () => {
for (const actionSlug in destination.actions) {
it(`${actionSlug} action - required fields`, async () => {
const seedName = `${destinationSlug}#${actionSlug}`
const action = destination.actions[actionSlug]
const [eventData, settingsData] = generateTestData(seedName, destination, action, true)

nock(/.*/).persist().get(/.*/).reply(200)
nock(/.*/).persist().post(/.*/).reply(200)
nock(/.*/).persist().put(/.*/).reply(200)
Comment on lines +16 to +18

const event = createTestEvent({
properties: eventData
})

const responses = await testDestination.testAction(actionSlug, {
event: event,
mapping: event.properties,
settings: settingsData,
auth: undefined
})

const request = responses[0].request
const rawBody = await request.text()

try {
const json = JSON.parse(rawBody)
expect(json).toMatchSnapshot()
return
} catch (err) {
expect(rawBody).toMatchSnapshot()
}

expect(request.headers).toMatchSnapshot()
})

it(`${actionSlug} action - all fields`, async () => {
const seedName = `${destinationSlug}#${actionSlug}`
const action = destination.actions[actionSlug]
const [eventData, settingsData] = generateTestData(seedName, destination, action, false)

nock(/.*/).persist().get(/.*/).reply(200)
nock(/.*/).persist().post(/.*/).reply(200)
nock(/.*/).persist().put(/.*/).reply(200)

const event = createTestEvent({
properties: eventData
})

const responses = await testDestination.testAction(actionSlug, {
event: event,
mapping: event.properties,
settings: settingsData,
auth: undefined
})

const request = responses[0].request
const rawBody = await request.text()

try {
const json = JSON.parse(rawBody)
expect(json).toMatchSnapshot()
return
} catch (err) {
expect(rawBody).toMatchSnapshot()
}
})
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const BASE_URL = 'https://control.kochava.com'

export const TRACK_ENDPOINT = `${BASE_URL}/track/json`

// Kochava multiplexes install vs event tracking through the top-level `action` field
// on the same /track/json endpoint.
export const KochavaAction = {
Install: 'install',
Event: 'event'
} as const

export type KochavaActionType = typeof KochavaAction[keyof typeof KochavaAction]

// The device identifier keys Kochava recognises inside the `device_ids` object.
export const DEVICE_ID_KEYS = ['idfa', 'idfv', 'adid', 'android_id'] as const
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import nock from 'nock'
import { createTestEvent, createTestIntegration } from '@segment/actions-core'
import Destination from '../../index'

const testDestination = createTestIntegration(Destination)

const settings = { kochava_app_id: 'ko-app-guid-123' }

describe('Kochava.event', () => {
afterEach(() => {
nock.cleanAll()
})

it('sends a post-install event with action "event" and epoch-seconds usertime', async () => {
nock('https://control.kochava.com').post('/track/json').reply(200, {})

const event = createTestEvent({
type: 'track',
event: 'Subscription Started',
timestamp: '2021-03-20T18:06:56.000Z',
properties: { currency: 'USD', sum: 150 },
context: {
device: { id: 'device-1', advertisingId: 'idfa-abc', adTrackingEnabled: true },
os: { version: '14.4' },
app: { version: '1.0.0' },
userAgent: 'Mozilla/5.0 (iPhone)',
ip: '104.219.46.66'
}
})

const responses = await testDestination.testAction('event', {
event,
settings,
useDefaultMappings: true
})

expect(responses.length).toBe(1)
expect(responses[0].status).toBe(200)

const body = JSON.parse(responses[0].options.body as string)
expect(body.action).toBe('event')
expect(body.kochava_app_id).toBe('ko-app-guid-123')
expect(body.data.event_name).toBe('Subscription Started')
expect(body.data.device_ids.idfa).toBe('idfa-abc')
expect(body.data.usertime).toBe(1616263616)
// device_ua is URL-encoded
expect(body.data.device_ua).toBe(encodeURIComponent('Mozilla/5.0 (iPhone)'))
// ad_tracking_enabled true -> device_limit_tracking false
expect(body.data.device_limit_tracking).toBe(false)
expect(body.data.currency).toBe('USD')
})

it('overrides the settings App ID with the mapped kochava_app_id', async () => {
nock('https://control.kochava.com').post('/track/json').reply(200, {})

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

const responses = await testDestination.testAction('event', {
event,
settings,
mapping: {
kochava_app_id: 'override-guid',
event_name: 'Purchase',
idfa: 'idfa-xyz',
device_ver: '15.0'
}
})

const body = JSON.parse(responses[0].options.body as string)
expect(body.kochava_app_id).toBe('override-guid')
expect(body.data.device_ids.idfa).toBe('idfa-xyz')
})

it('throws a validation error when no device identifier is present', async () => {
const event = createTestEvent({ type: 'track', event: 'Purchase' })

await expect(
testDestination.testAction('event', {
event,
settings,
mapping: {
event_name: 'Purchase',
idfa: '',
device_ver: '15.0'
}
})
).rejects.toThrow('At least one device identifier')
})
})

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

Loading
Loading