diff --git a/src/cdk/v2/destinations/fullstory/procWorkflow.yaml b/src/cdk/v2/destinations/fullstory/procWorkflow.yaml new file mode 100644 index 0000000000..50ac2a8163 --- /dev/null +++ b/src/cdk/v2/destinations/fullstory/procWorkflow.yaml @@ -0,0 +1,104 @@ +bindings: + - name: EventType + path: ../../../../constants + - path: ../../bindings/jsontemplate + exportAll: true + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + +steps: + - name: validateInput + template: | + $.assert(.message.type, "message Type is not present. Aborting message."); + $.assert(.message.type in {{$.EventType.([.TRACK, .IDENTIFY])}}, + "message type " + .message.type + " is not supported"); + - name: prepareContext + template: | + $.context.messageType = .message.type.toLowerCase(); + $.context.payload = {}; + $.context.finalHeaders = { + "authorization": "Basic " + .destination.Config.apiKey, + "content-type": "application/json" + }; + - name: identifyPayload + condition: $.context.messageType == "identify" + template: | + $.context.endpoint = "https://api.fullstory.com/v2/users"; + $.context.payload.properties = .message.traits ?? .message.context.traits; + $.context.payload.uid = .message.userId; + $.context.payload.email = .message.context.traits.email; + $.context.payload.display_name = .message.context.traits.name; + + - name: trackPayload + condition: $.context.messageType == "track" + template: | + $.context.endpoint = "https://api.fullstory.com/v2/events"; + $.context.payload.name = .message.event; + $.context.payload.properties = .message.properties; + $.context.payload.timestamp = .message.originalTimestamp; + $.context.payload.context = {}; + + - name: validateEventName + condition: $.context.messageType == "track" + template: | + $.assert(.message.event, "event is required for track call") + + - name: mapContextFieldsForTrack + condition: $.context.messageType == "track" + template: | + $.context.payload.context.browser = { + "url": .message.context.page.url, + "user_agent": .message.context.userAgent, + "initial_referrer": .message.context.page.initial_referrer, + }; + $.context.payload.context.mobile = { + "app_name": .message.context.app.name, + "app_version": .message.context.app.version, + }; + $.context.payload.context.device = { + "manufacturer": .message.context.device.manufacturer, + "model": .message.context.device.model, + }; + $.context.payload.context.location = { + "ip_address": .message.context.ip, + "latitude": .message.properties.latitude, + "longitude": .message.properties.longitude, + "city": .message.properties.city, + "region": .message.properties.region, + "country": .message.properties.country, + }; + + - name: mapIdsForTrack + condition: $.context.messageType == "track" + template: | + $.context.payload.session = { + "id": .message.properties.sessionId, + "use_most_recent": .message.properties.useMostRecent, + }; + $.context.payload.user = { + "id": .message.properties.userId ?? .message.userId, + } + + - name: cleanPayload + template: | + $.context.payload = $.removeUndefinedAndNullValues($.context.payload); + - name: buildResponseForProcessTransformation + template: | + $.context.payload.({ + "body": { + "JSON": ., + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": $.context.endpoint, + "headers": $.context.finalHeaders, + "params": {}, + "files": {} + }) + + + diff --git a/test/__tests__/data/fullstory.json b/test/__tests__/data/fullstory.json new file mode 100644 index 0000000000..b6e462005b --- /dev/null +++ b/test/__tests__/data/fullstory.json @@ -0,0 +1,354 @@ +[ + { + "description": "Complete track event", + "input": { + "message": { + "anonymousId": "78c53c15-32a1-4b65-adac-bec2d7bb8fab", + "channel": "web", + "context": { + "app": { + "name": "RSPM", + "version": "1.9.0" + }, + "campaign": { + "name": "sales campaign", + "source": "google", + "medium": "medium", + "term": "event data", + "content": "Make sense of the modern data stack" + }, + "ip": "192.0.2.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "2.9.1" + }, + "locale": "en-US", + "device": { + "manufacturer": "Nokia", + "model": "N2023" + }, + "page": { + "path": "/best-seller/1", + "initial_referrer": "https://www.google.com/search", + "initial_referring_domain": "google.com", + "referrer": "https://www.google.com/search?q=estore+bestseller", + "referring_domain": "google.com", + "search": "estore bestseller", + "title": "The best sellers offered by EStore", + "url": "https://www.estore.com/best-seller/1" + }, + "screen": { + "density": 420, + "height": 1794, + "width": 1080, + "innerHeight": 200, + "innerWidth": 100 + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" + }, + "event": "Product Reviewed", + "integrations": { + "All": true + }, + "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383", + "properties": { + "userId": "u001", + "sessionId": "s001", + "review_id": "review_id_1", + "product_id": "product_id_1", + "rating": 5.0, + "review_body": "Sample Review Body", + "latitude": 44.56, + "longitude": 54.46, + "region": "Atlas", + "city": "NY", + "country": "USA" + }, + "originalTimestamp": "2020-01-09T10:01:53.558Z", + "type": "track", + "sentAt": "2020-01-09T10:02:03.257Z" + }, + "destination": { + "ID": "1pYpzzvcn7AQ2W9GGIAZSsN6Mfq", + "Name": "Fullstory", + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "apiKey": "dummyfullstoryAPIKey" + }, + "Enabled": true, + "Transformations": [] + }, + "metadata": { + "sourceType": "fddf", + "destinationType": "fdf", + "k8_namespace": "fdfd" + } + }, + "output": { + "body": { + "JSON": { + "name": "Product Reviewed", + "properties": { + "userId": "u001", + "sessionId": "s001", + "review_id": "review_id_1", + "product_id": "product_id_1", + "rating": 5, + "review_body": "Sample Review Body", + "latitude": 44.56, + "longitude": 54.46, + "region": "Atlas", + "city": "NY", + "country": "USA" + }, + "timestamp": "2020-01-09T10:01:53.558Z", + "context": { + "browser": { + "url": "https://www.estore.com/best-seller/1", + "user_agent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", + "initial_referrer": "https://www.google.com/search" + }, + "mobile": { + "app_name": "RSPM", + "app_version": "1.9.0" + }, + "device": { + "manufacturer": "Nokia", + "model": "N2023" + }, + "location": { + "ip_address": "192.0.2.0", + "latitude": 44.56, + "longitude": 54.46, + "city": "NY", + "region": "Atlas", + "country": "USA" + } + }, + "session": { + "id": "s001" + }, + "user": { + "id": "u001" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "method": "POST", + "params": {}, + "version": "1", + "type": "REST", + "endpoint": "https://api.fullstory.com/v2/events", + "headers": { + "authorization": "Basic dummyfullstoryAPIKey", + "content-type": "application/json" + }, + "files": {} + } + }, + { + "description": "Missing event name", + "input": { + "message": { + "channel": "web", + "context": { + "device": { + "manufacturer": "Nokia", + "model": "N2023" + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" + }, + "integrations": { + "All": true + }, + "properties": { + "userId": "u001", + "latitude": 44.56, + "longitude": 54.46, + "region": "Atlas", + "city": "NY", + "country": "USA" + }, + "originalTimestamp": "2020-01-09T10:01:53.558Z", + "type": "track", + "sentAt": "2020-01-09T10:02:03.257Z" + }, + "destination": { + "ID": "1pYpzzvcn7AQ2W9GGIAZSsN6Mfq", + "Name": "Fullstory", + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "apiKey": "dummyfullstoryAPIKey" + }, + "Enabled": true, + "Transformations": [] + }, + "metadata": { + "sourceType": "fddf", + "destinationType": "fdf", + "k8_namespace": "fdfd" + } + }, + "output": { + "error": "event is required for track call: Workflow: procWorkflow, Step: validateEventName, ChildStep: undefined, OriginalError: event is required for track call" + } + }, + { + "description": "Complete identify event", + "input": { + "message": { + "userId": "dummy-user001", + "channel": "web", + "context": { + "traits": { + "company": "Initech", + "address": { + "country": "USA", + "state": "CA", + "street": "101 dummy street" + }, + "email": "dummyuser@domain.com", + "name": "dummy user", + "phone": "099-999-9999" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" + }, + "integrations": { + "All": true + }, + "originalTimestamp": "2020-01-27T12:20:55.301Z", + "receivedAt": "2020-01-27T17:50:58.657+05:30", + "request_ip": "14.98.244.60", + "sentAt": "2020-01-27T12:20:56.849Z", + "timestamp": "2020-01-27T17:50:57.109+05:30", + "type": "identify" + }, + "destination": { + "ID": "1pYpzzvcn7AQ2W9GGIAZSsN6Mfq", + "Name": "Fullstory", + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "apiKey": "fullstoryAPIKey" + }, + "Enabled": true, + "Transformations": [] + }, + "metadata": { + "sourceType": "fddf", + "destinationType": "fdf", + "k8_namespace": "fdfd" + } + }, + "output": { + "body": { + "JSON": { + "properties": { + "company": "Initech", + "address": { + "country": "USA", + "state": "CA", + "street": "101 dummy street" + }, + "email": "dummyuser@domain.com", + "name": "dummy user", + "phone": "099-999-9999" + }, + "uid": "dummy-user001", + "email": "dummyuser@domain.com", + "display_name": "dummy user" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api.fullstory.com/v2/users", + "headers": { + "authorization": "Basic fullstoryAPIKey", + "content-type": "application/json" + }, + "params": {}, + "files": {} + } + }, + { + "description": "Identify event with needed traits", + "input": { + "message": { + "userId": "dummy-user001", + "channel": "web", + "context": { + "traits": { + "email": "dummyuser@domain.com", + "name": "dummy user", + "phone": "099-999-9999" + } + }, + "timestamp": "2020-01-27T17:50:57.109+05:30", + "type": "identify" + }, + "destination": { + "ID": "1pYpzzvcn7AQ2W9GGIAZSsN6Mfq", + "Name": "Fullstory", + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "apiKey": "fullstoryAPIKey" + }, + "Enabled": true, + "Transformations": [] + }, + "metadata": { + "sourceType": "fddf", + "destinationType": "fdf", + "k8_namespace": "fdfd" + } + }, + "output": { + "body": { + "JSON": { + "properties": { + "email": "dummyuser@domain.com", + "name": "dummy user", + "phone": "099-999-9999" + }, + "uid": "dummy-user001", + "email": "dummyuser@domain.com", + "display_name": "dummy user" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api.fullstory.com/v2/users", + "headers": { + "authorization": "Basic fullstoryAPIKey", + "content-type": "application/json" + }, + "params": {}, + "files": {} + } + } +] diff --git a/test/__tests__/fullstory-cdk.test.ts b/test/__tests__/fullstory-cdk.test.ts new file mode 100644 index 0000000000..f7e0491aac --- /dev/null +++ b/test/__tests__/fullstory-cdk.test.ts @@ -0,0 +1,32 @@ +import fs from 'fs'; +import path from 'path'; +import { processCdkV2Workflow } from '../../src/cdk/v2/handler'; +import tags from '../../src/v0/util/tags'; + +const integration = 'fullstory'; +const destName = 'Fullstory'; + +// Processor Test files +const testDataFile = fs.readFileSync(path.resolve(__dirname, `./data/${integration}.json`), { + encoding: 'utf8', +}); +const testData = JSON.parse(testDataFile); + +describe(`${destName} Tests`, () => { + describe('Processor Tests', () => { + testData.forEach((dataPoint, index) => { + it(`${destName} - payload: ${index}`, async () => { + try { + const output = await processCdkV2Workflow( + integration, + dataPoint.input, + tags.FEATURES.PROCESSOR, + ); + expect(output).toEqual(dataPoint.output); + } catch (error: any) { + expect(error.message).toEqual(dataPoint.output.error); + } + }); + }); + }); +});