Skip to content

Commit

Permalink
Stratconn 2684 dynamic field to select audience (#1350)
Browse files Browse the repository at this point in the history
* Added log to test the dynamic field

* Convert audience id into dynamic field and removed log

* Added dynamic true

* Removed logs and updated the no.of api calls

* Remsolved typescript error

* Resolved comments of PR

* Added unit test case for dynamic fields

---------

Co-authored-by: Harsh Vardhan <[email protected]>
  • Loading branch information
hvardhan-unth and Harsh Vardhan authored Jul 11, 2023
1 parent f3c8131 commit 2c6164e
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import nock from 'nock'
import { createTestEvent, createTestIntegration } from '@segment/actions-core'
import { createTestEvent, createTestIntegration, DynamicFieldResponse } from '@segment/actions-core'
import Destination from '../../index'
import { BASE_URL, TIKTOK_API_VERSION } from '../../constants'

Expand Down Expand Up @@ -165,3 +165,26 @@ describe('TiktokAudiences.addUser', () => {
).rejects.toThrowError('At least one of Email Id or Advertising ID must be provided.')
})
})

describe('TiktokAudiences.dynamicField', () => {
it('should give error if selected_advertiser_id is not provided', async () => {
const settings = {
advertiser_ids: ['123']
}
const payload = {
selected_advertiser_id: ''
}
const responses = (await testDestination.testDynamicField('addUser', 'audience_id', {
settings,
payload
})) as DynamicFieldResponse

expect(responses).toMatchObject({
choices: [],
error: {
message: 'Please select Advertiser ID first to get list of Audience IDs.',
code: 'FIELD_NOT_SELECTED'
}
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ const action: ActionDefinition<Settings, Payload> = {
}
}
}
},
audience_id: async (request, { payload }) => {
try {
const tiktok = new TikTokAudiences(request)

return await tiktok.fetchAudiences(payload.selected_advertiser_id)
} catch (err) {
return {
choices: [],
error: {
message: JSON.stringify(err),
code: '500'
}
}
}
}
},
perform: async (request, { settings, payload }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,74 @@ describe('TikTok', () => {
})
})
})
describe('.fetchAudiences', () => {
const tiktok: TikTokAudiences = new TikTokAudiences(requestClient)

const selected_advertiser_id = '1234567890'
const page_number = 1

it('should dynamically fetch list of audiences and name', async () => {
nock(`${BASE_URL}${TIKTOK_API_VERSION}/dmp/custom_audience/list/`)
.get(`/`)
.query({
advertiser_id: selected_advertiser_id,
page: page_number,
page_size: '100'
})
.reply(200, {
code: 0,
message: 'success',
data: {
page_info: {
page_size: 10,
total_number: 1,
page: 1,
total_page: 1
},
list: [
{
cover_num: 6489086,
is_valid: false,
calculate_type: null,
is_creator: false,
audience_id: '123',
name: 'CUSTOM_AUDIENCE_NAME',
is_expiring: false,
create_time: '2022-05-26 22:12:12',
audience_type: 'Lookalike Audience',
expired_time: '2023-09-08 02:34:20',
shared: true
},
{
cover_num: 6489085,
is_valid: false,
calculate_type: null,
is_creator: false,
audience_id: '124',
name: 'CUSTOM_AUDIENCE_NAME1',
is_expiring: false,
create_time: '2022-05-26 22:12:12',
audience_type: 'Lookalike Audience',
expired_time: '2023-09-08 02:34:20',
shared: true
}
]
}
})

const fetchAudiencesRes = await tiktok.fetchAudiences(selected_advertiser_id)
expect(fetchAudiencesRes).toEqual({
choices: [
{
label: 'CUSTOM_AUDIENCE_NAME',
value: '123'
},
{
label: 'CUSTOM_AUDIENCE_NAME1',
value: '124'
}
]
})
})
})
})
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { RequestClient, ModifiedResponse } from '@segment/actions-core'
import { BASE_URL, TIKTOK_API_VERSION } from '../constants'
import type { GetAudienceAPIResponse, APIResponse, CreateAudienceAPIResponse } from '../types'
import type { GetAudienceAPIResponse, APIResponse, CreateAudienceAPIResponse, AudienceInfoError } from '../types'
import { DynamicFieldResponse } from '@segment/actions-core'
import type { Payload } from '../createAudience/generated-types'
import type { Audiences } from '../types'

interface AdvertiserInfoItem {
advertiser_id: string
Expand Down Expand Up @@ -41,20 +42,66 @@ export class TikTokAudiences {
})
}

async getAudiences(page_number: number, page_size: number): Promise<GetAudienceAPIResponse> {
const response: ModifiedResponse<GetAudienceAPIResponse> = await this.request(
`${BASE_URL}${TIKTOK_API_VERSION}/dmp/custom_audience/list/`,
{
method: 'GET',
searchParams: {
advertiser_id: this.selectedAdvertiserID ?? '',
page: page_number,
page_size: page_size
fetchAudiences = async (selected_advertiser_id: string): Promise<DynamicFieldResponse> => {
if (!selected_advertiser_id || !selected_advertiser_id.length) {
return {
choices: [],
error: {
message: 'Please select Advertiser ID first to get list of Audience IDs.',
code: 'FIELD_NOT_SELECTED'
}
}
)
}
try {
const response: Array<Audiences> = []
let page_number = 1
let total_page = 1
while (page_number <= total_page) {
const result = await this.request<GetAudienceAPIResponse>(
`${BASE_URL}${TIKTOK_API_VERSION}/dmp/custom_audience/list/`,
{
method: 'GET',
searchParams: {
advertiser_id: selected_advertiser_id,
page: page_number,
page_size: '100'
}
}
)

if (result.data.code !== 0) {
throw {
message: result.data.message,
code: result.data.code
}
}

total_page = result.data?.data?.page_info?.total_page || 1
page_number++
result.data.data.list.forEach((item) => {
response.push(item)
})
}

const choices = response?.map((item) => {
return {
label: item.name,
value: item.audience_id
}
})

return response.data
return {
choices: choices
}
} catch (err) {
return {
choices: [],
error: {
message: (err as AudienceInfoError).message ?? 'An error occurred while fetching audiences.',
code: (err as AudienceInfoError).code.toString() ?? 'FETCH_AUDIENCE_ERROR'
}
}
}
}

async createAudience(payload: Payload): Promise<ModifiedResponse<CreateAudienceAPIResponse>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const audience_id: InputField = {
description:
'Audience ID for the TikTok Audience you want to sync your Engage audience to. This is returned after you create an audience and can also be found in the TikTok Audiences dashboard.',
type: 'string',
dynamic: true,
required: true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const action: ActionDefinition<Settings, Payload> = {
selected_advertiser_id: async (request, { settings }) => {
try {
const tiktok = new TikTokAudiences(request)

return tiktok.fetchAdvertisers(settings.advertiser_ids)
} catch (err) {
return {
Expand All @@ -43,6 +42,21 @@ const action: ActionDefinition<Settings, Payload> = {
}
}
}
},
audience_id: async (request, { payload }) => {
try {
const tiktok = new TikTokAudiences(request)

return await tiktok.fetchAudiences(payload.selected_advertiser_id)
} catch (err) {
return {
choices: [],
error: {
message: JSON.stringify(err),
code: '500'
}
}
}
}
},
perform: async (request, { settings, payload }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ export interface Audiences {
expired_time: string
calculate_type: string
}

export interface AudienceInfoError {
code: number
message: string
}

0 comments on commit 2c6164e

Please sign in to comment.