diff --git a/.eslintrc.json b/.eslintrc.json index c2614ac5ef..d2928e50fd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -54,7 +54,7 @@ "@typescript-eslint/no-explicit-any": "off", "class-methods-use-this": "off", "@typescript-eslint/return-await": "error", - "import/prefer-default-export": "error", + "import/prefer-default-export": "off", "sonarjs/no-ignored-return": "error", "no-new": "error", "@typescript-eslint/no-shadow": "error", diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..5b716b7e9f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,57 @@ +## What are the changes introduced in this PR? + +Write a brief explainer on your code changes. + +## Please explain the objectives of your changes below + +Put down any required details on the broader aspect of your changes. If there are any dependent changes, **mandatorily** mention them here + +### Type of change + +If the pull request is a **bug-fix**, **enhancement** or a **refactor**, please fill in the details on the changes made. + +- Existing capabilities/behavior + +- New capabilities/behavior + +If the pull request is a **new feature**, + +### Any technical or performance related pointers to consider with the change? + +N/A + +### Any new dependencies introduced with this change? + +N/A + +### Any new generic utility introduced or modified. Please explain the changes. + +N/A + +### If the PR has changes in more than 10 files, please mention why the changes were not split into multiple PRs. + +N/A + +### If multiple linear tasks are associated with the PR changes, please elaborate on the reason: + +N/A + +
+ +### Developer checklist + +- [ ] **No breaking changes are being introduced.** + +- [ ] Are all related docs linked with the PR? + +- [ ] Are all changes manually tested? + +- [ ] Does this change require any documentation changes? + +- [ ] Are relevant unit and component test-cases added? + +### Reviewer checklist + +- [ ] Is the type of change in the PR title appropriate as per the changes? + +- [ ] Verified that there are no credentials or confidential data exposed with the changes. diff --git a/.github/workflows/build-push-docker-image.yml b/.github/workflows/build-push-docker-image.yml index 80d313486d..fe033b57c6 100644 --- a/.github/workflows/build-push-docker-image.yml +++ b/.github/workflows/build-push-docker-image.yml @@ -151,7 +151,7 @@ jobs: docker buildx imagetools create -t ${{ inputs.push_tags }} ${{ inputs.push_tags }}-amd64 ${{ inputs.push_tags }}-arm64 - name: Create latest multi-arch manifest - # To be triggered only for release/hotfix PR merges coming from `prepare-for-prod-deploy.yaml` + # To be triggered only for release/hotfix PR merges coming from `prepare-for-prod-dt-deploy.yaml` if: ${{ inputs.build_type == 'dt' }} run: | docker buildx imagetools create -t rudderstack/rudder-transformer:latest ${{ inputs.push_tags }}-amd64 ${{ inputs.push_tags }}-arm64 diff --git a/.github/workflows/create-hotfix-branch.yml b/.github/workflows/create-hotfix-branch.yml index d1397cb608..03c79e0df1 100644 --- a/.github/workflows/create-hotfix-branch.yml +++ b/.github/workflows/create-hotfix-branch.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest # Only allow these users to create new hotfix branch from 'main' - if: github.ref == 'refs/heads/main' && (github.actor == 'ItsSudip' || github.actor == 'krishna2020' || github.actor == 'saikumarrs' || github.actor == 'sandeepdsvs' || github.actor == 'shrouti1507' || github.actor == 'anantjain45823' || github.actor == 'chandumlg' || github.actor == 'mihir-4116') && (github.triggering_actor == 'ItsSudip' || github.triggering_actor == 'krishna2020' || github.triggering_actor == 'saikumarrs' || github.triggering_actor == 'sandeepdsvs' || github.triggering_actor == 'shrouti1507' || github.triggering_actor == 'anantjain45823' || github.triggering_actor == 'chandumlg' || github.triggering_actor == 'mihir-4116') + if: github.ref == 'refs/heads/main' && (github.actor == 'ItsSudip' || github.actor == 'krishna2020' || github.actor == 'saikumarrs' || github.actor == 'sandeepdsvs' || github.actor == 'shrouti1507' || github.actor == 'anantjain45823' || github.actor == 'chandumlg' || github.actor == 'mihir-4116' || github.actor == 'ujjwal-ab') && (github.triggering_actor == 'ItsSudip' || github.triggering_actor == 'krishna2020' || github.triggering_actor == 'saikumarrs' || github.triggering_actor == 'sandeepdsvs' || github.triggering_actor == 'shrouti1507' || github.triggering_actor == 'anantjain45823' || github.triggering_actor == 'chandumlg' || github.triggering_actor == 'mihir-4116' || github.triggering_actor == 'ujjwal-ab') steps: - name: Create Branch uses: peterjgrainger/action-create-branch@v2.4.0 diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 0657561f2b..57dd33f0b4 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest # Only allow release stakeholders to initiate releases - if: (github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/hotfix/')) && (github.actor == 'ItsSudip' || github.actor == 'krishna2020' || github.actor == 'saikumarrs' || github.actor == 'sandeepdsvs' || github.actor == 'shrouti1507' || github.actor == 'anantjain45823' || github.actor == 'chandumlg' || github.actor == 'mihir-4116') && (github.triggering_actor == 'ItsSudip' || github.triggering_actor == 'krishna2020' || github.triggering_actor == 'saikumarrs' || github.triggering_actor == 'sandeepdsvs' || github.triggering_actor == 'shrouti1507' || github.triggering_actor == 'anantjain45823' || github.triggering_actor == 'chandumlg' || github.triggering_actor == 'mihir-4116') + if: (github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/hotfix/')) && (github.actor == 'ItsSudip' || github.actor == 'krishna2020' || github.actor == 'saikumarrs' || github.actor == 'sandeepdsvs' || github.actor == 'koladilip' || github.actor == 'shrouti1507' || github.actor == 'anantjain45823' || github.actor == 'chandumlg' || github.actor == 'mihir-4116' || github.actor == 'yashasvibajpai' || github.actor == 'sanpj2292' || github.actor == 'ujjwal-ab') && (github.triggering_actor == 'ItsSudip' || github.triggering_actor == 'krishna2020' || github.triggering_actor == 'koladilip' || github.triggering_actor == 'saikumarrs' || github.triggering_actor == 'sandeepdsvs' || github.triggering_actor == 'shrouti1507' || github.triggering_actor == 'anantjain45823' || github.triggering_actor == 'chandumlg' || github.triggering_actor == 'mihir-4116' || github.triggering_actor == 'yashasvibajpai' || github.triggering_actor == 'sanpj2292' || github.triggering_actor == 'ujjwal-ab') steps: - name: Checkout uses: actions/checkout@v3.5.3 diff --git a/.github/workflows/prepare-for-prod-deploy.yml b/.github/workflows/prepare-for-prod-dt-deploy.yml similarity index 99% rename from .github/workflows/prepare-for-prod-deploy.yml rename to .github/workflows/prepare-for-prod-dt-deploy.yml index 0a2939ac2c..7750761a33 100644 --- a/.github/workflows/prepare-for-prod-deploy.yml +++ b/.github/workflows/prepare-for-prod-dt-deploy.yml @@ -1,4 +1,4 @@ -name: Prepare for Production Environment Deployment +name: Prepare for DT Production Environment Deployment on: push: diff --git a/.github/workflows/prepare-for-prod-ut-deploy.yml b/.github/workflows/prepare-for-prod-ut-deploy.yml index 1cb300512c..2da3c9d067 100644 --- a/.github/workflows/prepare-for-prod-ut-deploy.yml +++ b/.github/workflows/prepare-for-prod-ut-deploy.yml @@ -1,4 +1,4 @@ -name: Prepare for Production Environment Deployment +name: Prepare for UT Production Environment Deployment on: push: diff --git a/CHANGELOG.md b/CHANGELOG.md index c52759ab48..561aaa900f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,139 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.52.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.51.1...v1.52.0) (2023-12-12) + + +### Features + +* onboard msl changes for new record event ([#2644](https://github.com/rudderlabs/rudder-transformer/issues/2644)) ([36d3f25](https://github.com/rudderlabs/rudder-transformer/commit/36d3f258ed5ea4ba1899c8b2cae8203bf73d90ed)), closes [#2813](https://github.com/rudderlabs/rudder-transformer/issues/2813) +* onboard reddit cloud mode destination ([#2829](https://github.com/rudderlabs/rudder-transformer/issues/2829)) ([babb89a](https://github.com/rudderlabs/rudder-transformer/commit/babb89a5bf6d1b84d1319b967953c7c1b6de7c2c)) +* tiktok_ads: add support for custom events ([#2891](https://github.com/rudderlabs/rudder-transformer/issues/2891)) ([091354c](https://github.com/rudderlabs/rudder-transformer/commit/091354c4427b33c9f8ac2678db3a4ab38b008e7d)) + + +### Bug Fixes + +* active_campaign error handler ([#2895](https://github.com/rudderlabs/rudder-transformer/issues/2895)) ([5a6d296](https://github.com/rudderlabs/rudder-transformer/commit/5a6d296b0ce83f3b6b4e215839fb65d4e0f2de41)) +* add check to remove empty properties object from payload ([#2896](https://github.com/rudderlabs/rudder-transformer/issues/2896)) ([1a86a07](https://github.com/rudderlabs/rudder-transformer/commit/1a86a0723e3f5fb6fdf9cf1dc716a47c6da16745)) +* adobe_analytics event field check ([#2890](https://github.com/rudderlabs/rudder-transformer/issues/2890)) ([bf39215](https://github.com/rudderlabs/rudder-transformer/commit/bf39215dd1bbed482665c837a2bfabfcb751c753)) +* covert toString before toLowercase ([#2830](https://github.com/rudderlabs/rudder-transformer/issues/2830)) ([bed431e](https://github.com/rudderlabs/rudder-transformer/commit/bed431e1de94ab28df1ee592d083a1481b960b6d)) +* **dm:** add workspaceId in common metadata to be returned to the callers ([#2868](https://github.com/rudderlabs/rudder-transformer/issues/2868)) ([b3437a3](https://github.com/rudderlabs/rudder-transformer/commit/b3437a34358d5fd5b1eb63f30a5a695f39aa84ff)) +* **integrations:** onboard sprig destination ([#2857](https://github.com/rudderlabs/rudder-transformer/issues/2857)) ([ede22e3](https://github.com/rudderlabs/rudder-transformer/commit/ede22e3f8fb60a9e36e2a3f5a5e86260255c49ef)) +* mailjet source transformation by adding email exists check ([#2889](https://github.com/rudderlabs/rudder-transformer/issues/2889)) ([4a7eaa0](https://github.com/rudderlabs/rudder-transformer/commit/4a7eaa09000bcb82eb7f217d500223939bd9b07b)) +* missing null check in braze populateCustomAttributesWithOperation ([#2897](https://github.com/rudderlabs/rudder-transformer/issues/2897)) ([50e921d](https://github.com/rudderlabs/rudder-transformer/commit/50e921d1451bf7016e60b2e238b8f842d72b5b71)) +* removed retry logic from v1 cm360, added adapter for v1 to v0 conversion ([#2860](https://github.com/rudderlabs/rudder-transformer/issues/2860)) ([776d2c4](https://github.com/rudderlabs/rudder-transformer/commit/776d2c4abe23cd279195064684b9ccc807d83afc)) +* **dm:** use clones as false for tracking plan node cache ([#2899](https://github.com/rudderlabs/rudder-transformer/issues/2899)) ([8f47db8](https://github.com/rudderlabs/rudder-transformer/commit/8f47db8bcf581d1807cfa2aa823ef400a30a09e3)) + +### [1.51.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.51.0...v1.51.1) (2023-12-06) + + +### Bug Fixes + +* marketo backward compatibility ([#2880](https://github.com/rudderlabs/rudder-transformer/issues/2880)) ([af6aebb](https://github.com/rudderlabs/rudder-transformer/commit/af6aebba9a9891fadc91fe2dc4ae4db4b1e269c9)) +* marketo new field introduction backward compatibility ([cd6c3b0](https://github.com/rudderlabs/rudder-transformer/commit/cd6c3b0672a0b17078627f28f6613a2ef1898ee7)) +* remove ErrorResponse type from postTransfomration delivery ([b13f0a6](https://github.com/rudderlabs/rudder-transformer/commit/b13f0a6340177a56417692ad7dcf3829d4990826)) + +## [1.51.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.50.1...v1.51.0) (2023-12-06) + + +### Features + +* cm360 router batching ([#2836](https://github.com/rudderlabs/rudder-transformer/issues/2836)) ([4b260e4](https://github.com/rudderlabs/rudder-transformer/commit/4b260e4ec6d25875903830004b3e4975b3402b2d)) +* cm360 transformerproxy V1 flag ([#2848](https://github.com/rudderlabs/rudder-transformer/issues/2848)) ([27f0797](https://github.com/rudderlabs/rudder-transformer/commit/27f0797c6dcd626a713c11a48c6e85a69e0a4963)) +* **INT-305:** onboard gladly destination ([#2786](https://github.com/rudderlabs/rudder-transformer/issues/2786)) ([ff80b88](https://github.com/rudderlabs/rudder-transformer/commit/ff80b885fe0507c137b3c9eacffcef331010da0c)) +* marketo: migrate config fields and fix test cases ([#2789](https://github.com/rudderlabs/rudder-transformer/issues/2789)) ([7910dba](https://github.com/rudderlabs/rudder-transformer/commit/7910dba2318f92cec3be1b7c7aa6b00428ecae94)) +* mixpanel set once feature onboard ([#2820](https://github.com/rudderlabs/rudder-transformer/issues/2820)) ([9eda50e](https://github.com/rudderlabs/rudder-transformer/commit/9eda50e850c5a1ccb46f1b54c3d176edb915eb27)) +* onboard webhook to component tests ([#2837](https://github.com/rudderlabs/rudder-transformer/issues/2837)) ([284d141](https://github.com/rudderlabs/rudder-transformer/commit/284d1411514c26dda2403a4a18967e5f40e255ea)) +* update facebook destinations API version to v18.0 ([#2828](https://github.com/rudderlabs/rudder-transformer/issues/2828)) ([3127a1c](https://github.com/rudderlabs/rudder-transformer/commit/3127a1ca8dc1b887f9158a1d839c5504f40c4678)) + + +### Bug Fixes + +* add support for custom properties for braze purchase events ([#2856](https://github.com/rudderlabs/rudder-transformer/issues/2856)) ([be6ef26](https://github.com/rudderlabs/rudder-transformer/commit/be6ef2605f04e9182534b9633eeec1091cf7a431)) +* bugsnag issue in moengage identify event ([#2845](https://github.com/rudderlabs/rudder-transformer/issues/2845)) ([0e7adc6](https://github.com/rudderlabs/rudder-transformer/commit/0e7adc66ff88d9510e48a5651460b4e02cc57c78)) +* encode &, < and > to html counterparts in adobe analytics ([#2854](https://github.com/rudderlabs/rudder-transformer/issues/2854)) ([571dbf5](https://github.com/rudderlabs/rudder-transformer/commit/571dbf5bd65e7d0e261562ff3da3b393f27f27b6)) +* error handling in active_campaign ([#2843](https://github.com/rudderlabs/rudder-transformer/issues/2843)) ([a015460](https://github.com/rudderlabs/rudder-transformer/commit/a015460f0a6d2d5320f633abc151febf22561b6b)) +* make supportTransformerProxyV1 false ([#2861](https://github.com/rudderlabs/rudder-transformer/issues/2861)) ([80cf69d](https://github.com/rudderlabs/rudder-transformer/commit/80cf69dc40bb4dc7c0a6d516814f36d962018745)) +* remove errorCategory for braze dedup error ([#2850](https://github.com/rudderlabs/rudder-transformer/issues/2850)) ([91d4cd1](https://github.com/rudderlabs/rudder-transformer/commit/91d4cd16f9839b0be5a663ca5010bdd72cff9bdc)) +* sfmc bug fix for track event validations ([#2852](https://github.com/rudderlabs/rudder-transformer/issues/2852)) ([cd9a046](https://github.com/rudderlabs/rudder-transformer/commit/cd9a046f66eab8363373cb9a0fa1afeef3137d78)) +* unhandled error code in facebook_custom_audience ([#2853](https://github.com/rudderlabs/rudder-transformer/issues/2853)) ([8c02b8c](https://github.com/rudderlabs/rudder-transformer/commit/8c02b8ccb2101147ac84b4555e7fd07235ebf9fc)) +* updated transformerProxyV1 name ([#2859](https://github.com/rudderlabs/rudder-transformer/issues/2859)) ([1a8d825](https://github.com/rudderlabs/rudder-transformer/commit/1a8d825ccbb87d34d8ae5ff2cb02f4be9700eee6)) + +### [1.50.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.50.0...v1.50.1) (2023-12-05) + + +### Bug Fixes + +* salesforce transformer proxy response handling issue for authorization flow ([#2873](https://github.com/rudderlabs/rudder-transformer/issues/2873)) ([4cec65e](https://github.com/rudderlabs/rudder-transformer/commit/4cec65e4103e99021f5108fcc7c557b952f1c5eb)) + +## [1.50.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.49.1...v1.50.0) (2023-11-13) + + +### Features + +* add clickId support for tiktok and pinterest destination ([#2784](https://github.com/rudderlabs/rudder-transformer/issues/2784)) ([0e14296](https://github.com/rudderlabs/rudder-transformer/commit/0e1429663d167a2c5cded0d9130374eb586a18c0)) +* add delivery_category as part of contents, remove flattening custom_data in FB conversions ([#2812](https://github.com/rudderlabs/rudder-transformer/issues/2812)) ([e82cef8](https://github.com/rudderlabs/rudder-transformer/commit/e82cef88e154d47519f0deeb60f55773f25fd3ad)) +* add delivery_category as part of contents, update flattening custom_data in FB Pixel ([#2816](https://github.com/rudderlabs/rudder-transformer/issues/2816)) ([ee1f473](https://github.com/rudderlabs/rudder-transformer/commit/ee1f4733e82291375d85a6de8b8626ffdc8907b1)) +* adding support for future oauth facility in salesforce ([#2746](https://github.com/rudderlabs/rudder-transformer/issues/2746)) ([916ea4c](https://github.com/rudderlabs/rudder-transformer/commit/916ea4c8d08f69b68b7795dd513a25a3cded55fa)) +* introduce v1/source/sourceType endpoint ([#2722](https://github.com/rudderlabs/rudder-transformer/issues/2722)) ([0996e81](https://github.com/rudderlabs/rudder-transformer/commit/0996e816d3671c3e25561f76e3219be99225f24b)) +* move cdkV1 to cdkv2 component tests ([#2804](https://github.com/rudderlabs/rudder-transformer/issues/2804)) ([195b48a](https://github.com/rudderlabs/rudder-transformer/commit/195b48ac0f438a200933e4bbb956fcc3941b7aed)) +* use custom screen name amplitude ([#2823](https://github.com/rudderlabs/rudder-transformer/issues/2823)) ([93a82bd](https://github.com/rudderlabs/rudder-transformer/commit/93a82bd4856b462768d0213ae3de8b9b78e9858c)) + + +### Bug Fixes + +* source_transform_error stat label correction ([#2825](https://github.com/rudderlabs/rudder-transformer/issues/2825)) ([f3bcd7c](https://github.com/rudderlabs/rudder-transformer/commit/f3bcd7c9338ef96267be84f845c63f5234d37e33)) +* shopify redis metric when there is no data returned for a key ([#2811](https://github.com/rudderlabs/rudder-transformer/issues/2811)) ([c02370e](https://github.com/rudderlabs/rudder-transformer/commit/c02370e38fabb581698baa00e1ddd3da93dc07fa)) +* snapchat_conversion category mapping ([#2826](https://github.com/rudderlabs/rudder-transformer/issues/2826)) ([7acd004](https://github.com/rudderlabs/rudder-transformer/commit/7acd004e4290dfb5ea20402929041462eddb4496)) + +### [1.49.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.49.0...v1.49.1) (2023-11-10) + + +### Bug Fixes + +* update create-hotfix-branch.yml ([#2815](https://github.com/rudderlabs/rudder-transformer/issues/2815)) ([dd884dd](https://github.com/rudderlabs/rudder-transformer/commit/dd884ddc78898bd7de155ec4f05ce8fe6e2c4b80)) + +## [1.49.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.48.0...v1.49.0) (2023-11-06) + + +### Features + +* add new destination tiktok_audience ([#2710](https://github.com/rudderlabs/rudder-transformer/issues/2710)) ([9bc0fd8](https://github.com/rudderlabs/rudder-transformer/commit/9bc0fd8efcee44871a190bd6cb9e89c5cf035ff8)) +* onboard one signal to router transform ([#2785](https://github.com/rudderlabs/rudder-transformer/issues/2785)) ([818858e](https://github.com/rudderlabs/rudder-transformer/commit/818858e046ce5f9735bbb97715c43a959ad3aa3c)) +* onboard revenuecat as a source ([#2774](https://github.com/rudderlabs/rudder-transformer/issues/2774)) ([55f9637](https://github.com/rudderlabs/rudder-transformer/commit/55f96374b4d73db7013c1d5e72bfc9c8257b224b)) + + +### Bug Fixes + +* add check to remove null and undefined properties before sending ([#2796](https://github.com/rudderlabs/rudder-transformer/issues/2796)) ([6e89cd3](https://github.com/rudderlabs/rudder-transformer/commit/6e89cd3f67ea887ba17c1cd5ffbca6675f54d96c)) +* allow support for full url from UI in freshsales and freshmarketer ([#2780](https://github.com/rudderlabs/rudder-transformer/issues/2780)) ([570532c](https://github.com/rudderlabs/rudder-transformer/commit/570532ce790c05a69621d9289758a1b1a7acda8c)) +* busgnag issues for klaviyo, freshsales, customeio ([#2795](https://github.com/rudderlabs/rudder-transformer/issues/2795)) ([11fb7c4](https://github.com/rudderlabs/rudder-transformer/commit/11fb7c47910681833e37d25a1573d2005e62742b)) + +## [1.48.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.47.0...v1.48.0) (2023-11-02) + + +### Features + +* add support to add custom network policies for specific workspaces in faas pods ([bc1a760](https://github.com/rudderlabs/rudder-transformer/commit/bc1a76066c0aeb43776ded0b266ec48f5e69aa16)) + +## [1.47.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.46.5...v1.47.0) (2023-10-30) + + +### Features + +* add custom utm parameters to mixpanel ([#2771](https://github.com/rudderlabs/rudder-transformer/issues/2771)) ([9c4fcd3](https://github.com/rudderlabs/rudder-transformer/commit/9c4fcd3595534a8b563df3467e23c94c580f08a6)) +* add support filtering component tests by feature and index ([#2748](https://github.com/rudderlabs/rudder-transformer/issues/2748)) ([146f1c6](https://github.com/rudderlabs/rudder-transformer/commit/146f1c63db4e895c7d5ce2848a1b60e7c5bb9fb6)) +* onboard destination ortto ([#2730](https://github.com/rudderlabs/rudder-transformer/issues/2730)) ([9be5740](https://github.com/rudderlabs/rudder-transformer/commit/9be5740d8670890b0318da3d37f258ddc5e35445)) +* onboard facebook custom audience to transformer proxy ([#2769](https://github.com/rudderlabs/rudder-transformer/issues/2769)) ([14c5e40](https://github.com/rudderlabs/rudder-transformer/commit/14c5e40284af7df9e4f5b262ad226dd3afef226e)) +* add custom event name support in pinterest v5 ([#2773](https://github.com/rudderlabs/rudder-transformer/pull/2773)) ([a586a92](https://github.com/rudderlabs/rudder-transformer/commit/a586a92bf410679d0f3aa7012d4d10f8e2f515d5)) + + +### Bug Fixes + +* bugsnag error for salesforce ([#2753](https://github.com/rudderlabs/rudder-transformer/issues/2753)) ([a2ccdad](https://github.com/rudderlabs/rudder-transformer/commit/a2ccdad52a1fb88f962745800cb45d605b5e0bf3)) +* oom kill while stringifying large response json ([#2754](https://github.com/rudderlabs/rudder-transformer/issues/2754)) ([c8baf5b](https://github.com/rudderlabs/rudder-transformer/commit/c8baf5b2b6325d9e30200339055dcbefd780936c)) +* salesforce: handle ECONNABORTED error ([#2732](https://github.com/rudderlabs/rudder-transformer/issues/2732)) ([6b23a9b](https://github.com/rudderlabs/rudder-transformer/commit/6b23a9b33acd28fdacaa2390c1970a1fa4415ffa)) + ### [1.46.5](https://github.com/rudderlabs/rudder-transformer/compare/v1.46.4...v1.46.5) (2023-10-23) diff --git a/package-lock.json b/package-lock.json index d399b529f8..440bb9ea46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rudder-transformer", - "version": "1.46.5", + "version": "1.52.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rudder-transformer", - "version": "1.46.5", + "version": "1.52.0", "license": "ISC", "dependencies": { "@amplitude/ua-parser-js": "^0.7.24", @@ -19,14 +19,15 @@ "@koa/router": "^12.0.0", "@ndhoule/extend": "^2.0.0", "@pyroscope/nodejs": "^0.2.6", - "@rudderstack/workflow-engine": "^0.5.7", + "@rudderstack/integrations-lib": "^0.1.8", + "@rudderstack/workflow-engine": "^0.6.9", "ajv": "^8.12.0", "ajv-draft-04": "^1.0.0", "ajv-formats": "^2.1.1", - "axios": "^1.4.0", + "axios": "^1.6.0", "btoa": "^1.2.1", "component-each": "^0.2.6", - "crypto-js": "^4.1.1", + "crypto-js": "^4.2.0", "dotenv": "^16.0.3", "flat": "^5.0.2", "form-data": "^4.0.0", @@ -4804,15 +4805,73 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.6", "dev": true, @@ -4851,11 +4910,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.5", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -4896,20 +4956,22 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -4994,8 +5056,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } @@ -5022,11 +5085,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "license": "MIT", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -5035,7 +5099,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" }, @@ -5045,7 +5110,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5057,25 +5123,29 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" }, @@ -5084,9 +5154,10 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.6", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -5258,31 +5329,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.6", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.6", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -5299,12 +5372,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -6637,13 +6711,64 @@ "node": ">= 8" } }, - "node_modules/@rudderstack/json-template-engine": { + "node_modules/@rudderstack/integrations-lib": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@rudderstack/integrations-lib/-/integrations-lib-0.1.9.tgz", + "integrity": "sha512-ROi/LfI7PXqKDrjSig+1Rf2TQ8MgxJGJ7sAD1B0PmRKELQpxK6PLt8QF+vKXl8wYILQu2gwTkZ5o+uwmNKxGzg==", + "dependencies": { + "@rudderstack/workflow-engine": "^0.5.7", + "axios": "^1.4.0", + "axios-mock-adapter": "^1.22.0", + "crypto": "^1.0.1", + "get-value": "^3.0.1", + "handlebars": "^4.7.8", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "set-value": "^4.1.0", + "sha256": "^0.2.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@rudderstack/integrations-lib/node_modules/@aws-crypto/sha256-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-4.0.0.tgz", + "integrity": "sha512-MHGJyjE7TX9aaqXj7zk2ppnFUOhaDs5sP+HtNS0evOxn72c+5njUmyJmpGd7TfyoDznZlHMmdo/xGUdu2NIjNQ==", + "dependencies": { + "@aws-crypto/util": "^4.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@rudderstack/integrations-lib/node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@rudderstack/integrations-lib/node_modules/@aws-crypto/util": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-4.0.0.tgz", + "integrity": "sha512-2EnmPy2gsFZ6m8bwUQN4jq+IyXV3quHAcwPOS6ZA3k+geujiqI8aRokO2kFJe+idJ/P3v4qWI186rVMo0+zLDQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@rudderstack/integrations-lib/node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@rudderstack/integrations-lib/node_modules/@rudderstack/json-template-engine": { "version": "0.5.5", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@rudderstack/json-template-engine/-/json-template-engine-0.5.5.tgz", + "integrity": "sha512-p3HdTqgZiJjjZmjaHN2paa1e87ifGE5UjkA4zdvge4bBzJbKKMQNWqRg6I96SwoA+hsxNkW/f9R83SPLU9t7LA==" }, - "node_modules/@rudderstack/workflow-engine": { - "version": "0.5.7", - "license": "MIT", + "node_modules/@rudderstack/integrations-lib/node_modules/@rudderstack/workflow-engine": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@rudderstack/workflow-engine/-/workflow-engine-0.5.8.tgz", + "integrity": "sha512-H1aCowYqTnOoqJtL9cGDhdhoGNl+KzqmVbSjFmE7n75onZaIMs87+HQyW08jYxS9l1Uo4TL8SAvzFICqFqkBbw==", "dependencies": { "@aws-crypto/sha256-js": "^4.0.0", "@rudderstack/json-template-engine": "^0.5.5", @@ -6653,27 +6778,81 @@ "object-sizeof": "^2.6.3" } }, + "node_modules/@rudderstack/json-template-engine": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@rudderstack/json-template-engine/-/json-template-engine-0.8.1.tgz", + "integrity": "sha512-MR2ArfOXEDh9FEj/N3LVLjIxf134wq+YxUdZN4gTLEONIPdna97QeNk4hnhtlob0QQIrWr13mfPaU9FpvU2Q6Q==" + }, + "node_modules/@rudderstack/workflow-engine": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@rudderstack/workflow-engine/-/workflow-engine-0.6.9.tgz", + "integrity": "sha512-b0ZHURJfCj2REIL/w7AJgJ+K5BGwIVX3sRDZQqN3F4YWcZX3ZYUXo7gtUeb99FLnZzm7KuThIWR02Fxwos+L4Q==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.0.0", + "@rudderstack/json-template-engine": "^0.8.1", + "jsonata": "^2.0.3", + "lodash": "^4.17.21", + "object-sizeof": "^2.6.3", + "yaml": "^2.3.2" + } + }, "node_modules/@rudderstack/workflow-engine/node_modules/@aws-crypto/sha256-js": { - "version": "4.0.0", - "license": "Apache-2.0", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dependencies": { - "@aws-crypto/util": "^4.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, "node_modules/@rudderstack/workflow-engine/node_modules/@aws-crypto/util": { - "version": "4.0.0", - "license": "Apache-2.0", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", "dependencies": { "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@rudderstack/workflow-engine/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" + "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@sideway/address": { "version": "4.1.4", @@ -8171,8 +8350,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.4.0", - "license": "MIT", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -8183,7 +8363,6 @@ "version": "1.22.0", "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.22.0.tgz", "integrity": "sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "is-buffer": "^2.0.5" @@ -8196,7 +8375,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, "funding": [ { "type": "github", @@ -10607,9 +10785,16 @@ "node": "*" } }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." + }, "node_modules/crypto-js": { - "version": "4.1.1", - "license": "MIT" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" }, "node_modules/currently-unhandled": { "version": "0.4.1", @@ -13102,11 +13287,12 @@ "license": "MIT" }, "node_modules/handlebars": { - "version": "4.7.7", - "license": "MIT", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -14790,7 +14976,8 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -16194,9 +16381,16 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.4", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -16958,7 +17152,9 @@ } }, "node_modules/postcss": { - "version": "8.4.21", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -16968,11 +17164,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -19352,8 +19551,9 @@ } }, "node_modules/tslib": { - "version": "2.5.3", - "license": "0BSD" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsscmp": { "version": "1.0.6", @@ -19891,9 +20091,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.1", - "dev": true, - "license": "ISC", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index 8714141981..fe3c9f51b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.46.5", + "version": "1.52.0", "description": "", "homepage": "https://github.com/rudderlabs/rudder-transformer#readme", "bugs": { @@ -23,11 +23,12 @@ "lint:fix": "eslint . --fix", "lint:fix:json": "eslint --ext .json --fix .", "check:merge": "npm run verify || exit 1; codecov", - "start": "node ./dist/src/index.js", + "start": "cd dist;node ./src/index.js;cd ..", "build:start": "npm run build && npm run start", "build:ci": "tsc -p tsconfig.json", "build:swagger": "npm run build && npm run setup:swagger", "build": "npm run build:ci && npm run copy", + "clean:build": "npm run clean && npm run build", "build:clean": "npm run clean && npm run build", "verify": "eslint . || exit 1; npm run test:js || exit 1", "test:testRouter": "jest testRouter --detectOpenHandles --coverage --notify --watchAll=false", @@ -63,14 +64,15 @@ "@koa/router": "^12.0.0", "@ndhoule/extend": "^2.0.0", "@pyroscope/nodejs": "^0.2.6", - "@rudderstack/workflow-engine": "^0.5.7", + "@rudderstack/integrations-lib": "^0.1.8", + "@rudderstack/workflow-engine": "^0.6.9", "ajv": "^8.12.0", "ajv-draft-04": "^1.0.0", "ajv-formats": "^2.1.1", - "axios": "^1.4.0", + "axios": "^1.6.0", "btoa": "^1.2.1", "component-each": "^0.2.6", - "crypto-js": "^4.1.1", + "crypto-js": "^4.2.0", "dotenv": "^16.0.3", "flat": "^5.0.2", "form-data": "^4.0.0", diff --git a/src/adapters/networkHandlerFactory.js b/src/adapters/networkHandlerFactory.js index 7cfa4b048e..e8c3748d15 100644 --- a/src/adapters/networkHandlerFactory.js +++ b/src/adapters/networkHandlerFactory.js @@ -8,6 +8,8 @@ const { getIntegrations } = require('../routes/utils'); const handlers = { generic: GenericNetworkHandler, + v0: {}, + v1: {}, }; // Dynamically import the network handlers for all @@ -16,7 +18,17 @@ SUPPORTED_VERSIONS.forEach((version) => { const destinations = getIntegrations(path.resolve(__dirname, `../${version}/destinations`)); destinations.forEach((dest) => { try { - handlers[dest] = require(`../${version}/destinations/${dest}/networkHandler`).networkHandler; + // handles = { + // v0: { + // dest: handler + // }, + // v1: { + // dest: handler + // }, + // generic: GenericNetworkHandler, + // } + handlers[version][dest] = + require(`../${version}/destinations/${dest}/networkHandler`).networkHandler; } catch { // Do nothing as exception indicates // network handler is not defined for that destination @@ -24,9 +36,15 @@ SUPPORTED_VERSIONS.forEach((version) => { }); }); -const getNetworkHandler = (type) => { - const NetworkHandler = handlers[type] || handlers.generic; - return new NetworkHandler(); +const getNetworkHandler = (type, version) => { + let handlerVersion = version; + let NetworkHandler = handlers[version][type] || handlers.generic; + if (version === 'v1' && NetworkHandler === handlers.generic) { + NetworkHandler = handlers.v0[type] || handlers.generic; + handlerVersion = 'v0'; + } + const networkHandler = new NetworkHandler(); + return { networkHandler, handlerVersion }; }; module.exports = { diff --git a/src/adapters/networkHandlerFactory.test.js b/src/adapters/networkHandlerFactory.test.js new file mode 100644 index 0000000000..ff5f26a02d --- /dev/null +++ b/src/adapters/networkHandlerFactory.test.js @@ -0,0 +1,36 @@ +const { getNetworkHandler } = require('./networkHandlerFactory'); +const { networkHandler: GenericNetworkHandler } = require('./networkhandler/genericNetworkHandler'); + +describe(`Network Handler Tests`, () => { + it('Should return v0 networkhandler', () => { + let { networkHandler, handlerVersion } = getNetworkHandler('campaign_manager', `v0`); + const cmProxy = require(`../v0/destinations/campaign_manager/networkHandler`).networkHandler; + expect(networkHandler).toEqual(new cmProxy()); + }); + + it('Should return v0 networkhandler braze', () => { + let { networkHandler, handlerVersion } = getNetworkHandler('braze', `v0`); + const brazeProxy = require(`../v0/destinations/braze/networkHandler`).networkHandler; + expect(networkHandler).toEqual(new brazeProxy()); + }); + + it('Should return v1 networkhandler', () => { + let { networkHandler, handlerVersion } = getNetworkHandler('campaign_manager', `v1`); + const cmProxy = require(`../v1/destinations/campaign_manager/networkHandler`).networkHandler; + expect(networkHandler).toEqual(new cmProxy()); + }); + + it('Should return v0 handler if v1 version and handler is present for destination in v0', () => { + const { networkHandler, handlerVersion } = getNetworkHandler('braze', `v1`); + const brazeProxy = require(`../v0/destinations/braze/networkHandler`).networkHandler; + console.log(networkHandler); + expect(networkHandler).toEqual(new brazeProxy()); + }); + + it('Should return generic handler', () => { + const { networkHandler, handlerVersion } = getNetworkHandler('abc', `v1`); + const brazeProxy = require(`../v0/destinations/braze/networkHandler`).networkHandler; + console.log(networkHandler); + expect(networkHandler).toEqual(new GenericNetworkHandler()); + }); +}); diff --git a/src/adapters/networkhandler/genericNetworkHandler.js b/src/adapters/networkhandler/genericNetworkHandler.js index 23bdc1d7a2..bcbcb21259 100644 --- a/src/adapters/networkhandler/genericNetworkHandler.js +++ b/src/adapters/networkhandler/genericNetworkHandler.js @@ -1,7 +1,7 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { isHttpStatusSuccess } = require('../../v0/util/index'); const { proxyRequest, prepareProxyRequest } = require('../network'); const { getDynamicErrorType, processAxiosResponse } = require('../utils/networkUtils'); -const { NetworkError } = require('../../v0/util/errorTypes'); const tags = require('../../v0/util/tags'); /** diff --git a/src/adapters/utils/networkUtils.js b/src/adapters/utils/networkUtils.js index 7f830f5a4b..0dcb9931e9 100644 --- a/src/adapters/utils/networkUtils.js +++ b/src/adapters/utils/networkUtils.js @@ -1,6 +1,7 @@ /* eslint-disable eqeqeq */ const lodash = require('lodash'); const { isEmpty } = require('lodash'); +const { AbortedError } = require('@rudderstack/integrations-lib'); const { isHttpStatusRetryable, isDefinedAndNotNullAndNotEmpty, @@ -9,7 +10,6 @@ const { isHttpStatusSuccess, getErrorStatusCode, } = require('../../v0/util'); -const { AbortedError } = require('../../v0/util/errorTypes'); const tags = require('../../v0/util/tags'); const { HTTP_STATUS_CODES } = require('../../v0/util/constant'); diff --git a/src/cdk/v1/autopilot/transform.js b/src/cdk/v1/autopilot/transform.js index 613b985c0d..b27e50f096 100644 --- a/src/cdk/v1/autopilot/transform.js +++ b/src/cdk/v1/autopilot/transform.js @@ -1,5 +1,5 @@ const { Utils } = require('rudder-transformer-cdk'); -const { InstrumentationError } = require('../../../v0/util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); function identifyPostMapper(event, mappedPayload) { const { message } = event; diff --git a/src/cdk/v1/dcm_floodlight/transform.js b/src/cdk/v1/dcm_floodlight/transform.js index d5835d3e2b..bb93333745 100644 --- a/src/cdk/v1/dcm_floodlight/transform.js +++ b/src/cdk/v1/dcm_floodlight/transform.js @@ -5,6 +5,7 @@ const { removeUndefinedAndNullValues, isDefinedAndNotNull, } = require('rudder-transformer-cdk/build/utils'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { getIntegrationsObj, isEmpty, @@ -14,7 +15,6 @@ const { } = require('../../../v0/util'); const { GENERIC_TRUE_VALUES, GENERIC_FALSE_VALUES } = require('../../../constants'); const { BASE_URL, BLACKLISTED_CHARACTERS } = require('./config'); -const { ConfigurationError, InstrumentationError } = require('../../../v0/util/errorTypes'); // append properties to endpoint // eg: ${BASE_URL}key1=value1;key2=value2;.... diff --git a/src/cdk/v1/handler.js b/src/cdk/v1/handler.js index a7dfe85a9f..0af0859f49 100644 --- a/src/cdk/v1/handler.js +++ b/src/cdk/v1/handler.js @@ -6,13 +6,13 @@ const path = require('path'); const basePath = path.resolve(__dirname); ConfigFactory.init({ basePath, loggingMode: 'production' }); -const tags = require('../../v0/util/tags'); -const { generateErrorObject } = require('../../v0/util'); const { + InstrumentationError, TransformationError, ConfigurationError, - InstrumentationError, -} = require('../../v0/util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const tags = require('../../v0/util/tags'); +const { generateErrorObject } = require('../../v0/util'); const defTags = { [tags.TAG_NAMES.IMPLEMENTATION]: tags.IMPLEMENTATIONS.CDK_V1, diff --git a/src/cdk/v2/bindings/default.js b/src/cdk/v2/bindings/default.js index 0bba7210f0..a447370aca 100644 --- a/src/cdk/v2/bindings/default.js +++ b/src/cdk/v2/bindings/default.js @@ -1,8 +1,9 @@ +const crypto = require('crypto'); const { InstrumentationError, ConfigurationError, NetworkError, -} = require('../../../v0/util/errorTypes'); +} = require('@rudderstack/integrations-lib'); const { isHttpStatusSuccess } = require('../../../v0/util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../../v0/util/tags'); @@ -47,7 +48,12 @@ function assertHttpResp(processedResponse, message) { } } +function MD5(data) { + return crypto.createHash('md5').update(data).digest('hex'); +} + module.exports = { + MD5, isValidEventType, assert, assertConfig, diff --git a/src/cdk/v2/destinations/dcm_floodlight/utils.js b/src/cdk/v2/destinations/dcm_floodlight/utils.js index bee45bdea3..07b158efa3 100644 --- a/src/cdk/v2/destinations/dcm_floodlight/utils.js +++ b/src/cdk/v2/destinations/dcm_floodlight/utils.js @@ -1,7 +1,7 @@ const lodash = require('lodash'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getValueFromPropertiesOrTraits, getHashFromArray } = require('../../../../v0/util'); const { GENERIC_TRUE_VALUES, GENERIC_FALSE_VALUES } = require('../../../../constants'); -const { InstrumentationError } = require('../../../../v0/util/errorTypes'); // valid flag should be provided [1|true] or [0|false] const mapFlagValue = (key, value) => { diff --git a/src/cdk/v2/destinations/gladly/procWorkflow.yaml b/src/cdk/v2/destinations/gladly/procWorkflow.yaml new file mode 100644 index 0000000000..fe8697bc31 --- /dev/null +++ b/src/cdk/v2/destinations/gladly/procWorkflow.yaml @@ -0,0 +1,88 @@ +bindings: + - name: EventType + path: ../../../../constants + - path: ./utils + exportAll: true + - name: defaultRequestConfig + path: ../../../../v0/util + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + - name: getDestinationExternalID + path: ../../../../v0/util + - name: httpGET + path: ../../../../adapters/network + - name: processAxiosResponse + path: ../../../../adapters/utils/networkUtils + + +steps: + - name: checkIfProcessed + condition: .message.statusCode + template: | + $.batchMode ? .message.body.JSON : .message + onComplete: return + + - name: messageType + template: | + .message.type.toLowerCase() + + - name: validateInput + template: | + let messageType = $.outputs.messageType + $.assert(messageType, "message Type is not present. Aborting") + $.assert(messageType in {{$.EventType.([.IDENTIFY])}}, "message type " + messageType + " is not supported") + $.assertConfig(.destination.Config.apiToken, "API Token is not present. Aborting") + $.assertConfig(.destination.Config.domain, "Gladly domain is not present. Aborting") + $.assertConfig(.destination.Config.userName, "User Name is not present. Aborting") + + - name: preparePayload + template: | + $.context.payload = { + name: .message.traits.name || .message.context.traits.name, + image: .message.traits.avatar || .message.context.traits.avatar, + address: .message.traits.address || .message.context.traits.address + } + $.context.payload.address && typeof $.context.payload.address === "object" ? $.context.payload.address = JSON.stringify($.context.payload.address) + $.context.payload.emails = $.formatField(.message, "email") + $.context.payload.phones = $.formatField(.message, "phone") + $.context.payload.customAttributes = $.getCustomAttributes(.message) + $.context.payload.externalCustomerId = $.getExternalCustomerId(.message) + $.context.payload.id = $.getCustomerId(.message) + $.context.payload = $.removeUndefinedAndNullValues($.context.payload) + + - name: validatePayload + template: | + $.validatePayload($.context.payload) + + - name: findCustomer + description: Find if customer is exist or not based on email, phone or externalCustomerId + condition: $.getQueryParams($.context.payload) !== undefined + template: | + const requestOptions = { + headers: $.getHeaders(.destination) + } + const endpoint = $.getEndpoint(.destination) + "?" + $.getQueryParams($.context.payload); + const rawResponse = await $.httpGET(endpoint,requestOptions) + const processedResponse = $.processAxiosResponse(rawResponse) + processedResponse + + - name: createCustomer + description: Build response for create customer + condition: $.outputs.findCustomer.status === 400 || ($.outputs.findCustomer.status === 200 && $.outputs.findCustomer.response.length === 0) || $.getQueryParams($.context.payload) === undefined + template: | + const response = $.defaultRequestConfig() + response.body.JSON = $.removeUndefinedAndNullValues($.context.payload) + response.endpoint = $.getEndpoint(.destination) + response.method = "POST" + response.headers = $.getHeaders(.destination) + response + else: + name: updateCustomer + description: Build response for update customer + template: | + const response = $.defaultRequestConfig() + response.body.JSON = $.removeUndefinedAndNullValues($.context.payload.{~["id"]}) + response.endpoint = $.getEndpoint(.destination) + "/" + $.outputs.findCustomer.response[0].id + response.method = "PATCH" + response.headers = $.getHeaders(.destination) + response diff --git a/src/cdk/v2/destinations/gladly/rtWorkflow.yaml b/src/cdk/v2/destinations/gladly/rtWorkflow.yaml new file mode 100644 index 0000000000..341e5552c8 --- /dev/null +++ b/src/cdk/v2/destinations/gladly/rtWorkflow.yaml @@ -0,0 +1,33 @@ +bindings: + - name: handleRtTfSingleEventError + path: ../../../../v0/util/index + - path: ./utils + exportAll: true + +steps: + - name: validateInput + template: | + $.assert(Array.isArray(^) && ^.length > 0, "Invalid event array") + + - name: transform + externalWorkflow: + path: ./procWorkflow.yaml + loopOverInput: true + + - name: successfulEvents + template: | + $.outputs.transform#idx.output.({ + "batchedRequest": ., + "batched": false, + "destination": ^[idx].destination, + "metadata": ^[idx].metadata[], + "statusCode": 200 + })[] + - name: failedEvents + template: | + $.outputs.transform#idx.error.( + $.handleRtTfSingleEventError(^[idx], .originalError ?? ., {}) + )[] + - name: finalPayload + template: | + [...$.outputs.successfulEvents, ...$.outputs.failedEvents] \ No newline at end of file diff --git a/src/cdk/v2/destinations/gladly/utils.js b/src/cdk/v2/destinations/gladly/utils.js new file mode 100644 index 0000000000..0489f410ec --- /dev/null +++ b/src/cdk/v2/destinations/gladly/utils.js @@ -0,0 +1,174 @@ +const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); +const { base64Convertor, getDestinationExternalID } = require('../../../../v0/util'); +const { MappedToDestinationKey } = require('../../../../constants'); + +const reservedCustomAttributes = [ + 'email', + 'phone', + 'address', + 'name', + 'avatar', + 'firstName', + 'lastName', + 'userId', +]; + +const externalIdKey = 'context.externalId.0.id'; +const identifierTypeKey = 'context.externalId.0.identifierType'; + +const getHeaders = (destination) => { + const { apiToken, userName } = destination.Config; + const credentials = `${userName}:${apiToken}`; + const base64Credentials = base64Convertor(credentials); + return { + 'Content-Type': 'application/json', + Authorization: `Basic ${base64Credentials}`, + }; +}; + +const getEndpoint = (destination) => { + const { domain } = destination.Config; + return `https://${domain}/api/v1/customer-profiles`; +}; + +const getFieldValue = (field) => { + if (field) { + if (Array.isArray(field)) { + return field.map((item) => ({ original: item })); + } + return [{ original: field }]; + } + return undefined; +}; + +const formatFieldForRETl = (message, fieldName) => { + const identifierType = get(message, identifierTypeKey); + if (identifierType && identifierType === fieldName) { + const field = get(message, externalIdKey); + if (field) { + return [{ original: field }]; + } + } + const key = fieldName === 'email' ? 'emails' : 'phones'; + const field = get(message, `traits.${key}`); + return getFieldValue(field); +}; + +const formatFieldForEventStream = (message, fieldName) => { + const field = get(message, `context.traits.${fieldName}`); + return getFieldValue(field); +}; + +const formatField = (message, fieldName) => { + const mappedToDestination = get(message, MappedToDestinationKey); + if (mappedToDestination) { + return formatFieldForRETl(message, fieldName); + } + return formatFieldForEventStream(message, fieldName); +}; + +const getCustomAttributes = (message) => { + const mappedToDestination = get(message, MappedToDestinationKey); + // for rETL + if (mappedToDestination) { + if (message?.traits?.customAttributes && typeof message.traits.customAttributes === 'object') { + return Object.keys(message.traits.customAttributes).length > 0 + ? message.traits.customAttributes + : undefined; + } + return undefined; + } + + // for event stream + const customAttributes = message.context?.traits || {}; + reservedCustomAttributes.forEach((customAttribute) => { + if (customAttributes[customAttribute]) { + delete customAttributes[customAttribute]; + } + }); + return Object.keys(customAttributes).length > 0 ? customAttributes : undefined; +}; + +const getExternalCustomerId = (message) => { + const mappedToDestination = get(message, MappedToDestinationKey); + // for rETL + if (mappedToDestination) { + const identifierType = get(message, identifierTypeKey); + if (identifierType === 'externalCustomerId') { + return get(message, externalIdKey); + } + + if (message?.traits?.externalCustomerId) { + return message.traits.externalCustomerId; + } + + return undefined; + } + + // for event stream + return message.userId; +}; + +const getCustomerId = (message) => { + const mappedToDestination = get(message, MappedToDestinationKey); + // for rETL + if (mappedToDestination) { + const identifierType = get(message, identifierTypeKey); + if (identifierType === 'id') { + return get(message, externalIdKey); + } + + if (message?.traits?.id) { + return message.traits.id; + } + + return undefined; + } + + // for event stream + const customerId = getDestinationExternalID(message, 'GladlyCustomerId'); + if (customerId) { + return customerId; + } + + return undefined; +}; + +const validatePayload = (payload) => { + if (!(payload?.phones || payload?.emails || payload?.id || payload?.externalCustomerId)) { + throw new InstrumentationError( + 'One of phone, email, userId or GladlyCustomerId is required for an identify call', + ); + } +}; + +const getQueryParams = (payload) => { + if (payload.emails && payload.emails.length > 0) { + return `email=${encodeURIComponent(payload.emails[0].original)}`; + } + + if (payload.phones && payload.phones.length > 0) { + return `phoneNumber=${encodeURIComponent(payload.phones[0].original)}`; + } + + if (payload.externalCustomerId) { + return `externalCustomerId=${encodeURIComponent(payload.externalCustomerId)}`; + } + + return undefined; +}; + +module.exports = { + getHeaders, + getEndpoint, + formatField, + getFieldValue, + getCustomerId, + getQueryParams, + validatePayload, + formatFieldForRETl, + getCustomAttributes, + getExternalCustomerId, + formatFieldForEventStream, +}; diff --git a/src/cdk/v2/destinations/gladly/utils.test.js b/src/cdk/v2/destinations/gladly/utils.test.js new file mode 100644 index 0000000000..116f150448 --- /dev/null +++ b/src/cdk/v2/destinations/gladly/utils.test.js @@ -0,0 +1,503 @@ +const { + getHeaders, + getEndpoint, + formatField, + getCustomerId, + getFieldValue, + getQueryParams, + validatePayload, + formatFieldForRETl, + getCustomAttributes, + getExternalCustomerId, + formatFieldForEventStream, +} = require('./utils'); +const { base64Convertor } = require('../../../../v0/util'); + +describe('Unit test cases for getHeaders function', () => { + it('Should return headers', () => { + const destination = { + Config: { + apiToken: 'token', + userName: 'user', + }, + }; + const expectedHeaders = { + 'Content-Type': 'application/json', + Authorization: `Basic ${base64Convertor('user:token')}`, + }; + + const result = getHeaders(destination); + + expect(result).toEqual(expectedHeaders); + }); +}); + +describe('Unit test cases for getEndpoint function', () => { + it('Should return destination endpoint', () => { + const destination = { + Config: { + domain: 'rudderstack.us-uat.gladly.qa', + }, + }; + const expected = 'https://rudderstack.us-uat.gladly.qa/api/v1/customer-profiles'; + const result = getEndpoint(destination); + expect(result).toBe(expected); + }); +}); + +describe('Unit test cases for getFieldValue function', () => { + it('Should return an array with a single object containing the original value when the input field is a string', () => { + const field = 'rudderlabs1@gmail.com'; + const result = getFieldValue(field); + expect(result).toEqual([{ original: field }]); + }); + + it('should return an array with each element containing the original value when the input field is an array', () => { + const field = ['rudderlabs1@gmail.com', 'rudderlabs2@gmail.com', 'rudderlabs3@gmail.com']; + const result = getFieldValue(field); + expect(result).toEqual([ + { + original: 'rudderlabs1@gmail.com', + }, + { + original: 'rudderlabs2@gmail.com', + }, + { + original: 'rudderlabs3@gmail.com', + }, + ]); + }); + + it('Should return undefined when the input field is null', () => { + const field = null; + const result = getFieldValue(field); + expect(result).toBeUndefined(); + }); + + it('Should return undefined when the input field is undefined', () => { + const field = undefined; + const result = getFieldValue(field); + expect(result).toBeUndefined(); + }); +}); + +describe('Unit test cases for formatFieldForRETl function', () => { + it('should return the object containing the original value when identifierType matches fieldName', () => { + const message = { + context: { + externalId: [ + { + id: 'test@rudderlabs.com', + identifierType: 'email', + }, + ], + }, + traits: { + emails: ['test@rudderlabs.com', 'test@rudderlabshome.com'], + }, + }; + const fieldName = 'email'; + const expected = [{ original: 'test@rudderlabs.com' }]; + + const result = formatFieldForRETl(message, fieldName); + + expect(result).toEqual(expected); + }); + + it('Should retrieve the email value from traits when fieldName does not match with identifierType', () => { + const message = { + context: { + externalId: [ + { + id: '+91 9999999999', + identifierType: 'phone', + }, + ], + }, + traits: { + emails: ['test@rudderlabs.com', 'test@rudderlabshome.com'], + }, + }; + const fieldName = 'email'; + const expected = [{ original: 'test@rudderlabs.com' }, { original: 'test@rudderlabshome.com' }]; + + const result = formatFieldForRETl(message, fieldName); + + expect(result).toEqual(expected); + }); +}); + +describe('Unit test cases for formatFieldForEventStream function', () => { + it('Should return field value when fieldName exist in payload', () => { + const message = { + context: { + traits: { + phone: '+91 9999999999', + }, + }, + }; + const fieldName = 'phone'; + const expected = [{ original: '+91 9999999999' }]; + + const result = formatFieldForEventStream(message, fieldName); + expect(result).toEqual(expected); + }); + + it('Should return undefined when fieldName does not exist in payload', () => { + const message = { + context: { + traits: { + phone: '+91 9999999999', + }, + }, + }; + const fieldName = 'email'; + const result = formatFieldForEventStream(message, fieldName); + expect(result).toBeUndefined(); + }); +}); + +describe('Unit test cases for formatField function', () => { + describe('rETL tests', () => { + it('Should return field value from externalId when identifier type matches with fieldName', () => { + const message = { + context: { + externalId: [ + { + id: '+91 9999999999', + identifierType: 'phone', + }, + ], + mappedToDestination: true, + }, + traits: { + emails: ['test@rudderlabs.com', 'test@rudderlabshome.com'], + }, + }; + const result = formatField(message, 'phone'); + expect(result).toEqual([{ original: '+91 9999999999' }]); + }); + + it('Should return field value from traits when identifier type does not match with fieldName', () => { + const message = { + context: { + externalId: [ + { + id: 'user@1', + identifierType: 'externalCustomerId', + }, + ], + mappedToDestination: true, + }, + traits: { + phones: ['+91 9999999999'], + }, + }; + const result = formatField(message, 'phone'); + expect(result).toEqual([{ original: '+91 9999999999' }]); + }); + }); + + describe('Event stream tests', () => { + it('Should return field value from payload', () => { + const message = { + context: { + traits: { + phone: ['+91 9999999999'], + }, + }, + }; + const result = formatField(message, 'phone'); + expect(result).toEqual([{ original: '+91 9999999999' }]); + }); + }); +}); + +describe('Unit test cases for getCustomAttributes function', () => { + describe('rETL tests', () => { + it('Should return custom attributes from payload', () => { + const message = { + context: { + mappedToDestination: true, + }, + traits: { + customAttributes: { + attribute1: 'value1', + attribute2: 'value2', + }, + }, + }; + const result = getCustomAttributes(message); + expect(result).toEqual({ + attribute1: 'value1', + attribute2: 'value2', + }); + }); + + it('Should return undefined when empty custom attributes object is present in payload', () => { + const message = { + context: { + mappedToDestination: true, + }, + traits: { + customAttributes: {}, + }, + }; + const result = getCustomAttributes(message); + expect(result).toBeUndefined(); + }); + + it('Should return undefined when no custom attributes are present in payload', () => { + const message = { + context: { + mappedToDestination: true, + }, + traits: {}, + }; + const result = getCustomAttributes(message); + expect(result).toBeUndefined(); + }); + }); + + describe('Event stream tests', () => { + it('Should filter traits and return remaining custom attributes from payload', () => { + const message = { + context: { + traits: { + name: 'John Doe', + email: 'john@gmail.com', + age: 65, + source: 'rudderstack', + }, + }, + }; + const result = getCustomAttributes(message); + expect(result).toEqual({ + age: 65, + source: 'rudderstack', + }); + }); + + it('Should return undefined when empty traits object is present in payload', () => { + const message = { + context: { + traits: {}, + }, + }; + const result = getCustomAttributes(message); + expect(result).toBeUndefined(); + }); + + it('Should return undefined when no traits object is present in payload', () => { + const message = { + context: {}, + }; + const result = getCustomAttributes(message); + expect(result).toBeUndefined(); + }); + }); +}); + +describe('Unit test cases for getExternalCustomerId function', () => { + describe('rETL tests', () => { + it('Should return the external ID when the identifier type is "externalCustomerId"', () => { + const message = { + context: { + externalId: [ + { + id: 'externalCustomer@1', + identifierType: 'externalCustomerId', + }, + ], + mappedToDestination: true, + }, + }; + + const result = getExternalCustomerId(message); + expect(result).toBe('externalCustomer@1'); + }); + + it('Should return the external ID from traits when identifier type is not "externalCustomerId"', () => { + const message = { + context: { + externalId: [ + { + id: 'test@rudderlabs.com', + identifierType: 'email', + }, + ], + mappedToDestination: true, + }, + traits: { + externalCustomerId: 'externalCustomer@1', + }, + }; + const result = getExternalCustomerId(message); + expect(result).toBe('externalCustomer@1'); + }); + + it('Should return undefined when external customer id is not present in payload', () => { + const message = { + context: { + mappedToDestination: true, + }, + }; + + const result = getExternalCustomerId(message); + expect(result).toBeUndefined(); + }); + }); + + describe('Event stream tests', () => { + it('Should return the external ID as userId is present in payload', () => { + const message = { + userId: 'externalCustomer@1', + context: {}, + }; + + const result = getExternalCustomerId(message); + expect(result).toBe('externalCustomer@1'); + }); + + it('Should return undefined when userId is not present in payload', () => { + const message = { + context: {}, + }; + + const result = getExternalCustomerId(message); + expect(result).toBeUndefined(); + }); + }); +}); + +describe('Unit test cases for getCustomerId function', () => { + describe('rETL tests', () => { + it('Should return the customerId when the identifier type is "id"', () => { + const message = { + context: { + externalId: [ + { + id: 'user@1', + identifierType: 'id', + }, + ], + mappedToDestination: true, + }, + }; + + const result = getCustomerId(message); + expect(result).toBe('user@1'); + }); + + it('Should return the customerId from traits when identifier type is not "id"', () => { + const message = { + context: { + externalId: [ + { + id: 'test@rudderlabs.com', + identifierType: 'email', + }, + ], + mappedToDestination: true, + }, + traits: { + id: 'user@1', + }, + }; + const result = getCustomerId(message); + expect(result).toBe('user@1'); + }); + + it('Should return undefined when customerId is not present in payload', () => { + const message = { + context: { + mappedToDestination: true, + }, + }; + + const result = getCustomerId(message); + expect(result).toBeUndefined(); + }); + }); + + describe('Event stream tests', () => { + it('Should return the customerId as GladlyCustomerId is present in payload', () => { + const message = { + context: { + externalId: [ + { + id: 'user@1', + type: 'GladlyCustomerId', + }, + ], + }, + }; + const result = getCustomerId(message); + expect(result).toBe('user@1'); + }); + + it('Should return undefined when GladlyCustomerId is not present in payload', () => { + const message = { + context: {}, + }; + const result = getCustomerId(message); + expect(result).toBeUndefined(); + }); + }); +}); + +describe('Unit test cases for validatePayload function', () => { + it('Should throw an error when payload does not have all required fields', () => { + const payload = {}; + try { + validatePayload(payload); + } catch (err) { + expect(err.message).toEqual( + 'One of phone, email, userId or GladlyCustomerId is required for an identify call', + ); + } + }); + + it('Should throw an error when payload is undefined', () => { + const payload = undefined; + try { + validatePayload(payload); + } catch (err) { + expect(err.message).toEqual( + 'One of phone, email, userId or GladlyCustomerId is required for an identify call', + ); + } + }); +}); + +describe('Unit test cases for getQueryParams function', () => { + it('Should return email as query parameter if email is present in payload', () => { + const payload = { + emails: [{ original: 'test@example.com' }], + }; + const result = getQueryParams(payload); + expect(result).toBe('email=test%40example.com'); + }); + + it('Should return phone as query parameter if phone is present in payload', () => { + const payload = { + phones: [{ original: '+91 9999999999' }], + }; + const result = getQueryParams(payload); + expect(result).toBe('phoneNumber=%2B91%209999999999'); + }); + + it('Should return externalCustomerId as query parameter if externalCustomerId is present in payload', () => { + const payload = { + externalCustomerId: 'externalCustomer@1', + }; + const result = getQueryParams(payload); + expect(result).toBe('externalCustomerId=externalCustomer%401'); + }); + + it('should return undefined when no supported query params are present in payload', () => { + const payload = {}; + const result = getQueryParams(payload); + expect(result).toBeUndefined(); + }); +}); diff --git a/src/cdk/v2/destinations/pinterest_tag/procWorkflow.yaml b/src/cdk/v2/destinations/pinterest_tag/procWorkflow.yaml index 6854573cfa..7bcb804126 100644 --- a/src/cdk/v2/destinations/pinterest_tag/procWorkflow.yaml +++ b/src/cdk/v2/destinations/pinterest_tag/procWorkflow.yaml @@ -100,7 +100,8 @@ steps: "hashed_maids": .context.device.advertisingId, "client_ip_address": .context.ip ?? .request_ip, "client_user_agent": .context.userAgent, - "external_id": {{{{$.getGenericPaths("userId")}}}} + "external_id": {{{{$.getGenericPaths("userId")}}}}, + "click_id": .properties.clickId }); !.destination.Config.sendExternalId ? userFields = userFields{~["external_id"]} : null; userFields = $.removeUndefinedAndNullAndEmptyValues(userFields); @@ -179,22 +180,19 @@ steps: eventNames = $.convertToSnakeCase(eventNames); eventNames.length === 0 ? eventNames = $.ecomEventMaps.(){eventInLowerCase in .src}.dest[] ?? []; (eventNames.length === 0 && .destination.Config.sendAsCustomEvent) ? eventNames = ["custom"]; - (eventNames.length === 0 && $.outputs.apiVersion === {{$.API_VERSION.v3}}) ? eventNames = [event]; - $.assertConfig(eventNames.length > 0, - event + " is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting") - eventNames + eventNames.length === 0 ? eventNames = [event]; + eventNames; - name: payload template: | $.outputs.eventNames.().({...$.outputs.basePayload, event_name: .})[] - + - name: checkSendTestEventConfig description: | If sendTestEvent is enabled, we send test event to the destination ref: https://help.pinterest.com/en/business/article/track-conversions-with-the-conversions-api template: | - ^.destination.Config.sendAsTestEvent ? {"test": true} : {} - + ^.destination.Config.sendAsTestEvent ? {"test": true} : {} - name: buildResponseForBatchMode description: In batchMode we return payload directly diff --git a/src/cdk/v2/destinations/reddit/config.js b/src/cdk/v2/destinations/reddit/config.js new file mode 100644 index 0000000000..5c2c778ea5 --- /dev/null +++ b/src/cdk/v2/destinations/reddit/config.js @@ -0,0 +1,31 @@ +const ENDPOINT = 'https://ads-api.reddit.com/api/v2.0/conversions/events/'; +const maxBatchSize = 1000; + +const ecomEventMaps = [ + { + src: ['product viewed', 'product list viewed'], + dest: 'ViewContent', + }, + { + src: ['product added'], + dest: 'AddToCart', + }, + { + src: ['product added to wishlist'], + dest: 'AddToWishlist', + }, + { + src: ['order completed'], + dest: 'Purchase', + }, + { + src: ['products searched'], + dest: 'Search', + }, +]; + +module.exports = { + ENDPOINT, + maxBatchSize, + ecomEventMaps, +}; diff --git a/src/cdk/v2/destinations/reddit/procWorkflow.yaml b/src/cdk/v2/destinations/reddit/procWorkflow.yaml new file mode 100644 index 0000000000..65b466bc7c --- /dev/null +++ b/src/cdk/v2/destinations/reddit/procWorkflow.yaml @@ -0,0 +1,135 @@ +bindings: + - name: EventType + path: ../../../../constants + - path: ../../bindings/jsontemplate + exportAll: true + - path: ./config + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + - name: defaultRequestConfig + path: ../../../../v0/util + - name: isAppleFamily + path: ../../../../v0/util/index + - name: OAuthSecretError + path: '@rudderstack/integrations-lib' + +steps: + - name: validateInput + template: | + let messageType = .message.type; + $.assertConfig(.destination.Config.accountId, "Account is not present. Aborting message."); + $.assert(.message.type, "message Type is not present. Aborting message."); + $.assert(.message.type.toLowerCase() ==='track', "Event type " + .message.type.toLowerCase() + " is not supported. Aborting message."); + $.assert(.message.event, "Event is not present. Aborting message."); + $.assert(.message.().({{{{$.getGenericPaths("timestamp")}}}}), "Timestamp is not present. Aborting message."); + + - name: messageType + template: | + .message.type.toLowerCase() + + - name: prepareTrackPayload + condition: $.outputs.messageType === {{$.EventType.TRACK}} + steps: + - name: prepareUserObject + template: | + const os = (.message.context.os.name)? .message.context.os.name.toLowerCase(): null; + const hashData = .destination.Config.hashData; + let user = .message.().({ + "email": hashData ? $.SHA256({{{{$.getGenericPaths("email")}}}}) : ({{{{$.getGenericPaths("email")}}}}), + "external_id": hashData ? $.SHA256({{{{$.getGenericPaths("userId")}}}}) : ({{{{$.getGenericPaths("userId")}}}}), + "ip_address": hashData? $.SHA256(.context.ip || .request_ip) : (.context.ip || .request_ip), + "uuid": .properties.uuid, + "user_agent": .context.userAgent, + "idfa": $.isAppleFamily(os)? (hashData? $.SHA256(.context.device.advertisingId): .context.device.advertisingId): null, + "aaid": os === "android" && .context.device ? (hashData? $.SHA256(.context.device.advertisingId): .context.device.advertisingId): null, + "opt_out": .properties.optOut, + "screen_dimensions": {"width": .context.screen.width, "height": .context.screen.height}, + }); + $.removeUndefinedAndNullValues(user) + + - name: eventType + template: | + let event = .message.event; + let eventInLowerCase = event.trim().toLowerCase();; + let eventNames = .destination.Config.eventsMapping? .destination.Config.eventsMapping.(){.from === event}.to[] ?? []: []; + eventNames.length === 0 ? eventNames = $.ecomEventMaps.(){eventInLowerCase in .src}.dest[] ?? []; + const event_type = (eventNames.length === 0 || eventNames[0]==="") ? ({"tracking_type": "Custom", "custom_event_name": event}): ({tracking_type: eventNames[0]}); + + - name: customFields + condition: $.outputs.eventType.tracking_type === "Purchase" + template: | + const customFields = .message.().({ + "currency": .properties.currency, + "value": .properties.revenue !== undefined ? Number(.properties.revenue) : undefined, + "item_count": (Array.isArray(.properties.products) && .properties.products.length) || (.properties.itemCount && Number(.properties.itemCount)), + "value_decimal": .properties.revenue !== undefined ? Number(.properties.revenue)/100 : undefined, + "conversion_id": .properties.conversionId || .messageId, + }); + $.removeUndefinedAndNullValues(customFields) + else: + name: nonRevenueTypeEvents + template: | + const customFields = .message.().({ + "conversion_id": .properties.conversionId || .messageId, + }); + $.removeUndefinedAndNullValues(customFields) + + - name: productFields + condition: .message.properties.products + description: When event contains multiple products + template: | + let products = .message.properties.products; + { + "item_count": $.sum(products.quantity.(Number(.))[]) || 0, + "products": .message.properties@prop.products.({ + "id": .product_id ?? prop.product_id, + "name": .name ?? prop.name, + "category": .category ?? prop.category, + })[] + } + else: + name: singleProductFields + template: | + const props = .message.properties; + const output = { + "item_count": Number(props.quantity) || 0, + "products": { + "id": props.product_id, + "name": props.name, + "category": props.category, + }[] + }; + - name: combineAllEcomFields + template: | + {...$.outputs.prepareTrackPayload.productFields, ...$.outputs.prepareTrackPayload.customFields} + + - name: prepareFinalPayload + template: | + { + events: [{ + "click_id": .message.properties.clickId, + "event_at": .message.().({{{{$.getGenericPaths("timestamp")}}}}), + "event_type": $.outputs.prepareTrackPayload.eventType, + "user": $.outputs.prepareTrackPayload.prepareUserObject, + "event_metadata": $.outputs.prepareTrackPayload.combineAllEcomFields, + }] + } + + - name: payload + condition: $.outputs.messageType === {{$.EventType.TRACK}} + template: | + const outputPayload = $.outputs.prepareTrackPayload + + - name: buildResponseForProcessTransformation + description: build response + template: | + $.assertThrow((.metadata.secret && .metadata.secret.accessToken), new $.OAuthSecretError("Secret or accessToken is not present in the metadata")) + const accessToken = .metadata.secret.accessToken + const response = $.defaultRequestConfig(); + response.body.JSON = $.outputs.payload; + response.headers = { + "Authorization": "Bearer "+ accessToken, + "Content-Type": "application/json" + } + response.endpoint = $.ENDPOINT+.destination.Config.accountId; + finalResponse = response; diff --git a/src/cdk/v2/destinations/reddit/rtWorkflow.yaml b/src/cdk/v2/destinations/reddit/rtWorkflow.yaml new file mode 100644 index 0000000000..937ff021f4 --- /dev/null +++ b/src/cdk/v2/destinations/reddit/rtWorkflow.yaml @@ -0,0 +1,67 @@ +bindings: + - path: ./utils + - path: ./config + +steps: + - name: validateInput + template: | + $.assert(Array.isArray(^) && ^.length > 0, "Invalid event array") + + - name: transform + externalWorkflow: + path: ./procWorkflow.yaml + bindings: + - name: batchMode + value: true + loopOverInput: true + - name: successfulEvents + template: | + $.outputs.transform#idx.output.({ + "message": .[], + "destination": ^ [idx].destination, + "metadata": ^ [idx].metadata + })[] + - name: failedEvents + template: | + $.outputs.transform#idx.error.({ + "metadata": ^[idx].metadata[], + "destination": ^[idx].destination, + "batched": false, + "statusCode": .status, + "error": .message, + "statTags": .originalError.statTags + })[] + + - name: batchSuccessfulEvents + description: Batches the successfulEvents using endpoint + condition: $.outputs.successfulEvents.length + template: | + let batches = $.batchEvents($.outputs.successfulEvents); + batches@batch.({ + "batchedRequest": { + "body": { + "JSON": batch.message.body.JSON, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": batch.message.endpoint, + "headers": batch.message.headers, + "params": {}, + "files": {} + }, + "metadata": batch.metadata, + "batched": true, + "statusCode": 200, + "destination": batch.destination + })[]; + else: + name: returnEmptyOuput + template: '[]' + + - name: finalPayload + template: | + [...$.outputs.batchSuccessfulEvents, ...$.outputs.failedEvents] diff --git a/src/cdk/v2/destinations/reddit/utils.js b/src/cdk/v2/destinations/reddit/utils.js new file mode 100644 index 0000000000..c108603235 --- /dev/null +++ b/src/cdk/v2/destinations/reddit/utils.js @@ -0,0 +1,33 @@ +const lodash = require('lodash'); +const { maxBatchSize } = require('./config'); + +const batchEventChunks = (eventChunks) => { + const batchedEvents = []; + if (Array.isArray(eventChunks)) { + eventChunks.forEach((chunk) => { + const response = { destination: chunk[0].destination }; + chunk.forEach((event, index) => { + if (index === 0) { + const [firstMessage] = event.message; + response.message = firstMessage; + response.destination = event.destination; + response.metadata = [event.metadata]; + } else { + response.message.body.JSON.events.push(...event.message[0].body.JSON.events); + response.metadata.push(event.metadata); + } + }); + batchedEvents.push(response); + }); + } + return batchedEvents; +}; + +const batchEvents = (successfulEvents) => { + const eventChunks = lodash.chunk(successfulEvents, maxBatchSize); + const batchedEvents = batchEventChunks(eventChunks); + return batchedEvents; +}; +module.exports = { + batchEvents, +}; diff --git a/src/cdk/v2/destinations/sprig/procWorkflow.yaml b/src/cdk/v2/destinations/sprig/procWorkflow.yaml new file mode 100644 index 0000000000..18b46913fd --- /dev/null +++ b/src/cdk/v2/destinations/sprig/procWorkflow.yaml @@ -0,0 +1,73 @@ +bindings: + - name: EventType + path: ../../../../constants + - path: ../../bindings/jsontemplate + - name: defaultRequestConfig + path: ../../../../v0/util + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + +steps: + - name: messageType + template: | + .message.type.toLowerCase(); + + - name: validateInput + template: | + let messageType = $.outputs.messageType; + $.assert(messageType, "message Type is not present. Aborting"); + $.assert(messageType in {{$.EventType.([.IDENTIFY, .TRACK])}}, "message type " + messageType + " is not supported"); + $.assertConfig(.destination.Config.apiKey, "API Key is not present. Aborting"); + + - name: validateIdentifyPayload + condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} + template: | + const userId = .message.({{{{$.getGenericPaths("userIdOnly")}}}});; + $.assert(userId, "userId is required"); + + - name: prepareIdentifyPayload + condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} + template: | + $.context.payload = .message.({ + userId: {{{{$.getGenericPaths("userIdOnly")}}}}, + emailAddress: {{{{$.getGenericPaths("email")}}}}, + attributes: .context.traits + }); + $.context.payload = $.removeUndefinedAndNullValues($.context.payload); + + - name: validateTrackPayload + condition: $.outputs.messageType === {{$.EventType.TRACK}} + template: | + const userId = .message.({{{{$.getGenericPaths("userIdOnly")}}}});; + $.assert(userId, "userId is required"); + $.assert(.message.event, "event name is required"); + + - name: prepareTrackPayload + condition: $.outputs.messageType === {{$.EventType.TRACK}} + template: | + $.context.payload = .message.({ + userId: {{{{$.getGenericPaths("userIdOnly")}}}}, + emailAddress: {{{{$.getGenericPaths("email")}}}} + }); + const events = [ + { + event: .message.event, + timestamp: $.toMilliseconds(.message.().({{{{$.getGenericPaths("timestamp")}}}})) + } + ] + $.context.payload.events = events; + $.context.payload = $.removeUndefinedAndNullValues($.context.payload); + + - name: buildResponse + template: | + const response = $.defaultRequestConfig(); + response.body.JSON = $.context.payload; + response.endpoint = "https://api.sprig.com/v2/users"; + response.headers = { + "accept": "application/json", + "content-type": "application/json", + "authorization": "API-Key " + .destination.Config.apiKey + }; + response + + diff --git a/src/cdk/v2/destinations/tiktok_audience/config.js b/src/cdk/v2/destinations/tiktok_audience/config.js new file mode 100644 index 0000000000..853f372505 --- /dev/null +++ b/src/cdk/v2/destinations/tiktok_audience/config.js @@ -0,0 +1,9 @@ +const ACTION_MAP = { + add: 'add', + remove: 'delete', +}; +const SHA256_TRAITS = ['IDFA_SHA256', 'AAID_SHA256', 'EMAIL_SHA256', 'PHONE_SHA256']; +module.exports = { + ACTION_MAP, + SHA256_TRAITS, +}; diff --git a/src/cdk/v2/destinations/tiktok_audience/procWorkflow.yaml b/src/cdk/v2/destinations/tiktok_audience/procWorkflow.yaml new file mode 100644 index 0000000000..cd84ecbc87 --- /dev/null +++ b/src/cdk/v2/destinations/tiktok_audience/procWorkflow.yaml @@ -0,0 +1,67 @@ + +bindings: + - name: EventType + path: ../../../../constants + - path: ../../bindings/jsontemplate + exportAll: true + - path: ./config + - name: removeUndefinedAndNullValues + path: ../../../../v0/util + - name: defaultRequestConfig + path: ../../../../v0/util + +steps: + - name: validateInput + template: | + let messageType = .message.type; + $.assert(.message.type, "message Type is not present. Aborting message."); + $.assert(.message.type.toLowerCase() ==='audiencelist', "Event type " + .message.type.toLowerCase() + " is not supported. Aborting message."); + $.assert(.message.properties, "Message properties is not present. Aborting message."); + $.assert(.message.properties.listData, "listData is not present inside properties. Aborting message."); + $.assert($.containsAll(Object.keys(.message.properties.listData), ["add", "remove"]), "unsupported action type. Aborting message.") + + - name: prepareIdentifiersList + description: | + Populate list of identifiers to be updated + template: | + const destinationFields = .message.context.destinationFields.split(", ") + const audienceId = .message.context.externalId[0].type.split("-")[1]; + const isHashRequired = .destination.Config.isHashRequired; + const advertiserIds = .metadata.secret.advertiserIds; + const hashTraits = function(traits) { + traits@trait.(destinationFields@destinationField.( + trait[destinationField] ? { + id: isHashRequired ? + destinationField in $.SHA256_TRAITS ? + $.SHA256(trait[destinationField]) : $.MD5(trait[destinationField]) + : trait[destinationField], + audience_ids:[audienceId] + } : {} + )[]) + }; + const listData = .message.properties.listData; + const actions = Object.keys(listData) + actions@action.({ + "batch_data": hashTraits(listData[action]), + "id_schema": destinationFields, + "advertiser_ids": advertiserIds, + "action": $.ACTION_MAP[action], + })[] + + + - name: buildResponseForProcessTransformation + description: build response + template: | + const accessToken = .metadata.secret.accessToken + const anonymousId = .message.anonymousId; + $.outputs.prepareIdentifiersList@body.( + let response = $.defaultRequestConfig(); + response.body.JSON = body; + response.userId = anonymousId; + response.endpoint = "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/"; + response.headers = { + "Access-Token": accessToken, + "Content-Type": "application/json" + }; + response + ) diff --git a/src/cdk/v2/destinations/tiktok_audience/rtWorkflow.yaml b/src/cdk/v2/destinations/tiktok_audience/rtWorkflow.yaml new file mode 100644 index 0000000000..a7fa855938 --- /dev/null +++ b/src/cdk/v2/destinations/tiktok_audience/rtWorkflow.yaml @@ -0,0 +1,31 @@ +bindings: + - name: handleRtTfSingleEventError + path: ../../../../v0/util/index + +steps: + - name: validateInput + template: | + $.assert(Array.isArray(^) && ^.length > 0, "Invalid event array") + + - name: transform + externalWorkflow: + path: ./procWorkflow.yaml + loopOverInput: true + + - name: successfulEvents + template: | + $.outputs.transform#idx{"output" in .}.({ + "batchedRequest": .output, + "batched": true, + "destination": ^[idx].destination, + "metadata": ^[idx].metadata[], + "statusCode": 200 + })[] + - name: failedEvents + template: | + $.outputs.transform#idx.error.( + $.handleRtTfSingleEventError(^[idx], .originalError ?? ., {}) + )[] + - name: finalPayload + template: | + [...$.outputs.failedEvents, ...$.outputs.successfulEvents] diff --git a/src/cdk/v2/handler.ts b/src/cdk/v2/handler.ts index 4b3868b85b..47d6d10179 100644 --- a/src/cdk/v2/handler.ts +++ b/src/cdk/v2/handler.ts @@ -64,25 +64,26 @@ export function getCachedWorkflowEngine( return workflowEnginePromiseMap[destName][feature]; } -export async function executeWorkflow(workflowEngine: WorkflowEngine, parsedEvent: FixMe) { - try { - const result = await workflowEngine.execute(parsedEvent); - // TODO: Handle remaining output scenarios - return result.output; - } catch (error) { - throw getErrorInfo(error, isCdkV2Destination(parsedEvent), defTags); - } +export async function executeWorkflow( + workflowEngine: WorkflowEngine, + parsedEvent: FixMe, + requestMetadata: NonNullable = {}, +) { + const result = await workflowEngine.execute(parsedEvent, { requestMetadata }); + // TODO: Handle remaining output scenarios + return result.output; } export async function processCdkV2Workflow( destType: string, parsedEvent: FixMe, feature: string, + requestMetadata: NonNullable = {}, bindings: Record = {}, ) { try { const workflowEngine = await getCachedWorkflowEngine(destType, feature, bindings); - return await executeWorkflow(workflowEngine, parsedEvent); + return await executeWorkflow(workflowEngine, parsedEvent, requestMetadata); } catch (error) { throw getErrorInfo(error, isCdkV2Destination(parsedEvent), defTags); } diff --git a/src/cdk/v2/utils.ts b/src/cdk/v2/utils.ts index 3fb26c07e0..f9a5c66937 100644 --- a/src/cdk/v2/utils.ts +++ b/src/cdk/v2/utils.ts @@ -1,9 +1,9 @@ import path from 'path'; import fs from 'fs/promises'; import { WorkflowExecutionError, WorkflowCreationError } from '@rudderstack/workflow-engine'; +import { PlatformError } from '@rudderstack/integrations-lib'; import logger from '../../logger'; import { generateErrorObject } from '../../v0/util'; -import { PlatformError } from '../../v0/util/errorTypes'; import tags from '../../v0/util/tags'; import { CatchErr } from '../../util/types'; diff --git a/src/constants/destinationCanonicalNames.js b/src/constants/destinationCanonicalNames.js index 870c534db0..d1e199c9e2 100644 --- a/src/constants/destinationCanonicalNames.js +++ b/src/constants/destinationCanonicalNames.js @@ -1,5 +1,6 @@ const DestHandlerMap = { ga360: 'ga', + salesforce_oauth: 'salesforce', }; const DestCanonicalNames = { diff --git a/src/controllers/delivery.ts b/src/controllers/delivery.ts index 5dee091c46..0cc5e12d78 100644 --- a/src/controllers/delivery.ts +++ b/src/controllers/delivery.ts @@ -1,32 +1,48 @@ +/* eslint-disable prefer-destructuring */ +/* eslint-disable sonarjs/no-duplicate-string */ import { Context } from 'koa'; -import MiscService from '../services/misc'; -import { DeliveryResponse, ProcessorTransformationOutput } from '../types/index'; -import ServiceSelector from '../helpers/serviceSelector'; -import DeliveryTestService from '../services/delivertTest/deliveryTest'; -import ControllerUtility from './util'; +import { MiscService } from '../services/misc'; +import { + DeliveriesResponse, + DeliveryResponse, + ProcessorTransformationOutput, + ProxyDeliveriesRequest, + ProxyDeliveryRequest, +} from '../types/index'; +import { ServiceSelector } from '../helpers/serviceSelector'; +import { DeliveryTestService } from '../services/delivertTest/deliveryTest'; +import { ControllerUtility } from './util'; import logger from '../logger'; -import DestinationPostTransformationService from '../services/destination/postTransformation'; +import { DestinationPostTransformationService } from '../services/destination/postTransformation'; import tags from '../v0/util/tags'; import { FixMe } from '../util/types'; -export default class DeliveryController { +const NON_DETERMINABLE = 'Non-determinable'; + +export class DeliveryController { public static async deliverToDestination(ctx: Context) { logger.debug('Native(Delivery):: Request to transformer::', JSON.stringify(ctx.request.body)); let deliveryResponse: DeliveryResponse; const requestMetadata = MiscService.getRequestMetadata(ctx); - const event = ctx.request.body as ProcessorTransformationOutput; + const deliveryRequest = ctx.request.body as ProxyDeliveryRequest; const { destination }: { destination: string } = ctx.params; const integrationService = ServiceSelector.getNativeDestinationService(); try { - deliveryResponse = await integrationService.deliver(event, destination, requestMetadata); + deliveryResponse = (await integrationService.deliver( + deliveryRequest, + destination, + requestMetadata, + 'v0', + )) as DeliveryResponse; } catch (error: any) { + const { metadata } = deliveryRequest; const metaTO = integrationService.getTags( destination, - event.metadata?.destinationId || 'Non-determininable', - event.metadata?.workspaceId || 'Non-determininable', + metadata?.destinationId || NON_DETERMINABLE, + metadata?.workspaceId || NON_DETERMINABLE, tags.FEATURES.DATA_DELIVERY, ); - metaTO.metadata = event.metadata; + metaTO.metadata = metadata; deliveryResponse = DestinationPostTransformationService.handleDeliveryFailureEvents( error, metaTO, @@ -34,6 +50,42 @@ export default class DeliveryController { } ctx.body = { output: deliveryResponse }; ControllerUtility.deliveryPostProcess(ctx, deliveryResponse.status); + + logger.debug('Native(Delivery):: Response from transformer::', JSON.stringify(ctx.body)); + return ctx; + } + + public static async deliverToDestinationV1(ctx: Context) { + logger.debug('Native(Delivery):: Request to transformer::', JSON.stringify(ctx.request.body)); + let deliveryResponse: DeliveriesResponse; + const requestMetadata = MiscService.getRequestMetadata(ctx); + const deliveryRequest = ctx.request.body as ProxyDeliveriesRequest; + const { destination }: { destination: string } = ctx.params; + const integrationService = ServiceSelector.getNativeDestinationService(); + try { + deliveryResponse = (await integrationService.deliver( + deliveryRequest, + destination, + requestMetadata, + 'v1', + )) as DeliveriesResponse; + } catch (error: any) { + const { metadata } = deliveryRequest; + const metaTO = integrationService.getTags( + destination, + metadata[0].destinationId || NON_DETERMINABLE, + metadata[0].workspaceId || NON_DETERMINABLE, + tags.FEATURES.DATA_DELIVERY, + ); + metaTO.metadatas = metadata; + deliveryResponse = DestinationPostTransformationService.handlevV1DeliveriesFailureEvents( + error, + metaTO, + ); + } + ctx.body = { output: deliveryResponse }; + ControllerUtility.deliveryPostProcess(ctx); + logger.debug('Native(Delivery):: Response from transformer::', JSON.stringify(ctx.body)); return ctx; } @@ -44,6 +96,7 @@ export default class DeliveryController { JSON.stringify(ctx.request.body), ); const { destination }: { destination: string } = ctx.params; + const { version }: { version: string } = ctx.params; const { deliveryPayload, destinationRequestPayload, @@ -55,6 +108,7 @@ export default class DeliveryController { destination, destinationRequestPayload, deliveryPayload, + version, ); ctx.body = { output: response }; ControllerUtility.postProcess(ctx); diff --git a/src/controllers/destination.ts b/src/controllers/destination.ts index 60eac8a56c..71075d1b4c 100644 --- a/src/controllers/destination.ts +++ b/src/controllers/destination.ts @@ -1,22 +1,22 @@ import { Context } from 'koa'; -import MiscService from '../services/misc'; -import PreTransformationDestinationService from '../services/destination/preTransformation'; -import PostTransformationDestinationService from '../services/destination/postTransformation'; +import { MiscService } from '../services/misc'; +import { DestinationPreTransformationService } from '../services/destination/preTransformation'; +import { DestinationPostTransformationService } from '../services/destination/postTransformation'; import { ProcessorTransformationRequest, RouterTransformationRequest, ProcessorTransformationResponse, RouterTransformationResponse, } from '../types/index'; -import ServiceSelector from '../helpers/serviceSelector'; -import ControllerUtility from './util'; +import { ServiceSelector } from '../helpers/serviceSelector'; +import { ControllerUtility } from './util'; import stats from '../util/stats'; import logger from '../logger'; import { getIntegrationVersion } from '../util/utils'; import tags from '../v0/util/tags'; -import DynamicConfigParser from '../util/dynamicConfigParser'; +import { DynamicConfigParser } from '../util/dynamicConfigParser'; -export default class DestinationController { +export class DestinationController { public static async destinationTransformAtProcessor(ctx: Context) { const startTime = new Date(); logger.debug( @@ -36,7 +36,7 @@ export default class DestinationController { const integrationService = ServiceSelector.getDestinationService(events); try { integrationService.init(); - events = PreTransformationDestinationService.preProcess( + events = DestinationPreTransformationService.preProcess( events, ctx, ) as ProcessorTransformationRequest[]; @@ -59,7 +59,7 @@ export default class DestinationController { tags.FEATURES.PROCESSOR, ); metaTO.metadata = ev.metadata; - const errResp = PostTransformationDestinationService.handleProcessorTransformFailureEvents( + const errResp = DestinationPostTransformationService.handleProcessorTransformFailureEvents( error, metaTO, ); @@ -110,7 +110,7 @@ export default class DestinationController { const integrationService = ServiceSelector.getDestinationService(events); let resplist: RouterTransformationResponse[]; try { - events = PreTransformationDestinationService.preProcess(events, ctx); + events = DestinationPreTransformationService.preProcess(events, ctx); const timestampCorrectEvents = ControllerUtility.handleTimestampInEvents(events); events = DynamicConfigParser.process(timestampCorrectEvents); resplist = await integrationService.doRouterTransformation( @@ -127,7 +127,7 @@ export default class DestinationController { tags.FEATURES.ROUTER, ); metaTO.metadatas = events.map((ev) => ev.metadata); - const errResp = PostTransformationDestinationService.handleRouterTransformFailureEvents( + const errResp = DestinationPostTransformationService.handleRouterTransformFailureEvents( error, metaTO, ); @@ -165,7 +165,7 @@ export default class DestinationController { let events = routerRequest.input; const integrationService = ServiceSelector.getDestinationService(events); try { - events = PreTransformationDestinationService.preProcess(events, ctx); + events = DestinationPreTransformationService.preProcess(events, ctx); const timestampCorrectEvents = ControllerUtility.handleTimestampInEvents(events); const resplist = integrationService.doBatchTransformation( timestampCorrectEvents, @@ -182,7 +182,7 @@ export default class DestinationController { tags.FEATURES.BATCH, ); metaTO.metadatas = events.map((ev) => ev.metadata); - const errResp = PostTransformationDestinationService.handleBatchTransformFailureEvents( + const errResp = DestinationPostTransformationService.handleBatchTransformFailureEvents( error, metaTO, ); diff --git a/src/controllers/eventTest.ts b/src/controllers/eventTest.ts index 8888b63807..d5507f65d2 100644 --- a/src/controllers/eventTest.ts +++ b/src/controllers/eventTest.ts @@ -1,9 +1,9 @@ import { Context } from 'koa'; -import EventTesterService from '../services/eventTest/eventTester'; +import { EventTesterService } from '../services/eventTest/eventTester'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { CatchErr, FixMe } from '../util/types'; -export default class EventTestController { +export class EventTestController { private static API_VERSION = '1'; public static async testEvent(ctx: Context) { diff --git a/src/controllers/misc.ts b/src/controllers/misc.ts index 92ec33f80f..e2efdab5db 100644 --- a/src/controllers/misc.ts +++ b/src/controllers/misc.ts @@ -1,7 +1,7 @@ import { Context } from 'koa'; -import MiscService from '../services/misc'; +import { MiscService } from '../services/misc'; -export default class MiscController { +export class MiscController { public static healthStats(ctx: Context) { ctx.body = MiscService.getHealthInfo(); ctx.status = 200; diff --git a/src/controllers/profile.ts b/src/controllers/profile.ts index 984f4ac645..a0a62bf479 100644 --- a/src/controllers/profile.ts +++ b/src/controllers/profile.ts @@ -1,8 +1,8 @@ import { Context } from 'koa'; -import ProfileService from '../services/profile'; -import ControllerUtility from './util'; +import { ProfileService } from '../services/profile'; +import { ControllerUtility } from './util'; -export default class ProfileController { +export class ProfileController { /** * Example usage of API * diff --git a/src/controllers/regulation.ts b/src/controllers/regulation.ts index cefe1f748a..a50541780d 100644 --- a/src/controllers/regulation.ts +++ b/src/controllers/regulation.ts @@ -1,15 +1,14 @@ import { Context } from 'koa'; import logger from '../logger'; import { UserDeletionRequest, UserDeletionResponse } from '../types'; -import ServiceSelector from '../helpers/serviceSelector'; +import { ServiceSelector } from '../helpers/serviceSelector'; import tags from '../v0/util/tags'; import stats from '../util/stats'; -import PostTransformationDestinationService from '../services/destination/postTransformation'; +import { DestinationPostTransformationService } from '../services/destination/postTransformation'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { CatchErr } from '../util/types'; -// TODO: refactor this class to new format -export default class RegulationController { +export class RegulationController { public static async deleteUsers(ctx: Context) { logger.debug( 'Native(Process-Transform):: Requst to transformer::', @@ -44,7 +43,7 @@ export default class RegulationController { tags.FEATURES.USER_DELETION, ); // eslint-disable-next-line @typescript-eslint/no-unused-vars - const errResp = PostTransformationDestinationService.handleUserDeletionFailureEvents( + const errResp = DestinationPostTransformationService.handleUserDeletionFailureEvents( error, metaTO, ); diff --git a/src/controllers/source.ts b/src/controllers/source.ts index efb6dc746e..ef5483a756 100644 --- a/src/controllers/source.ts +++ b/src/controllers/source.ts @@ -1,11 +1,11 @@ import { Context } from 'koa'; -import MiscService from '../services/misc'; -import ServiceSelector from '../helpers/serviceSelector'; -import ControllerUtility from './util'; +import { MiscService } from '../services/misc'; +import { ServiceSelector } from '../helpers/serviceSelector'; +import { ControllerUtility } from './util'; import logger from '../logger'; -import PostTransformationServiceSource from '../services/source/postTransformation'; +import { SourcePostTransformationService } from '../services/source/postTransformation'; -export default class SourceController { +export class SourceController { public static async sourceTransform(ctx: Context) { logger.debug( 'Native(Source-Transform):: Request to transformer::', @@ -16,16 +16,21 @@ export default class SourceController { const { version, source }: { version: string; source: string } = ctx.params; const integrationService = ServiceSelector.getNativeSourceService(); try { - const resplist = await integrationService.sourceTransformRoutine( - events, + const { implementationVersion, input } = ControllerUtility.adaptInputToVersion( source, version, + events, + ); + const resplist = await integrationService.sourceTransformRoutine( + input, + source, + implementationVersion, requestMetadata, ); ctx.body = resplist; } catch (err: any) { const metaTO = integrationService.getTags(); - const resp = PostTransformationServiceSource.handleFailureEventsSource(err, metaTO); + const resp = SourcePostTransformationService.handleFailureEventsSource(err, metaTO); ctx.body = [resp]; } ControllerUtility.postProcess(ctx); diff --git a/src/controllers/trackingPlan.ts b/src/controllers/trackingPlan.ts index 66bf360700..74e47e0ec9 100644 --- a/src/controllers/trackingPlan.ts +++ b/src/controllers/trackingPlan.ts @@ -1,8 +1,8 @@ import { Context } from 'koa'; -import TrackingPlanservice from '../services/trackingPlan'; -import ControllerUtility from './util'; +import { TrackingPlanservice } from '../services/trackingPlan'; +import { ControllerUtility } from './util'; -export default class TrackingPlanController { +export class TrackingPlanController { public static async validateTrackingPlan(ctx: Context) { const events = ctx.request.body; const requestSize = Number(ctx.request.get('content-length')); diff --git a/src/controllers/userTransform.ts b/src/controllers/userTransform.ts index 6cbf578077..c344bd072a 100644 --- a/src/controllers/userTransform.ts +++ b/src/controllers/userTransform.ts @@ -1,15 +1,15 @@ import { Context } from 'koa'; import { ProcessorTransformationRequest, UserTransformationServiceResponse } from '../types/index'; -import UserTransformService from '../services/userTransform'; +import { UserTransformService } from '../services/userTransform'; import logger from '../logger'; import { setupUserTransformHandler, extractLibraries, validateCode, } from '../util/customTransformer'; -import ControllerUtility from './util'; +import { ControllerUtility } from './util'; -export default class UserTransformController { +export class UserTransformController { public static async transform(ctx: Context) { logger.debug( '(User transform - router:/customTransform ):: Request to transformer', diff --git a/src/controllers/util/index.test.ts b/src/controllers/util/index.test.ts new file mode 100644 index 0000000000..e23d3f6832 --- /dev/null +++ b/src/controllers/util/index.test.ts @@ -0,0 +1,149 @@ +import { ControllerUtility } from './index'; + +describe('adaptInputToVersion', () => { + it('should return the input unchanged when the implementation version is not found', () => { + const sourceType = 'NA_SOURCE'; + const requestVersion = 'v0'; + const input = [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ]; + const expected = { + implementationVersion: undefined, + input: [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ], + }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); + it('should return the input unchanged when the implementation version and request version are the same i.e. v0', () => { + const sourceType = 'pipedream'; + const requestVersion = 'v0'; + const input = [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ]; + const expected = { + implementationVersion: 'v0', + input: [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ], + }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); + it('should return the input unchanged when the implementation version and request version are the same i.e. v1', () => { + const sourceType = 'webhook'; + const requestVersion = 'v1'; + const input = [ + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + ]; + const expected = { + implementationVersion: 'v1', + input: [ + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + ], + }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); + it('should convert input from v0 to v1 when the request version is v0 and the implementation version is v1', () => { + const sourceType = 'webhook'; + const requestVersion = 'v0'; + const input = [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ]; + const expected = { + implementationVersion: 'v1', + input: [ + { event: { key1: 'val1', key2: 'val2' }, source: undefined }, + { event: { key1: 'val1', key2: 'val2' }, source: undefined }, + { event: { key1: 'val1', key2: 'val2' }, source: undefined }, + ], + }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); + + it('should convert input from v1 to v0 format when the request version is v1 and the implementation version is v0', () => { + const sourceType = 'pipedream'; + const requestVersion = 'v1'; + const input = [ + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + { + event: { key1: 'val1', key2: 'val2' }, + source: { id: 'source_id', config: { configField1: 'configVal1' } }, + }, + ]; + const expected = { + implementationVersion: 'v0', + input: [ + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + { key1: 'val1', key2: 'val2' }, + ], + }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); + + // Should return an empty array when the input is an empty array + it('should return an empty array when the input is an empty array', () => { + const sourceType = 'pipedream'; + const requestVersion = 'v1'; + const input = []; + const expected = { implementationVersion: 'v0', input: [] }; + + const result = ControllerUtility.adaptInputToVersion(sourceType, requestVersion, input); + + expect(result).toEqual(expected); + }); +}); diff --git a/src/controllers/util/index.ts b/src/controllers/util/index.ts index e2071968d7..75d3d8ffa7 100644 --- a/src/controllers/util/index.ts +++ b/src/controllers/util/index.ts @@ -1,3 +1,5 @@ +import fs = require('fs'); +import path = require('path'); import { Context } from 'koa'; import isEmpty from 'lodash/isEmpty'; import get from 'get-value'; @@ -7,12 +9,15 @@ import { ProcessorTransformationRequest, RouterTransformationRequestData, RudderMessage, + SourceInput, } from '../../types'; import { getValueFromMessage } from '../../v0/util'; import genericFieldMap from '../../v0/util/data/GenericFieldMapping.json'; import { EventType, MappedToDestinationKey } from '../../constants'; -export default class ControllerUtility { +export class ControllerUtility { + private static sourceVersionMap: Map = new Map(); + public static timestampValsMap: Record = { [EventType.IDENTIFY]: [ `context.${RETL_TIMESTAMP}`, @@ -23,6 +28,49 @@ export default class ControllerUtility { [EventType.TRACK]: [`properties.${RETL_TIMESTAMP}`, ...genericFieldMap.timestamp], }; + private static getSourceVersionsMap(): Map { + if (this.sourceVersionMap?.size > 0) { + return this.sourceVersionMap; + } + const versions = ['v0', 'v1']; + versions.forEach((version) => { + const files = fs.readdirSync(path.resolve(__dirname, `../../${version}/sources`), { + withFileTypes: true, + }); + const sources = files.filter((file) => file.isDirectory()).map((folder) => folder.name); + sources.forEach((source) => { + this.sourceVersionMap.set(source, version); + }); + }); + return this.sourceVersionMap; + } + + private static convertSourceInputv1Tov0(sourceEvents: SourceInput[]): NonNullable[] { + return sourceEvents.map((sourceEvent) => sourceEvent.event); + } + + private static convertSourceInputv0Tov1(sourceEvents: unknown[]): SourceInput[] { + return sourceEvents.map( + (sourceEvent) => ({ event: sourceEvent, source: undefined } as SourceInput), + ); + } + + public static adaptInputToVersion( + sourceType: string, + requestVersion: string, + input: NonNullable[], + ): { implementationVersion: string; input: NonNullable[] } { + const sourceToVersionMap = this.getSourceVersionsMap(); + const implementationVersion = sourceToVersionMap.get(sourceType); + let updatedInput: NonNullable[] = input; + if (requestVersion === 'v0' && implementationVersion === 'v1') { + updatedInput = this.convertSourceInputv0Tov1(input); + } else if (requestVersion === 'v1' && implementationVersion === 'v0') { + updatedInput = this.convertSourceInputv1Tov0(input as SourceInput[]); + } + return { implementationVersion, input: updatedInput }; + } + private static getCompatibleStatusCode(status: number): number { return getCompatibleStatusCode(status); } diff --git a/src/features.json b/src/features.json index 7de214ab39..e0745c2246 100644 --- a/src/features.json +++ b/src/features.json @@ -25,6 +25,7 @@ "PINTEREST_TAG": true, "PROFITWELL": true, "SALESFORCE": true, + "SALESFORCE_OAUTH": true, "SFMC": true, "SNAPCHAT_CONVERSION": true, "TIKTOK_ADS": true, @@ -58,6 +59,12 @@ "OPTIMIZELY_FULLSTACK": true, "TWITTER_ADS": true, "CLEVERTAP": true, - "ORTTO": true - } + "ORTTO": true, + "GLADLY": true, + "ONE_SIGNAL": true, + "TIKTOK_AUDIENCE": true, + "REDDIT": true + }, + "supportSourceTransformV1": true, + "supportTransformerProxyV1": true } diff --git a/src/helpers/fetchHandlers.ts b/src/helpers/fetchHandlers.ts index 96a74e528d..ef7d9e6611 100644 --- a/src/helpers/fetchHandlers.ts +++ b/src/helpers/fetchHandlers.ts @@ -1,6 +1,6 @@ -import MiscService from '../services/misc'; +import { MiscService } from '../services/misc'; -export default class FetchHandler { +export class FetchHandler { private static sourceHandlerMap: Map = new Map(); private static destHandlerMap: Map = new Map(); diff --git a/src/helpers/serviceSelector.ts b/src/helpers/serviceSelector.ts index bac1a17c16..89678e9407 100644 --- a/src/helpers/serviceSelector.ts +++ b/src/helpers/serviceSelector.ts @@ -1,16 +1,16 @@ +import { PlatformError } from '@rudderstack/integrations-lib'; import { ProcessorTransformationRequest, RouterTransformationRequestData } from '../types/index'; import { INTEGRATION_SERVICE } from '../routes/utils/constants'; -import CDKV1DestinationService from '../services/destination/cdkV1Integration'; -import CDKV2DestinationService from '../services/destination/cdkV2Integration'; -import DestinationService from '../interfaces/DestinationService'; -import NativeIntegrationDestinationService from '../services/destination/nativeIntegration'; -import SourceService from '../interfaces/SourceService'; -import NativeIntegrationSourceService from '../services/source/nativeIntegration'; -import { PlatformError } from '../v0/util/errorTypes'; -import ComparatorService from '../services/comparator'; +import { CDKV1DestinationService } from '../services/destination/cdkV1Integration'; +import { CDKV2DestinationService } from '../services/destination/cdkV2Integration'; +import { DestinationService } from '../interfaces/DestinationService'; +import { NativeIntegrationDestinationService } from '../services/destination/nativeIntegration'; +import { SourceService } from '../interfaces/SourceService'; +import { NativeIntegrationSourceService } from '../services/source/nativeIntegration'; +import { ComparatorService } from '../services/comparator'; import { FixMe } from '../util/types'; -export default class ServiceSelector { +export class ServiceSelector { private static serviceMap: Map = new Map(); private static services = { diff --git a/src/index.ts b/src/index.ts index d1cc95cc36..36f32f1aed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,8 +4,6 @@ import gracefulShutdown from 'http-graceful-shutdown'; import dotenv from 'dotenv'; import logger from './logger'; import cluster from './util/cluster'; -import { router } from './legacy/router'; -import { testRouter } from './testRouter'; import { metricsRouter } from './routes/metricsRouter'; import { addStatMiddleware, addRequestSizeMiddleware, initPyroscope } from './middleware'; import { logProcessInfo } from './util/utils'; @@ -14,7 +12,6 @@ import { RedisDB } from './util/redis/redisConnector'; dotenv.config(); const clusterEnabled = process.env.CLUSTER_ENABLED !== 'false'; -const useUpdatedRoutes = process.env.ENABLE_NEW_ROUTES !== 'false'; const port = parseInt(process.env.PORT ?? '9090', 10); const metricsPort = parseInt(process.env.METRICS_PORT || '9091', 10); @@ -35,15 +32,8 @@ app.use( addRequestSizeMiddleware(app); addSwaggerRoutes(app); -if (useUpdatedRoutes) { - logger.info('Using new routes'); - applicationRoutes(app); -} else { - // To be depricated - logger.info('Using old routes'); - app.use(router.routes()).use(router.allowedMethods()); - app.use(testRouter.routes()).use(testRouter.allowedMethods()); -} +logger.info('Using new routes'); +applicationRoutes(app); function finalFunction() { RedisDB.disconnect(); diff --git a/src/interfaces/DestinationService.ts b/src/interfaces/DestinationService.ts index 123da35292..bf39024d85 100644 --- a/src/interfaces/DestinationService.ts +++ b/src/interfaces/DestinationService.ts @@ -5,12 +5,13 @@ import { ProcessorTransformationResponse, RouterTransformationRequestData, RouterTransformationResponse, - ProcessorTransformationOutput, UserDeletionRequest, UserDeletionResponse, + ProxyRequest, + DeliveriesResponse, } from '../types/index'; -export default interface DestinationService { +export interface DestinationService { getName(): string; init(): void; @@ -44,10 +45,11 @@ export default interface DestinationService { ): RouterTransformationResponse[]; deliver( - event: ProcessorTransformationOutput, + event: ProxyRequest, destinationType: string, requestMetadata: NonNullable, - ): Promise; + version: string, + ): Promise; processUserDeletion( requests: UserDeletionRequest[], diff --git a/src/interfaces/SourceService.ts b/src/interfaces/SourceService.ts index 99b29f095b..c7de8cfe8b 100644 --- a/src/interfaces/SourceService.ts +++ b/src/interfaces/SourceService.ts @@ -1,6 +1,6 @@ import { MetaTransferObject, SourceTransformationResponse } from '../types/index'; -export default interface SourceService { +export interface SourceService { getTags(): MetaTransferObject; sourceTransformRoutine( diff --git a/src/legacy/router.js b/src/legacy/router.js index a8c2b49a1a..f8deb3fe62 100644 --- a/src/legacy/router.js +++ b/src/legacy/router.js @@ -7,6 +7,7 @@ const Router = require('@koa/router'); const lodash = require('lodash'); const fs = require('fs'); const path = require('path'); +const { PlatformError } = require('@rudderstack/integrations-lib'); const logger = require('../logger'); const stats = require('../util/stats'); const { SUPPORTED_VERSIONS, API_VERSION } = require('../routes/utils/constants'); @@ -35,7 +36,6 @@ const { sendViolationMetrics, constructValidationErrors, } = require('../util/utils'); -const { PlatformError } = require('../v0/util/errorTypes'); const { processCdkV1 } = require('../cdk/v1/handler'); const { extractLibraries } = require('../util/customTransformer'); const { getCompatibleStatusCode } = require('../adapters/utils/networkUtils'); @@ -571,14 +571,9 @@ if (startDestTransformer) { destEvents.length > 0 && destEvents[0].metadata ? getMetadata(destEvents[0].metadata) : {}; - const userFuncStartTime = new Date(); if (transformationVersionId) { let destTransformedEvents; try { - stats.counter('user_transform_function_input_events', destEvents.length, { - processSessions, - ...metaTags, - }); destTransformedEvents = await userTransformHandler()( destEvents, transformationVersionId, @@ -630,12 +625,6 @@ if (startDestTransformer) { processSessions, ...metaTags, }); - } finally { - stats.timing('user_transform_function_latency', userFuncStartTime, { - transformationVersionId, - processSessions, - ...metaTags, - }); } } else { const errorMessage = 'Transformation VersionID not found'; diff --git a/src/middlewares/featureFlag.ts b/src/middlewares/featureFlag.ts index 146e57186c..206fa7c5ea 100644 --- a/src/middlewares/featureFlag.ts +++ b/src/middlewares/featureFlag.ts @@ -6,7 +6,7 @@ export interface FeatureFlags { export const FEATURE_FILTER_CODE = 'filter-code'; -export default class FeatureFlagMiddleware { +export class FeatureFlagMiddleware { public static async handle(ctx: Context, next: Next): Promise { // Initialize ctx.state.features if it doesn't exist ctx.state.features = (ctx.state.features || {}) as FeatureFlags; diff --git a/src/middlewares/routeActivation.ts b/src/middlewares/routeActivation.ts index dfdaef964e..ffb1e15e80 100644 --- a/src/middlewares/routeActivation.ts +++ b/src/middlewares/routeActivation.ts @@ -18,7 +18,7 @@ const destinationFilterList = process.env.DESTINATION_FILTER_LIST?.toLocaleLower const sourceFilteList = process.env.SOURCE_FILTER_LIST?.toLocaleLowerCase(); const deliveryFilterList = process.env.DESTINATION_DELIVERY_FILTER_LIST?.toLocaleLowerCase(); -export default class RouteActivationMiddleware { +export class RouteActivationMiddleware { private static executeActivationRule(ctx: Context, next: Next, shouldActivate: boolean) { if (shouldActivate) { return next(); diff --git a/src/routes/delivery.ts b/src/routes/delivery.ts index 141700fd9f..30f4e2fb78 100644 --- a/src/routes/delivery.ts +++ b/src/routes/delivery.ts @@ -1,16 +1,23 @@ import Router from '@koa/router'; -import DeliveryController from '../controllers/delivery'; -import RouteActivationMiddleware from '../middlewares/routeActivation'; +import { DeliveryController } from '../controllers/delivery'; +import { RouteActivationMiddleware } from '../middlewares/routeActivation'; const router = new Router(); router.post( - '/:version/destinations/:destination/proxy', + '/v0/destinations/:destination/proxy', RouteActivationMiddleware.isDeliveryRouteActive, RouteActivationMiddleware.destinationDeliveryFilter, DeliveryController.deliverToDestination, ); +router.post( + '/v1/destinations/:destination/proxy', + RouteActivationMiddleware.isDeliveryRouteActive, + RouteActivationMiddleware.destinationDeliveryFilter, + DeliveryController.deliverToDestinationV1, +); + router.post( '/:version/destinations/:destination/proxyTest', RouteActivationMiddleware.isDeliveryTestRouteActive, diff --git a/src/routes/destination.ts b/src/routes/destination.ts index 3d4be42ff3..1c47825145 100644 --- a/src/routes/destination.ts +++ b/src/routes/destination.ts @@ -1,30 +1,30 @@ import Router from '@koa/router'; -import DestinationController from '../controllers/destination'; -import RegulationController from '../controllers/regulation'; -import FeatureFlagController from '../middlewares/featureFlag'; -import RouteActivationController from '../middlewares/routeActivation'; +import { DestinationController } from '../controllers/destination'; +import { RegulationController } from '../controllers/regulation'; +import { FeatureFlagMiddleware } from '../middlewares/featureFlag'; +import { RouteActivationMiddleware } from '../middlewares/routeActivation'; const router = new Router(); router.post( '/:version/destinations/:destination', - RouteActivationController.isDestinationRouteActive, - RouteActivationController.destinationProcFilter, - FeatureFlagController.handle, + RouteActivationMiddleware.isDestinationRouteActive, + RouteActivationMiddleware.destinationProcFilter, + FeatureFlagMiddleware.handle, DestinationController.destinationTransformAtProcessor, ); router.post( '/routerTransform', - RouteActivationController.isDestinationRouteActive, - RouteActivationController.destinationRtFilter, - FeatureFlagController.handle, + RouteActivationMiddleware.isDestinationRouteActive, + RouteActivationMiddleware.destinationRtFilter, + FeatureFlagMiddleware.handle, DestinationController.destinationTransformAtRouter, ); router.post( '/batch', - RouteActivationController.isDestinationRouteActive, - RouteActivationController.destinationBatchFilter, - FeatureFlagController.handle, + RouteActivationMiddleware.isDestinationRouteActive, + RouteActivationMiddleware.destinationBatchFilter, + FeatureFlagMiddleware.handle, DestinationController.batchProcess, ); diff --git a/src/routes/misc.ts b/src/routes/misc.ts index 750c1194dd..4d1c5d5fb5 100644 --- a/src/routes/misc.ts +++ b/src/routes/misc.ts @@ -1,6 +1,6 @@ import Router from '@koa/router'; -import ProfileController from '../controllers/profile'; -import MiscController from '../controllers/misc'; +import { ProfileController } from '../controllers/profile'; +import { MiscController } from '../controllers/misc'; const router = new Router(); diff --git a/src/routes/source.ts b/src/routes/source.ts index ade26c8700..1abc46e2e4 100644 --- a/src/routes/source.ts +++ b/src/routes/source.ts @@ -1,13 +1,13 @@ import Router from '@koa/router'; -import RouteActivationController from '../middlewares/routeActivation'; -import SourceController from '../controllers/source'; +import { RouteActivationMiddleware } from '../middlewares/routeActivation'; +import { SourceController } from '../controllers/source'; const router = new Router(); router.post( '/:version/sources/:source', - RouteActivationController.isSourceRouteActive, - RouteActivationController.sourceFilter, + RouteActivationMiddleware.isSourceRouteActive, + RouteActivationMiddleware.sourceFilter, SourceController.sourceTransform, ); diff --git a/src/routes/testEvents.ts b/src/routes/testEvents.ts index 556ec10198..a35fe447ba 100644 --- a/src/routes/testEvents.ts +++ b/src/routes/testEvents.ts @@ -1,5 +1,5 @@ import Router from '@koa/router'; -import EventTestController from '../controllers/eventTest'; +import { EventTestController } from '../controllers/eventTest'; const router = new Router({ prefix: '/test-router' }); diff --git a/src/routes/trackingPlan.ts b/src/routes/trackingPlan.ts index d177af7b2c..3e62ba2a74 100644 --- a/src/routes/trackingPlan.ts +++ b/src/routes/trackingPlan.ts @@ -1,5 +1,5 @@ import Router from '@koa/router'; -import TrackingPlanController from '../controllers/trackingPlan'; +import { TrackingPlanController } from '../controllers/trackingPlan'; const router = new Router(); diff --git a/src/routes/userTransform.ts b/src/routes/userTransform.ts index 23870db3b4..1fb8ad3a1c 100644 --- a/src/routes/userTransform.ts +++ b/src/routes/userTransform.ts @@ -1,34 +1,34 @@ import Router from '@koa/router'; -import RouteActivationController from '../middlewares/routeActivation'; -import FeatureFlagController from '../middlewares/featureFlag'; -import UserTransformController from '../controllers/userTransform'; +import { RouteActivationMiddleware } from '../middlewares/routeActivation'; +import { FeatureFlagMiddleware } from '../middlewares/featureFlag'; +import { UserTransformController } from '../controllers/userTransform'; const router = new Router(); router.post( '/customTransform', - RouteActivationController.isUserTransformRouteActive, - FeatureFlagController.handle, + RouteActivationMiddleware.isUserTransformRouteActive, + FeatureFlagMiddleware.handle, UserTransformController.transform, ); router.post( '/transformation/test', - RouteActivationController.isUserTransformTestRouteActive, + RouteActivationMiddleware.isUserTransformTestRouteActive, UserTransformController.testTransform, ); router.post( '/transformationLibrary/test', - RouteActivationController.isUserTransformTestRouteActive, + RouteActivationMiddleware.isUserTransformTestRouteActive, UserTransformController.testTransformLibrary, ); router.post( '/transformation/sethandle', - RouteActivationController.isUserTransformTestRouteActive, + RouteActivationMiddleware.isUserTransformTestRouteActive, UserTransformController.testTransformSethandle, ); router.post( '/extractLibs', - RouteActivationController.isUserTransformRouteActive, + RouteActivationMiddleware.isUserTransformRouteActive, UserTransformController.extractLibhandle, ); diff --git a/src/routes/utils/constants.js b/src/routes/utils/constants.js index f074db6c62..ccec8e54dd 100644 --- a/src/routes/utils/constants.js +++ b/src/routes/utils/constants.js @@ -1,4 +1,4 @@ -const SUPPORTED_VERSIONS = ['v0']; +const SUPPORTED_VERSIONS = ['v0', 'v1']; const API_VERSION = '2'; const INTEGRATION_SERVICE = { COMPARATOR: 'comparator', @@ -7,8 +7,8 @@ const INTEGRATION_SERVICE = { NATIVE_DEST: 'native_dest', NATIVE_SOURCE: 'native_source', }; -const CHANNELS= { - sources: 'sources' +const CHANNELS = { + sources: 'sources', }; const RETL_TIMESTAMP = 'timestamp'; diff --git a/src/services/comparator.ts b/src/services/comparator.ts index 3495b7bbfd..d1e085b4bd 100644 --- a/src/services/comparator.ts +++ b/src/services/comparator.ts @@ -1,13 +1,14 @@ /* eslint-disable class-methods-use-this */ -import IntegrationDestinationService from '../interfaces/DestinationService'; +import { DestinationService } from '../interfaces/DestinationService'; import { + DeliveriesResponse, DeliveryResponse, Destination, ErrorDetailer, MetaTransferObject, - ProcessorTransformationOutput, ProcessorTransformationRequest, ProcessorTransformationResponse, + ProxyRequest, RouterTransformationRequestData, RouterTransformationResponse, UserDeletionRequest, @@ -20,15 +21,12 @@ import { CommonUtils } from '../util/common'; const NS_PER_SEC = 1e9; -export default class ComparatorService implements IntegrationDestinationService { - secondaryService: IntegrationDestinationService; +export class ComparatorService implements DestinationService { + secondaryService: DestinationService; - primaryService: IntegrationDestinationService; + primaryService: DestinationService; - constructor( - primaryService: IntegrationDestinationService, - secondaryService: IntegrationDestinationService, - ) { + constructor(primaryService: DestinationService, secondaryService: DestinationService) { this.primaryService = primaryService; this.secondaryService = secondaryService; } @@ -368,17 +366,18 @@ export default class ComparatorService implements IntegrationDestinationService } public async deliver( - event: ProcessorTransformationOutput, + event: ProxyRequest, destinationType: string, requestMetadata: NonNullable, - ): Promise { + version: string, + ): Promise { const primaryResplist = await this.primaryService.deliver( event, destinationType, requestMetadata, + version, ); logger.error('[LIVE_COMPARE_TEST] not implemented for delivery routine'); - return primaryResplist; } diff --git a/src/services/delivertTest/deliveryTest.ts b/src/services/delivertTest/deliveryTest.ts index e5713073c1..2f5db183e5 100644 --- a/src/services/delivertTest/deliveryTest.ts +++ b/src/services/delivertTest/deliveryTest.ts @@ -7,17 +7,18 @@ import stats from '../../util/stats'; import logger from '../../logger'; import tags from '../../v0/util/tags'; -export default class DeliveryTestService { +export class DeliveryTestService { public static async doTestDelivery( destination: string, routerDestReqPayload: any, routerDeliveryPayload: any, + version, ) { let response: any; try { - const destNetworkHandler = networkHandlerFactory.getNetworkHandler(destination); + const { networkHandler } = networkHandlerFactory.getNetworkHandler(destination, version); - const proxyDestReqPayload = destNetworkHandler.prepareProxy(routerDeliveryPayload); + const proxyDestReqPayload = networkHandler.prepareProxy(routerDeliveryPayload); response = { destinationRequestPayload: proxyDestReqPayload, }; diff --git a/src/services/destination/cdkV1Integration.ts b/src/services/destination/cdkV1Integration.ts index a016665afb..197e3162ea 100644 --- a/src/services/destination/cdkV1Integration.ts +++ b/src/services/destination/cdkV1Integration.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ConfigFactory, Executor, RudderBaseConfig } from 'rudder-transformer-cdk'; import path from 'path'; -import IntegrationDestinationService from '../../interfaces/DestinationService'; +import { TransformationError } from '@rudderstack/integrations-lib'; +import { DestinationService } from '../../interfaces/DestinationService'; import { DeliveryResponse, ErrorDetailer, @@ -10,17 +11,17 @@ import { ProcessorTransformationResponse, RouterTransformationRequestData, RouterTransformationResponse, - ProcessorTransformationOutput, UserDeletionRequest, UserDeletionResponse, + ProxyRequest, + DeliveriesResponse, } from '../../types/index'; -import { TransformationError } from '../../v0/util/errorTypes'; -import DestinationPostTransformationService from './postTransformation'; +import { DestinationPostTransformationService } from './postTransformation'; import tags from '../../v0/util/tags'; import { getErrorInfo } from '../../cdk/v1/handler'; import { CatchErr } from '../../util/types'; -export default class CDKV1DestinationService implements IntegrationDestinationService { +export class CDKV1DestinationService implements DestinationService { public init() { ConfigFactory.init({ basePath: path.resolve(__dirname, '../../cdk/v1'), @@ -117,10 +118,10 @@ export default class CDKV1DestinationService implements IntegrationDestinationSe } public deliver( - _event: ProcessorTransformationOutput, + _event: ProxyRequest, _destinationType: string, _requestMetadata: NonNullable, - ): Promise { + ): Promise { throw new TransformationError('CDV1 Does not Implement Delivery Routine'); } diff --git a/src/services/destination/cdkV2Integration.ts b/src/services/destination/cdkV2Integration.ts index b4c0a15e87..be7f0e51d5 100644 --- a/src/services/destination/cdkV2Integration.ts +++ b/src/services/destination/cdkV2Integration.ts @@ -1,8 +1,9 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable class-methods-use-this */ import groupBy from 'lodash/groupBy'; +import { TransformationError } from '@rudderstack/integrations-lib'; import { processCdkV2Workflow } from '../../cdk/v2/handler'; -import IntegrationDestinationService from '../../interfaces/DestinationService'; +import { DestinationService } from '../../interfaces/DestinationService'; import { DeliveryResponse, ErrorDetailer, @@ -14,14 +15,15 @@ import { ProcessorTransformationOutput, UserDeletionRequest, UserDeletionResponse, + ProxyRequest, + DeliveriesResponse, } from '../../types/index'; -import { TransformationError } from '../../v0/util/errorTypes'; import tags from '../../v0/util/tags'; -import DestinationPostTransformationService from './postTransformation'; +import { DestinationPostTransformationService } from './postTransformation'; import stats from '../../util/stats'; import { CatchErr } from '../../util/types'; -export default class CDKV2DestinationService implements IntegrationDestinationService { +export class CDKV2DestinationService implements DestinationService { public init() {} public getName(): string { @@ -52,7 +54,7 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe events: ProcessorTransformationRequest[], destinationType: string, _version: string, - _requestMetadata: NonNullable, + requestMetadata: NonNullable, ): Promise { // TODO: Change the promise type const respList: ProcessorTransformationResponse[][] = await Promise.all( @@ -64,6 +66,7 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe destinationType, event, tags.FEATURES.PROCESSOR, + requestMetadata, ); stats.increment('event_transform_success', { @@ -108,7 +111,7 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe events: RouterTransformationRequestData[], destinationType: string, _version: string, - _requestMetadata: NonNullable, + requestMetadata: NonNullable, ): Promise { const allDestEvents: object = groupBy( events, @@ -126,7 +129,12 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe metaTo.metadata = destInputArray[0].metadata; try { const doRouterTransformationResponse: RouterTransformationResponse[] = - await processCdkV2Workflow(destinationType, destInputArray, tags.FEATURES.ROUTER); + await processCdkV2Workflow( + destinationType, + destInputArray, + tags.FEATURES.ROUTER, + requestMetadata, + ); return DestinationPostTransformationService.handleRouterTransformSuccessEvents( doRouterTransformationResponse, undefined, @@ -159,10 +167,10 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe } public deliver( - _event: ProcessorTransformationOutput, + _event: ProxyRequest, _destinationType: string, _requestMetadata: NonNullable, - ): Promise { + ): Promise { throw new TransformationError('CDKV2 Does not Implement Delivery Routine'); } diff --git a/src/services/destination/nativeIntegration.ts b/src/services/destination/nativeIntegration.ts index a788b388e4..c3b0237cdc 100644 --- a/src/services/destination/nativeIntegration.ts +++ b/src/services/destination/nativeIntegration.ts @@ -1,7 +1,9 @@ +/* eslint-disable prefer-destructuring */ +/* eslint-disable sonarjs/no-duplicate-string */ /* eslint-disable @typescript-eslint/no-unused-vars */ import groupBy from 'lodash/groupBy'; import cloneDeep from 'lodash/cloneDeep'; -import IntegrationDestinationService from '../../interfaces/DestinationService'; +import { DestinationService } from '../../interfaces/DestinationService'; import { DeliveryResponse, ErrorDetailer, @@ -13,13 +15,19 @@ import { ProcessorTransformationOutput, UserDeletionRequest, UserDeletionResponse, + ProxyRequest, + ProxyDeliveriesRequest, + ProxyDeliveryRequest, + DeliveriesResponse, + DeliveryJobState, } from '../../types/index'; -import DestinationPostTransformationService from './postTransformation'; +import { DestinationPostTransformationService } from './postTransformation'; import networkHandlerFactory from '../../adapters/networkHandlerFactory'; -import FetchHandler from '../../helpers/fetchHandlers'; +import { FetchHandler } from '../../helpers/fetchHandlers'; import tags from '../../v0/util/tags'; +import stats from '../../util/stats'; -export default class NativeIntegrationDestinationService implements IntegrationDestinationService { +export class NativeIntegrationDestinationService implements DestinationService { public init() {} public getName(): string { @@ -169,29 +177,66 @@ export default class NativeIntegrationDestinationService implements IntegrationD } public async deliver( - destinationRequest: ProcessorTransformationOutput, + deliveryRequest: ProxyRequest, destinationType: string, _requestMetadata: NonNullable, - ): Promise { + version: string, + ): Promise { try { - const networkHandler = networkHandlerFactory.getNetworkHandler(destinationType); - const rawProxyResponse = await networkHandler.proxy(destinationRequest, destinationType); + const { networkHandler, handlerVersion } = networkHandlerFactory.getNetworkHandler( + destinationType, + version, + ); + const rawProxyResponse = await networkHandler.proxy(deliveryRequest, destinationType); const processedProxyResponse = networkHandler.processAxiosResponse(rawProxyResponse); - return networkHandler.responseHandler( + let rudderJobMetadata = + version.toLowerCase() === 'v1' + ? (deliveryRequest as ProxyDeliveriesRequest).metadata + : (deliveryRequest as ProxyDeliveryRequest).metadata; + + if (version.toLowerCase() === 'v1' && handlerVersion.toLowerCase() === 'v0') { + rudderJobMetadata = rudderJobMetadata[0]; + } + + let responseProxy = networkHandler.responseHandler( { ...processedProxyResponse, - rudderJobMetadata: destinationRequest.metadata, + rudderJobMetadata, }, destinationType, - ) as DeliveryResponse; + ); + // Adaption Logic for V0 to V1 + if (handlerVersion.toLowerCase() === 'v0' && version.toLowerCase() === 'v1') { + const v0Response = responseProxy as DeliveryResponse; + const jobStates = (deliveryRequest as ProxyDeliveriesRequest).metadata.map( + (metadata) => + ({ + error: JSON.stringify(v0Response.destinationResponse?.response), + statusCode: v0Response.status, + metadata, + } as DeliveryJobState), + ); + responseProxy = { + response: jobStates, + } as DeliveriesResponse; + } + return responseProxy; } catch (err: any) { + const metadata = Array.isArray(deliveryRequest.metadata) + ? deliveryRequest.metadata[0] + : deliveryRequest.metadata; const metaTO = this.getTags( destinationType, - destinationRequest.metadata?.destinationId || 'Non-determininable', - destinationRequest.metadata?.workspaceId || 'Non-determininable', + metadata?.destinationId || 'Non-determininable', + metadata?.workspaceId || 'Non-determininable', tags.FEATURES.DATA_DELIVERY, ); - metaTO.metadata = destinationRequest.metadata; + + if (version.toLowerCase() === 'v1') { + metaTO.metadatas = (deliveryRequest as ProxyDeliveriesRequest).metadata; + return DestinationPostTransformationService.handlevV1DeliveriesFailureEvents(err, metaTO); + } + metaTO.metadata = (deliveryRequest as ProxyDeliveryRequest).metadata; return DestinationPostTransformationService.handleDeliveryFailureEvents(err, metaTO); } } @@ -202,6 +247,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD ): Promise { const response = await Promise.all( requests.map(async (request) => { + const startTime = new Date(); const { destType } = request; const destUserDeletionHandler: any = FetchHandler.getDeletionHandler( destType.toLowerCase(), @@ -218,6 +264,11 @@ export default class NativeIntegrationDestinationService implements IntegrationD ...request, rudderDestInfo, }); + stats.timing('regulation_worker_requests_dest_latency', startTime, { + feature: tags.FEATURES.USER_DELETION, + implementation: tags.IMPLEMENTATIONS.NATIVE, + destType, + }); return result; } catch (error: any) { const metaTO = this.getTags(destType, 'unknown', 'unknown', tags.FEATURES.USER_DELETION); diff --git a/src/services/destination/postTransformation.ts b/src/services/destination/postTransformation.ts index 090e39b059..7e9cd52aed 100644 --- a/src/services/destination/postTransformation.ts +++ b/src/services/destination/postTransformation.ts @@ -2,6 +2,7 @@ import cloneDeep from 'lodash/cloneDeep'; import isObject from 'lodash/isObject'; import isEmpty from 'lodash/isEmpty'; +import { PlatformError } from '@rudderstack/integrations-lib'; import { ProcessorTransformationRequest, ProcessorTransformationResponse, @@ -10,13 +11,16 @@ import { DeliveryResponse, MetaTransferObject, UserDeletionResponse, + DeliveriesResponse, + DeliveryJobState, } from '../../types/index'; import { generateErrorObject } from '../../v0/util'; -import ErrorReportingService from '../errorReporting'; +import { ErrorReportingService } from '../errorReporting'; import tags from '../../v0/util/tags'; import stats from '../../util/stats'; +import { FixMe } from '../../util/types'; -export default class DestinationPostTransformationService { +export class DestinationPostTransformationService { public static handleProcessorTransformSucessEvents( event: ProcessorTransformationRequest, transformedPayloads: ProcessorTransformationOutput | ProcessorTransformationOutput[], @@ -139,7 +143,7 @@ export default class DestinationPostTransformationService { } public static handleDeliveryFailureEvents( - error: NonNullable, + error: any, metaTo: MetaTransferObject, ): DeliveryResponse { const errObj = generateErrorObject(error, metaTo.errorDetails, false); @@ -152,6 +156,38 @@ export default class DestinationPostTransformationService { authErrorCategory: errObj.authErrorCategory, }), } as DeliveryResponse; + + ErrorReportingService.reportError(error, metaTo.errorContext, resp); + return resp; + } + + public static handlevV1DeliveriesFailureEvents( + error: FixMe, + metaTo: MetaTransferObject, + ): DeliveriesResponse { + const errObj = generateErrorObject(error, metaTo.errorDetails, false); + const metadataArray = metaTo.metadatas; + if (!Array.isArray(metadataArray)) { + // Panic + throw new PlatformError('Proxy v1 endpoint error : metadataArray is not an array'); + } + const responses = metadataArray.map((metadata) => { + const resp = { + error: + JSON.stringify(error.destinationResponse?.response) || + errObj.message || + '[Delivery] Error occured while processing payload', + statusCode: errObj.status, + metadata, + } as DeliveryJobState; + return resp; + }); + + const resp = { + response: responses, + statTags: errObj.statTags, + } as DeliveriesResponse; + ErrorReportingService.reportError(error, metaTo.errorContext, resp); return resp; } @@ -161,7 +197,7 @@ export default class DestinationPostTransformationService { metaTo: MetaTransferObject, ): UserDeletionResponse { const errObj = generateErrorObject(error, metaTo.errorDetails, false); - // TODO: Add stat tags here + stats.increment('regulation_worker_user_deletion_failure', metaTo.errorDetails); const resp = { statusCode: errObj.status, error: errObj.message, diff --git a/src/services/destination/preTransformation.ts b/src/services/destination/preTransformation.ts index dd5579b7b9..db1d76d64e 100644 --- a/src/services/destination/preTransformation.ts +++ b/src/services/destination/preTransformation.ts @@ -1,7 +1,7 @@ import { Context } from 'koa'; import { ProcessorTransformationRequest, RouterTransformationRequestData } from '../../types/index'; -export default class PreTransformationDestinationService { +export class DestinationPreTransformationService { public static preProcess( events: ProcessorTransformationRequest[] | RouterTransformationRequestData[], ctx: Context, diff --git a/src/services/errorReporting.ts b/src/services/errorReporting.ts index 2d3c84ff30..3a4276f978 100644 --- a/src/services/errorReporting.ts +++ b/src/services/errorReporting.ts @@ -1,6 +1,6 @@ import { client } from '../util/errorNotifier'; -export default class ErrorReportingService { +export class ErrorReportingService { public static reportError(error: NonNullable, context: string, errorResp: object) { client.notify(error, context, { ...errorResp, diff --git a/src/services/eventTest/eventTester.ts b/src/services/eventTest/eventTester.ts index a3755d3e80..75df29cc63 100644 --- a/src/services/eventTest/eventTester.ts +++ b/src/services/eventTest/eventTester.ts @@ -1,7 +1,7 @@ import { sendToDestination, userTransformHandler } from '../../routerUtils'; import { FixMe } from '../../util/types'; -export default class EventTesterService { +export class EventTesterService { private static getDestHandler(version, destination) { // eslint-disable-next-line global-require, import/no-dynamic-require return require(`../../${version}/destinations/${destination}/transform`); diff --git a/src/services/misc.ts b/src/services/misc.ts index 4c3e2ae6da..e0953d08bf 100644 --- a/src/services/misc.ts +++ b/src/services/misc.ts @@ -6,7 +6,7 @@ import { DestHandlerMap } from '../constants/destinationCanonicalNames'; import { Metadata } from '../types'; import { getCPUProfile, getHeapProfile } from '../middleware'; -export default class MiscService { +export class MiscService { public static getDestHandler(dest: string, version: string) { if (DestHandlerMap.hasOwnProperty(dest)) { return require(`../${version}/destinations/${DestHandlerMap[dest]}/transform`); diff --git a/src/services/profile.ts b/src/services/profile.ts index 4d7a7104e7..d71826e251 100644 --- a/src/services/profile.ts +++ b/src/services/profile.ts @@ -22,7 +22,7 @@ logger.info(`Interval Bytes set: ${intervalBytes}`); heap.start(intervalBytes, stackDepth); -export default class ProfileService { +export class ProfileService { private static async promisifiedRead(readable: any) { // eslint-disable-next-line no-new new Promise((resolve, reject) => { diff --git a/src/services/source/nativeIntegration.ts b/src/services/source/nativeIntegration.ts index f29d68d054..6eaef2f835 100644 --- a/src/services/source/nativeIntegration.ts +++ b/src/services/source/nativeIntegration.ts @@ -1,4 +1,4 @@ -import IntegrationSourceService from '../../interfaces/SourceService'; +import { SourceService } from '../../interfaces/SourceService'; import { ErrorDetailer, MetaTransferObject, @@ -6,12 +6,12 @@ import { SourceTransformationResponse, } from '../../types/index'; import { FixMe } from '../../util/types'; -import PostTransformationServiceSource from './postTransformation'; -import FetchHandler from '../../helpers/fetchHandlers'; +import { SourcePostTransformationService } from './postTransformation'; +import { FetchHandler } from '../../helpers/fetchHandlers'; import tags from '../../v0/util/tags'; import stats from '../../util/stats'; -export default class NativeIntegrationSourceService implements IntegrationSourceService { +export class NativeIntegrationSourceService implements SourceService { public getTags(): MetaTransferObject { const metaTO = { errorDetails: { @@ -38,14 +38,14 @@ export default class NativeIntegrationSourceService implements IntegrationSource try { const respEvents: RudderMessage | RudderMessage[] | SourceTransformationResponse = await sourceHandler.process(sourceEvent); - return PostTransformationServiceSource.handleSuccessEventsSource(respEvents); + return SourcePostTransformationService.handleSuccessEventsSource(respEvents); } catch (error: FixMe) { const metaTO = this.getTags(); stats.increment('source_transform_errors', { - sourceType, + source: sourceType, version, }); - return PostTransformationServiceSource.handleFailureEventsSource(error, metaTO); + return SourcePostTransformationService.handleFailureEventsSource(error, metaTO); } }), ); diff --git a/src/services/source/postTransformation.ts b/src/services/source/postTransformation.ts index f732cac3a7..20c815171b 100644 --- a/src/services/source/postTransformation.ts +++ b/src/services/source/postTransformation.ts @@ -1,9 +1,9 @@ import { MetaTransferObject, RudderMessage, SourceTransformationResponse } from '../../types/index'; import { CatchErr } from '../../util/types'; import { generateErrorObject } from '../../v0/util'; -import ErrorReportingService from '../errorReporting'; +import { ErrorReportingService } from '../errorReporting'; -export default class PostTransformationSourceService { +export class SourcePostTransformationService { public static handleFailureEventsSource( error: CatchErr, metaTO: MetaTransferObject, diff --git a/src/services/trackingPlan.ts b/src/services/trackingPlan.ts index 35f21320a5..2e68df55e9 100644 --- a/src/services/trackingPlan.ts +++ b/src/services/trackingPlan.ts @@ -4,7 +4,7 @@ import { getMetadata } from '../v0/util'; import eventValidator from '../util/eventValidation'; import stats from '../util/stats'; -export default class TrackingPlanservice { +export class TrackingPlanservice { public static async validateTrackingPlan(events, requestSize, reqParams) { const requestStartTime = new Date(); const respList: any[] = []; diff --git a/src/services/userTransform.ts b/src/services/userTransform.ts index 18165615a8..bf34e3d82a 100644 --- a/src/services/userTransform.ts +++ b/src/services/userTransform.ts @@ -24,7 +24,7 @@ import { CatchErr, FixMe } from '../util/types'; import { FeatureFlags, FEATURE_FILTER_CODE } from '../middlewares/featureFlag'; import { HTTP_CUSTOM_STATUS_CODES } from '../constants'; -export default class UserTransformService { +export class UserTransformService { public static async transformRoutine( events: ProcessorTransformationRequest[], features: FeatureFlags = {}, @@ -65,6 +65,7 @@ export default class UserTransformService { sourceId: eventsToProcess[0]?.metadata?.sourceId, destinationId: eventsToProcess[0]?.metadata.destinationId, destinationType: eventsToProcess[0]?.metadata.destinationType, + workspaceId: eventsToProcess[0]?.metadata.workspaceId, messageIds, }; @@ -85,9 +86,6 @@ export default class UserTransformService { } const userFuncStartTime = new Date(); try { - stats.counter('user_transform_function_input_events', eventsToProcess.length, { - ...metaTags, - }); const destTransformedEvents: UserTransformationResponse[] = await userTransformHandler()( eventsToProcess, transformationVersionId, diff --git a/src/types/index.ts b/src/types/index.ts index 79efaecb40..f4432e5c2a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -16,9 +16,46 @@ type ProcessorTransformationOutput = { FORM?: Record; }; files?: Record; - metadata?: Metadata; }; +type ProxyDeliveryRequest = { + version: string; + type: string; + method: string; + endpoint: string; + userId: string; + headers?: Record; + params?: Record; + body?: { + JSON?: Record; + JSON_ARRAY?: Record; + XML?: Record; + FORM?: Record; + }; + files?: Record; + metadata: Metadata; +}; + +type ProxyDeliveriesRequest = { + version: string; + type: string; + method: string; + endpoint: string; + userId: string; + headers?: Record; + params?: Record; + body?: { + JSON?: Record; + JSON_ARRAY?: Record; + XML?: Record; + FORM?: Record; + }; + files?: Record; + metadata: Metadata[]; +}; + +type ProxyRequest = ProxyDeliveryRequest | ProxyDeliveriesRequest; + type Metadata = { sourceId: string; workspaceId: string; @@ -50,6 +87,7 @@ type Metadata = { sourceDefinitionId: string; destinationDefinitionId: string; transformationId: string; + dontBatch?: boolean; }; type MessageIdMetadataMap = { @@ -142,6 +180,20 @@ type DeliveryResponse = { authErrorCategory?: string; }; +type DeliveryJobState = { + error: string; + statusCode: number; + metadata: Metadata; +}; + +type DeliveriesResponse = { + status?: number; + message?: string; + statTags?: object; + authErrorCategory?: string; + response: DeliveryJobState[]; +}; + enum MessageType { IDENTIFY = 'identify', TRACK = 'track', @@ -224,26 +276,60 @@ type ComparatorInput = { requestMetadata: object; feature: string; }; +type SourceDefinition = { + ID: string; + Name: string; + Category: string; + Type: string; +}; +type Source = { + ID: string; + OriginalID: string; + Name: string; + SourceDefinition: SourceDefinition; + Config: object; + Enabled: boolean; + WorkspaceID: string; + WriteKey: string; + Transformations?: UserTransformationInput[]; + RevisionID?: string; + Destinations?: Destination[]; + Transient: boolean; + EventSchemasEnabled: boolean; + DgSourceTrackingPlanConfig: object; +}; + +type SourceInput = { + event: NonNullable[]; + source?: Source; +}; export { - Metadata, + ComparatorInput, + DeliveryJobState, + DeliveryResponse, + DeliveriesResponse, + Destination, + ErrorDetailer, MessageIdMetadataMap, - UserTransformationLibrary, + MetaTransferObject, + Metadata, + ProcessorTransformationOutput, ProcessorTransformationRequest, ProcessorTransformationResponse, + ProxyDeliveriesRequest, + ProxyDeliveryRequest, + ProxyRequest, RouterTransformationRequest, RouterTransformationRequestData, RouterTransformationResponse, RudderMessage, - ProcessorTransformationOutput, SourceTransformationResponse, - DeliveryResponse, - ErrorDetailer, - UserTransformationResponse, - UserTransformationServiceResponse, - MetaTransferObject, UserDeletionRequest, UserDeletionResponse, - Destination, - ComparatorInput, + SourceInput, + Source, + UserTransformationLibrary, + UserTransformationResponse, + UserTransformationServiceResponse, }; diff --git a/src/util/customTransformer-faas.js b/src/util/customTransformer-faas.js index d1fa48d2d1..2c0bbfd8c0 100644 --- a/src/util/customTransformer-faas.js +++ b/src/util/customTransformer-faas.js @@ -1,7 +1,7 @@ const { v4: uuidv4 } = require('uuid'); const crypto = require('crypto'); const NodeCache = require('node-cache'); -const { getMetadata } = require('../v0/util'); +const { getMetadata, getTransformationMetadata } = require('../v0/util'); const stats = require('./stats'); const { setupFaasFunction, @@ -24,8 +24,8 @@ function generateFunctionName(userTransformation, libraryVersionIds, testMode) { const ids = [userTransformation.workspaceId, userTransformation.versionId].concat( (libraryVersionIds || []).sort(), ); - const hash = crypto.createHash('md5').update(`${ids}`).digest('hex'); + const hash = crypto.createHash('md5').update(`${ids}`).digest('hex'); return `fn-${userTransformation.workspaceId}-${hash}`.substring(0, 63).toLowerCase(); } @@ -82,10 +82,10 @@ async function setOpenFaasUserTransform( libraryVersionIds, pregeneratedFnName, testMode = false, + trMetadata = {}, ) { const tags = { transformerVersionId: userTransformation.versionId, - language: userTransformation.language, identifier: 'openfaas', testMode, }; @@ -106,6 +106,7 @@ async function setOpenFaasUserTransform( testMode, ), testMode, + trMetadata, ); stats.timing('creation_time', setupTime, tags); @@ -126,24 +127,21 @@ async function runOpenFaasUserTransform( if (events.length === 0) { throw new Error('Invalid payload. No events'); } - const metaTags = events[0].metadata ? getMetadata(events[0].metadata) : {}; - const tags = { - transformerVersionId: userTransformation.versionId, - language: userTransformation.language, - identifier: 'openfaas', - testMode, - ...metaTags, - }; + const trMetadata = events[0].metadata ? getTransformationMetadata(events[0].metadata) : {}; // check and deploy faas function if not exists const functionName = generateFunctionName(userTransformation, libraryVersionIds, testMode); if (testMode) { - await setOpenFaasUserTransform(userTransformation, libraryVersionIds, functionName, testMode); + await setOpenFaasUserTransform( + userTransformation, + libraryVersionIds, + functionName, + testMode, + trMetadata, + ); } - const invokeTime = new Date(); - stats.counter('events_to_process', events.length, tags); - const result = await executeFaasFunction( + return await executeFaasFunction( functionName, events, userTransformation.versionId, @@ -156,9 +154,8 @@ async function runOpenFaasUserTransform( testMode, ), testMode, + trMetadata, ); - stats.timing('run_time', invokeTime, tags); - return result; } module.exports = { diff --git a/src/util/customTransformer-v1.js b/src/util/customTransformer-v1.js index 397281d8d9..60f8e493fa 100644 --- a/src/util/customTransformer-v1.js +++ b/src/util/customTransformer-v1.js @@ -1,7 +1,7 @@ const ivm = require('isolated-vm'); const { getFactory } = require('./ivmFactory'); -const { getMetadata } = require('../v0/util'); +const { getMetadata, getTransformationMetadata } = require('../v0/util'); const logger = require('../logger'); const stats = require('./stats'); @@ -54,63 +54,48 @@ async function userTransformHandlerV1( libraryVersionIds, testMode = false, ) { - /* - Removing pool usage to address memory leaks - Env variable ON_DEMAND_ISOLATE_VM is not being used anymore - */ - if (userTransformation.versionId) { - const metaTags = events.length && events[0].metadata ? getMetadata(events[0].metadata) : {}; - const tags = { - transformerVersionId: userTransformation.versionId, - identifier: 'v1', - ...metaTags, - }; - - logger.debug(`Isolate VM being created... `); - const isolatevmFactory = await getFactory( - userTransformation.code, - libraryVersionIds, - userTransformation.versionId, - userTransformation.secrets || {}, - testMode, - ); - const isolatevm = await isolatevmFactory.create(); - logger.debug(`Isolate VM created... `); + if (!userTransformation.versionId) { + return { transformedEvents : events }; + } - // Transform the event... - stats.counter('events_to_process', events.length, tags); - const isolateStartWallTime = calculateMsFromIvmTime(isolatevm.isolateStartWallTime); - const isolateStartCPUTime = calculateMsFromIvmTime(isolatevm.isolateStartCPUTime); + const isolatevmFactory = await getFactory( + userTransformation.code, + libraryVersionIds, + userTransformation.versionId, + userTransformation.secrets || {}, + testMode, + ); - const invokeTime = new Date(); - let transformedEvents; - // Destroy isolatevm in case of execution errors - try { - transformedEvents = await transform(isolatevm, events); - } catch (err) { - logger.error(`Error encountered while executing transformation: ${err.message}`); - isolatevmFactory.destroy(isolatevm); - throw err; - } - const { logs } = isolatevm; - stats.timing('run_time', invokeTime, tags); - const isolateEndWallTime = calculateMsFromIvmTime(isolatevm.isolate.wallTime); - const isolateEndCPUTime = calculateMsFromIvmTime(isolatevm.isolate.cpuTime); + logger.debug(`Creating IsolateVM`); + const isolatevm = await isolatevmFactory.create(); - //TODO: fix "Value is not a valid number: NaN" error and uncomment - //stats.timing('isolate_wall_time', isolateEndWallTime - isolateStartWallTime, tags); - //stats.timing('isolate_cpu_time', isolateEndCPUTime - isolateStartCPUTime, tags); + const invokeTime = new Date(); + let transformedEvents; + let logs; + let transformationError; - // Destroy the isolated vm resources created - logger.debug(`Isolate VM being destroyed... `); + try { + transformedEvents = await transform(isolatevm, events); + logs = isolatevm.logs; + } catch (err) { + logger.error(`Error encountered while executing transformation: ${err.message}`); + transformationError = err; + throw err; + } finally { + logger.debug(`Destroying IsolateVM`); isolatevmFactory.destroy(isolatevm); - logger.debug(`Isolate VM destroyed... `); - - return { transformedEvents, logs }; - // Events contain message and destination. We take the message part of event and run transformation on it. - // And put back the destination after transforrmation + // send the observability stats + const tags = { + identifier: 'v1', + errored: transformationError ? true : false, + ...events.length && events[0].metadata ? getMetadata(events[0].metadata) : {}, + ...events.length && events[0].metadata ? getTransformationMetadata(events[0].metadata) : {} + } + stats.counter('user_transform_function_input_events', events.length, tags); + stats.timing('user_transform_function_latency', invokeTime, tags); } - return { transformedEvents: events }; + + return { transformedEvents, logs }; } async function setUserTransformHandlerV1() { diff --git a/src/util/customTransformer.js b/src/util/customTransformer.js index 90dcea61b2..001fe3216c 100644 --- a/src/util/customTransformer.js +++ b/src/util/customTransformer.js @@ -7,6 +7,7 @@ const { UserTransformHandlerFactory } = require('./customTransformerFactory'); const { parserForImport } = require('./parser'); const stats = require('./stats'); const { fetchWithDnsWrapper } = require('./utils'); +const { getMetadata, getTransformationMetadata } = require('../v0/util'); const ISOLATE_VM_MEMORY = parseInt(process.env.ISOLATE_VM_MEMORY || '128', 10); const GEOLOCATION_TIMEOUT_IN_MS = parseInt(process.env.GEOLOCATION_TIMEOUT_IN_MS || '1000', 10); @@ -19,10 +20,6 @@ async function runUserTransform( versionId, testMode = false, ) { - const tags = { - transformerVersionId: versionId, - identifier: 'v0', - }; // TODO: Decide on the right value for memory limit const isolate = new ivm.Isolate({ memoryLimit: ISOLATE_VM_MEMORY }); const context = await isolate.createContext(); @@ -214,9 +211,6 @@ async function runUserTransform( const customScript = await isolate.compileScript(`${code}`); await customScript.run(context); const fnRef = await jail.get('transform', { reference: true }); - // stat - stats.counter('events_to_process', events.length, tags); - // TODO : check if we can resolve this // eslint-disable-next-line no-async-promise-executor const executionPromise = new Promise(async (resolve, reject) => { const sharedMessagesList = new ivm.ExternalCopy(events).copyInto({ @@ -233,6 +227,7 @@ async function runUserTransform( } }); let result; + let transformationError; const invokeTime = new Date(); try { const timeoutPromise = new Promise((resolve) => { @@ -245,8 +240,8 @@ async function runUserTransform( if (result === 'Timedout') { throw new Error('Timed out'); } - stats.timing('run_time', invokeTime, tags); } catch (error) { + transformationError = error; throw error; } finally { // release function, script, context and isolate @@ -255,6 +250,16 @@ async function runUserTransform( bootstrapScriptResult.release(); context.release(); isolate.dispose(); + + const tags = { + identifier: 'v0', + errored: transformationError ? true : false, + ...events.length && events[0].metadata ? getMetadata(events[0].metadata) : {}, + ...events.length && events[0].metadata ? getTransformationMetadata(events[0].metadata) : {} + } + + stats.counter('user_transform_function_input_events', events.length, tags); + stats.timing('user_transform_function_latency', invokeTime, tags); } return { diff --git a/src/util/customTransformerFactory.js b/src/util/customTransformerFactory.js index 66268db286..1bf10e5d45 100644 --- a/src/util/customTransformerFactory.js +++ b/src/util/customTransformerFactory.js @@ -1,9 +1,15 @@ -const { setOpenFaasUserTransform, runOpenFaasUserTransform } = require('./customTransformer-faas'); +const { + setOpenFaasUserTransform, + runOpenFaasUserTransform, +} = require('./customTransformer-faas'); -const { userTransformHandlerV1, setUserTransformHandlerV1 } = require('./customTransformer-v1'); +const { + userTransformHandlerV1, + setUserTransformHandlerV1, +} = require('./customTransformer-v1'); const UserTransformHandlerFactory = (userTransformation) => { - const transformHandler = { + return { setUserTransform: async (libraryVersionIds) => { switch (userTransformation.language) { case 'pythonfaas': @@ -17,13 +23,23 @@ const UserTransformHandlerFactory = (userTransformation) => { switch (userTransformation.language) { case 'pythonfaas': case 'python': - return runOpenFaasUserTransform(events, userTransformation, libraryVersionIds, testMode); + return runOpenFaasUserTransform( + events, + userTransformation, + libraryVersionIds, + testMode + ); + default: - return userTransformHandlerV1(events, userTransformation, libraryVersionIds, testMode); + return userTransformHandlerV1( + events, + userTransformation, + libraryVersionIds, + testMode + ); } }, }; - return transformHandler; }; exports.UserTransformHandlerFactory = UserTransformHandlerFactory; diff --git a/src/util/dynamicConfigParser.ts b/src/util/dynamicConfigParser.ts index 73ad85a0d2..6de2e38f94 100644 --- a/src/util/dynamicConfigParser.ts +++ b/src/util/dynamicConfigParser.ts @@ -6,7 +6,7 @@ import { FixMe } from './types'; const get = require('get-value'); const unset = require('unset-value'); -export default class DynamicConfigParser { +export class DynamicConfigParser { private static getDynamicConfigValue( event: ProcessorTransformationRequest | RouterTransformationRequestData, value: FixMe, diff --git a/src/util/errorNotifier/bugsnag.js b/src/util/errorNotifier/bugsnag.js index a88432f23d..ef01c58730 100644 --- a/src/util/errorNotifier/bugsnag.js +++ b/src/util/errorNotifier/bugsnag.js @@ -5,9 +5,6 @@ const { DataValidationError, } = require('rudder-transformer-cdk/build/error/index'); const stackTraceParser = require('stacktrace-parser'); -const { logger } = require('../../logger'); -const pkg = require('../../../package.json'); - const { BaseError, TransformationError, @@ -23,8 +20,10 @@ const { UnhandledStatusCodeError, UnauthorizedError, NetworkInstrumentationError, - FilteredEventsError, -} = require('../../v0/util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const { FilteredEventsError } = require('../../v0/util/errorTypes'); +const { logger } = require('../../logger'); +const pkg = require('../../../package.json'); const { BUGSNAG_API_KEY: apiKey, diff --git a/src/util/openfaas/index.js b/src/util/openfaas/index.js index 60ad316e1b..878fa706d9 100644 --- a/src/util/openfaas/index.js +++ b/src/util/openfaas/index.js @@ -1,6 +1,5 @@ const NodeCache = require('node-cache'); const { - getFunction, deleteFunction, deployFunction, invokeFunction, @@ -8,6 +7,9 @@ const { } = require('./faasApi'); const logger = require('../../logger'); const { RetryRequestError, RespStatusError } = require('../utils'); +const stats = require('../stats'); +const { getMetadata, getTransformationMetadata } = require('../../v0/util'); +const { HTTP_STATUS_CODES } = require('../../v0/util/constant'); const FAAS_BASE_IMG = process.env.FAAS_BASE_IMG || 'rudderlabs/openfaas-flask:main'; const FAAS_MAX_PODS_IN_TEXT = process.env.FAAS_MAX_PODS_IN_TEXT || '40'; @@ -23,6 +25,8 @@ const CONFIG_BACKEND_URL = process.env.CONFIG_BACKEND_URL || 'https://api.rudder const GEOLOCATION_URL = process.env.GEOLOCATION_URL || ''; const FAAS_AST_VID = 'ast'; const FAAS_AST_FN_NAME = 'fn-ast'; +const CUSTOM_NETWORK_POLICY_WORKSPACE_IDS = process.env.CUSTOM_NETWORK_POLICY_WORKSPACE_IDS || ''; +const customNetworkPolicyWorkspaceIds = CUSTOM_NETWORK_POLICY_WORKSPACE_IDS.split(','); // Initialise node cache const functionListCache = new NodeCache(); @@ -111,7 +115,14 @@ const invalidateFnCache = () => { functionListCache.set(FUNC_LIST_KEY, []); }; -const deployFaasFunction = async (functionName, code, versionId, libraryVersionIDs, testMode) => { +const deployFaasFunction = async ( + functionName, + code, + versionId, + libraryVersionIDs, + testMode, + trMetadata = {}, +) => { try { logger.debug('[Faas] Deploying a faas function'); let envProcess = 'python index.py'; @@ -132,6 +143,22 @@ const deployFaasFunction = async (functionName, code, versionId, libraryVersionI if (GEOLOCATION_URL) { envVars.geolocation_url = GEOLOCATION_URL; } + // labels + const labels = { + 'openfaas-fn': 'true', + 'parent-component': 'openfaas', + 'com.openfaas.scale.max': FAAS_MAX_PODS_IN_TEXT, + 'com.openfaas.scale.min': FAAS_MIN_PODS_IN_TEXT, + transformationId: trMetadata.transformationId, + workspaceId: trMetadata.workspaceId, + }; + if ( + trMetadata.workspaceId && + customNetworkPolicyWorkspaceIds.includes(trMetadata.workspaceId) + ) { + labels['custom-network-policy'] = 'true'; + } + // TODO: investigate and add more required labels and annotations const payload = { service: functionName, @@ -139,12 +166,7 @@ const deployFaasFunction = async (functionName, code, versionId, libraryVersionI image: FAAS_BASE_IMG, envProcess, envVars, - labels: { - 'openfaas-fn': 'true', - 'parent-component': 'openfaas', - 'com.openfaas.scale.max': FAAS_MAX_PODS_IN_TEXT, - 'com.openfaas.scale.min': FAAS_MIN_PODS_IN_TEXT, - }, + labels, annotations: { 'prometheus.io.scrape': 'true', }, @@ -175,14 +197,28 @@ const deployFaasFunction = async (functionName, code, versionId, libraryVersionI } }; -async function setupFaasFunction(functionName, code, versionId, libraryVersionIDs, testMode) { +async function setupFaasFunction( + functionName, + code, + versionId, + libraryVersionIDs, + testMode, + trMetadata = {}, +) { try { if (!testMode && isFunctionDeployed(functionName)) { logger.debug(`[Faas] Function ${functionName} already deployed`); return; } // deploy faas function - await deployFaasFunction(functionName, code, versionId, libraryVersionIDs, testMode); + await deployFaasFunction( + functionName, + code, + versionId, + libraryVersionIDs, + testMode, + trMetadata, + ); // This api call is only used to check if function is spinned correctly await awaitFunctionReadiness(functionName); @@ -196,33 +232,33 @@ async function setupFaasFunction(functionName, code, versionId, libraryVersionID } const executeFaasFunction = async ( - functionName, + name, events, versionId, libraryVersionIDs, testMode, + trMetadata = {}, ) => { - try { - logger.debug('[Faas] Invoking faas function'); + logger.debug(`Executing faas function: ${name}`); - if (testMode) await awaitFunctionReadiness(functionName); + const startTime = new Date(); + let errorRaised; - const res = await invokeFunction(functionName, events); - logger.debug('[Faas] Invoked faas function'); - return res; + try { + if (testMode) await awaitFunctionReadiness(name); + return await invokeFunction(name, events); } catch (error) { - logger.error(`[Faas] Error while invoking ${functionName}: ${error.message}`); - if ( - error.statusCode === 404 && - error.message.includes(`error finding function ${functionName}`) - ) { - removeFunctionFromCache(functionName); - await setupFaasFunction(functionName, null, versionId, libraryVersionIDs, testMode); - throw new RetryRequestError(`${functionName} not found`); + logger.error(`Error while invoking ${name}: ${error.message}`); + errorRaised = error; + + if (error.statusCode === 404 && error.message.includes(`error finding function ${name}`)) { + removeFunctionFromCache(name); + await setupFaasFunction(name, null, versionId, libraryVersionIDs, testMode, trMetadata); + throw new RetryRequestError(`${name} not found`); } if (error.statusCode === 429) { - throw new RetryRequestError(`Rate limit exceeded for ${functionName}`); + throw new RetryRequestError(`Rate limit exceeded for ${name}`); } if (error.statusCode === 500 || error.statusCode === 503) { @@ -230,16 +266,30 @@ const executeFaasFunction = async ( } if (error.statusCode === 504) { - throw new RespStatusError('Timed out'); + throw new RespStatusError(`${name} timed out`, 504); } throw error; } finally { + // delete the function created, if it's called as part of testMode if (testMode) { - deleteFunction(functionName).catch((err) => { - logger.error(`[Faas] Error while deleting ${functionName}: ${err.message}`); - }); + deleteFunction(name).catch((err) => + logger.error(`[Faas] Error while deleting ${name}: ${err.message}`), + ); } + + // setup the tags for observability and then fire the stats + const tags = { + identifier: 'openfaas', + testMode: testMode, + errored: errorRaised ? true : false, + statusCode: errorRaised ? errorRaised.statusCode : HTTP_STATUS_CODES.OK, // default statuscode is 200OK + ...(events.length && events[0].metadata ? getMetadata(events[0].metadata) : {}), + ...(events.length && events[0].metadata ? getTransformationMetadata(events[0].metadata) : {}), + }; + + stats.counter('user_transform_function_input_events', events.length, tags); + stats.timing('user_transform_function_latency', startTime, tags); } }; diff --git a/src/util/prometheus.js b/src/util/prometheus.js index 9f3255a05d..d7ba3b7c61 100644 --- a/src/util/prometheus.js +++ b/src/util/prometheus.js @@ -249,12 +249,6 @@ class Prometheus { type: 'counter', labelNames: ['processSessions'], }, - { - name: 'user_transform_function_input_events', - help: 'user_transform_function_input_events', - type: 'counter', - labelNames: ['processSessions', 'sourceType', 'destinationType', 'k8_namespace'], - }, { name: 'user_transform_errors', help: 'user_transform_errors', @@ -457,6 +451,12 @@ class Prometheus { type: 'counter', labelNames: ['writeKey', 'timestamp'], }, + { + name: 'regulation_worker_user_deletion_failure', + help: 'regulation_worker_user_deletion_failure', + type: 'counter', + labelNames: ['destType', 'module', 'implementation', 'feature'], + }, { name: 'shopify_server_side_identifier_event', help: 'shopify_server_side_identifier_event', @@ -493,6 +493,12 @@ class Prometheus { type: 'counter', labelNames: ['type', 'writeKey', 'source'], }, + { + name: 'shopify_anon_id_resolve', + help: 'shopify_anon_id_resolve', + type: 'counter', + labelNames: ['method', 'writeKey', 'shopifyTopic'], + }, { name: 'shopify_redis_calls', help: 'shopify_redis_calls', @@ -505,20 +511,6 @@ class Prometheus { type: 'counter', labelNames: ['writeKey', 'source'], }, - { - name: 'events_to_process', - help: 'events_to_process', - type: 'counter', - labelNames: [ - 'transformerVersionId', - 'language', - 'identifier', - 'testMode', - 'sourceType', - 'destinationType', - 'k8_namespace', - ], - }, { name: 'get_transformation_code', help: 'get_transformation_code', @@ -619,6 +611,12 @@ class Prometheus { type: 'histogram', labelNames: ['sourceType', 'destinationType', 'k8_namespace'], }, + { + name: 'regulation_worker_requests_dest_latency', + help: 'regulation_worker_requests_dest_latency', + type: 'histogram', + labelNames: ['feature', 'implementation', 'destType'], + }, { name: 'dest_transform_request_latency', help: 'dest_transform_request_latency', @@ -668,21 +666,6 @@ class Prometheus { type: 'histogram', labelNames: ['transformerVersionId', 'language', 'identifier', 'publish', 'testMode'], }, - { - name: 'run_time', - help: 'run_time', - type: 'histogram', - labelNames: [ - 'transformerVersionId', - 'language', - 'identifier', - 'publish', - 'testMode', - 'sourceType', - 'destinationType', - 'k8_namespace', - ], - }, { name: 'get_tracking_plan', help: 'get_tracking_plan', type: 'histogram', labelNames: [] }, { name: 'createivm_duration', help: 'createivm_duration', type: 'histogram', labelNames: [] }, { @@ -940,6 +923,38 @@ class Prometheus { type: 'histogram', labelNames: [], }, + { + name: 'user_transform_function_input_events', + help: 'user_transform_function_input_events', + type: 'counter', + labelNames: [ + 'identifier', + 'testMode', + 'sourceType', + 'destinationType', + 'k8_namespace', + 'errored', + 'statusCode', + 'transformationId', + 'workspaceId', + ], + }, + { + name: 'user_transform_function_latency', + help: 'user_transform_function_latency', + type: 'histogram', + labelNames: [ + 'identifier', + 'testMode', + 'sourceType', + 'destinationType', + 'k8_namespace', + 'errored', + 'statusCode', + 'transformationId', + 'workspaceId', + ], + }, ]; metrics.forEach((metric) => { diff --git a/src/util/redis/redisConnector.js b/src/util/redis/redisConnector.js index 749e23ff83..84d578d3b3 100644 --- a/src/util/redis/redisConnector.js +++ b/src/util/redis/redisConnector.js @@ -1,5 +1,5 @@ const Redis = require('ioredis'); -const { RedisError } = require('../../v0/util/errorTypes'); +const { RedisError } = require('@rudderstack/integrations-lib'); const log = require('../../logger'); const stats = require('../stats'); diff --git a/src/util/stats.js b/src/util/stats.js index de77362ac1..e57ab85731 100644 --- a/src/util/stats.js +++ b/src/util/stats.js @@ -11,14 +11,19 @@ function init() { return; } - if (statsClientType === 'statsd') { - statsClient = new statsd.Statsd(); - logger.info('created statsd client'); - } else if (statsClientType === 'prometheus') { - statsClient = new prometheus.Prometheus(); - logger.info('created prometheus client'); - } else { - logger.info("Invalid stats client type. Valid values are 'statsd' and 'prometheus'."); + switch (statsClientType) { + case 'statsd': + logger.info("setting up statsd client") + statsClient = new statsd.Statsd(); + break; + + case 'prometheus': + logger.info("setting up prometheus client") + statsClient = new prometheus.Prometheus(); + break; + + default: + logger.error(`invalid stats client type: ${statsClientType}, supported values are 'statsd' and 'prometheues'`) } } diff --git a/src/util/trackingPlan.js b/src/util/trackingPlan.js index 0c03820308..a77265a5b8 100644 --- a/src/util/trackingPlan.js +++ b/src/util/trackingPlan.js @@ -4,7 +4,7 @@ const logger = require('../logger'); const { responseStatusHandler } = require('./utils'); const stats = require('./stats'); -const tpCache = new NodeCache(); +const tpCache = new NodeCache({ useClones: false }); const CONFIG_BACKEND_URL = process.env.CONFIG_BACKEND_URL || 'https://api.rudderlabs.com'; const TRACKING_PLAN_URL = `${CONFIG_BACKEND_URL}/workspaces`; diff --git a/src/v0/destinations/active_campaign/transform.js b/src/v0/destinations/active_campaign/transform.js index 9c6643ebc3..70caf47ea8 100644 --- a/src/v0/destinations/active_campaign/transform.js +++ b/src/v0/destinations/active_campaign/transform.js @@ -1,6 +1,7 @@ /* eslint-disable array-callback-return */ /* eslint-disable no-empty */ const get = require('get-value'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, getHeader } = require('./config'); const { @@ -12,13 +13,6 @@ const { } = require('../../util'); const { errorHandler } = require('./util'); const { httpGET, httpPOST } = require('../../../adapters/network'); -const { - InstrumentationError, - TransformationError, - NetworkError, -} = require('../../util/errorTypes'); -const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const tags = require('../../util/tags'); const TOTAL_RECORDS_KEY = 'response.data.meta.total'; const EVENT_DATA_KEY = 'properties.eventData'; @@ -68,18 +62,11 @@ const syncContact = async (contactPayload, category, destination) => { feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to create new contact'); + errorHandler(res, 'Failed to create new contact'); } const createdContact = get(res, 'response.data.contact'); // null safe if (!createdContact) { - throw new NetworkError( - 'Unable to Create Contact', - res.response?.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(res.response?.status), - }, - res.response, - ); + errorHandler(res, 'Failed to create new contact'); } return createdContact.id; }; @@ -111,7 +98,7 @@ const customTagProcessor = async (message, category, destination, contactId) => feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to fetch already created tags'); + errorHandler(res, 'Failed to fetch already created tags'); } const storedTags = {}; @@ -182,7 +169,7 @@ const customTagProcessor = async (message, category, destination, contactId) => feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to create new tag'); + errorHandler(res, 'Failed to create new tag'); // For each tags successfully created the response id is pushed to tagIds } if (res.response.status === 201) tagIds.push(res.response.data.tag.id); @@ -214,7 +201,7 @@ const customTagProcessor = async (message, category, destination, contactId) => ); responsesArr.forEach((respItem) => { if (respItem.success === false) - errorHandler(respItem.response, 'Failed to merge created contact with created tags'); + errorHandler(respItem, 'Failed to merge created contact with created tags'); }); }; @@ -232,7 +219,7 @@ const customFieldProcessor = async (message, category, destination) => { // Step - 2 // Get the existing field data from dest and store it in responseStaging // Ref - https://developers.activecampaign.com/reference/retrieve-fields - let endpoint = `${destination.Config.apiUrl}${`${category.fieldEndPoint}?limit=100`}`; + let endpoint = `${destination.Config.apiUrl}${category.fieldEndPoint}?limit=100`; const requestOptions = { headers: { 'Api-Token': destination.Config.apiKey, @@ -243,7 +230,7 @@ const customFieldProcessor = async (message, category, destination) => { feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to get existing field data'); + errorHandler(res, 'Failed to get existing field data'); } responseStaging.push(res.response.status === 200 ? res.response.data.fields : []); @@ -270,7 +257,7 @@ const customFieldProcessor = async (message, category, destination) => { if (resp.success === true && resp.response.status === 200) { responseStaging.push(resp.response.data.fields); } else { - errorHandler(resp.response, 'Failed to get existing field data'); + errorHandler(resp, 'Failed to get existing field data'); } }); } @@ -365,7 +352,7 @@ const customListProcessor = async (message, category, destination, contactId) => const responses = await Promise.all(promises); responses.forEach((respItem) => { if (respItem.success === false) { - errorHandler(respItem.response, 'Failed to map created contact with the list'); + errorHandler(respItem, 'Failed to map created contact with the list'); } }); }; @@ -417,18 +404,11 @@ const screenRequestHandler = async (message, category, destination) => { feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to retrieve events'); + errorHandler(res, 'Failed to retrieve events'); } if (res?.response?.status !== 200) { - throw new NetworkError( - 'Unable to create event', - res.response?.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(res.response?.status), - }, - res.response, - ); + errorHandler(res, 'Unable to create event'); } const storedEventsArr = res.response?.data?.eventTrackingEvents; @@ -451,18 +431,11 @@ const screenRequestHandler = async (message, category, destination) => { feature: 'transformation', }); if (res.success === false) { - errorHandler(res.response, 'Failed to create event'); + errorHandler(res, 'Failed to create event'); } if (res.response.status !== 201) { - throw new NetworkError( - 'Unable to create event', - res.response.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(res.response.status), - }, - res?.response, - ); + errorHandler(res, 'Unable to create event'); } } // Previous operations successfull then @@ -495,18 +468,11 @@ const trackRequestHandler = async (message, category, destination) => { }); if (res.success === false) { - errorHandler(res.response, 'Failed to retrieve events'); + errorHandler(res, 'Failed to retrieve events'); } if (res.response.status !== 200) { - throw new NetworkError( - 'Unable to fetch events. Aborting', - res.response.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(res.response.status), - }, - res?.response, - ); + errorHandler(res, 'Unable to fetch events. Aborting'); } const storedEventsArr = res.response?.data?.eventTrackingEvents; @@ -529,14 +495,7 @@ const trackRequestHandler = async (message, category, destination) => { feature: 'transformation', }); if (res.response?.status !== 201) { - throw new NetworkError( - 'Unable to create event. Aborting', - res.response.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(res.response.status), - }, - res.response, - ); + errorHandler(res, 'Unable to create event. Aborting'); } } diff --git a/src/v0/destinations/active_campaign/util.js b/src/v0/destinations/active_campaign/util.js index c508618336..40e15f95b3 100644 --- a/src/v0/destinations/active_campaign/util.js +++ b/src/v0/destinations/active_campaign/util.js @@ -1,31 +1,24 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { - nodeSysErrorToStatus, getDynamicErrorType, + processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); -const errorHandler = (err, message) => { - if (err.response) { - throw new NetworkError( - `${message} (${err.response?.statusText},${JSON.stringify(err.response?.data)})`, - err.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(err.status), - }, - err, - ); - } else { - const httpError = nodeSysErrorToStatus(err.code); - throw new NetworkError( - `${message} ${httpError.message}`, - httpError.status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(httpError.status), - }, - err, - ); +const errorHandler = (httpCallError, message) => { + const { response, status } = processAxiosResponse(httpCallError); + let msg = message; + if (response) { + msg = `${message} (${httpCallError.response?.statusText},${JSON.stringify(response)})`; } + throw new NetworkError( + msg, + status, + { + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), + }, + response, + ); }; const offsetLimitVarPath = 'response.data.meta.total'; diff --git a/src/v0/destinations/adj/transform.js b/src/v0/destinations/adj/transform.js index 695654e58a..8248e731c9 100644 --- a/src/v0/destinations/adj/transform.js +++ b/src/v0/destinations/adj/transform.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + InstrumentationError, + TransformationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, baseEndpoint } = require('./config'); const { @@ -11,11 +16,6 @@ const { isAppleFamily, simpleProcessRouterDest, } = require('../../util'); -const { - InstrumentationError, - TransformationError, - ConfigurationError, -} = require('../../util/errorTypes'); const rejectParams = ['revenue', 'currency']; diff --git a/src/v0/destinations/adobe_analytics/config.js b/src/v0/destinations/adobe_analytics/config.js index 7a66b32a48..ed5852f5a5 100644 --- a/src/v0/destinations/adobe_analytics/config.js +++ b/src/v0/destinations/adobe_analytics/config.js @@ -44,4 +44,5 @@ module.exports = { ECOM_PRODUCT_EVENTS, commonConfig: MAPPING_CONFIG[CONFIG_CATEGORIES.COMMON.name], formatDestinationConfig, + DESTINATION: 'ADOBE_ANALYTICS', }; diff --git a/src/v0/destinations/adobe_analytics/networkHandler.js b/src/v0/destinations/adobe_analytics/networkHandler.js new file mode 100644 index 0000000000..0ec1fad286 --- /dev/null +++ b/src/v0/destinations/adobe_analytics/networkHandler.js @@ -0,0 +1,55 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); +const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); +const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); +const { DESTINATION } = require('./config'); + +/** + * Extract data inside different tags from an xml payload + * @param {*} xml + * @param {*} tagName + * @returns data inside the tagName + */ +function extractContent(xmlPayload, tagName) { + const pattern = new RegExp(`<${tagName}>(.*?)`); + const match = xmlPayload.match(pattern); + return match ? match[1] : null; +} + +const responseHandler = (destinationResponse, dest) => { + const message = `[${DESTINATION}] - Request Processed Successfully`; + const { response, status } = destinationResponse; + + // Extract values between different tags + const responseStatus = extractContent(response, 'status'); + const reason = extractContent(response, 'reason'); + + // if the status tag in XML contains FAILURE, we build and throw an explicit error + if (responseStatus === 'FAILURE') { + if (reason) { + throw new InstrumentationError( + `[${DESTINATION} Response Handler] Request failed for destination ${dest} : ${reason}`, + ); + } else { + throw new InstrumentationError( + `[${DESTINATION} Response Handler] Request failed for destination ${dest} with a general error`, + ); + } + } + + return { + status, + message, + destinationResponse, + }; +}; + +function networkHandler() { + this.responseHandler = responseHandler; + this.proxy = proxyRequest; + this.prepareProxy = prepareProxyRequest; + this.processAxiosResponse = processAxiosResponse; +} + +module.exports = { + networkHandler, +}; diff --git a/src/v0/destinations/adobe_analytics/transform.js b/src/v0/destinations/adobe_analytics/transform.js index 54806bf578..b428138724 100644 --- a/src/v0/destinations/adobe_analytics/transform.js +++ b/src/v0/destinations/adobe_analytics/transform.js @@ -1,5 +1,10 @@ const jsonxml = require('jsontoxml'); const get = require('get-value'); +const { + InstrumentationError, + TransformationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ECOM_PRODUCT_EVENTS, commonConfig, formatDestinationConfig } = require('./config'); const { @@ -11,13 +16,9 @@ const { isDefinedAndNotNull, isDefinedAndNotNullAndNotEmpty, getIntegrationsObj, + removeUndefinedAndNullValues, simpleProcessRouterDest, } = require('../../util'); -const { - InstrumentationError, - TransformationError, - ConfigurationError, -} = require('../../util/errorTypes'); const { handleContextData, @@ -75,6 +76,7 @@ const responseBuilderSimple = async (message, destinationConfig, basicPayload) = } payload.linkURL = adobeIntegrationsObject?.linkURL || context?.page?.url || 'No linkURL provided'; + payload.linkURL = encodeURI(payload.linkURL); } // handle hier if (overrideHiers) { @@ -96,7 +98,7 @@ const responseBuilderSimple = async (message, destinationConfig, basicPayload) = const propertiesPageUrl = properties?.pageUrl; const pageUrl = contextPageUrl || propertiesPageUrl; if (isDefinedAndNotNullAndNotEmpty(pageUrl)) { - payload.pageUrl = pageUrl; + payload.pageUrl = encodeURI(pageUrl); } if (trackPageName) { // better handling possible here, both error and implementation wise @@ -344,6 +346,9 @@ const processTrackEvent = (message, adobeEventName, destinationConfig, extras = const handleTrack = (message, destinationConfig) => { const ORDER_ID_KEY = 'properties.order_id'; const { event: rawEvent, properties } = message; + if (!rawEvent) { + throw new InstrumentationError('Event name is not present. Aborting message.'); + } let payload = null; // handle ecommerce events separately // generic events should go to the default @@ -394,7 +399,7 @@ const handleTrack = (message, destinationConfig) => { break; } - return payload; + return removeUndefinedAndNullValues(payload); }; const process = async (event) => { diff --git a/src/v0/destinations/adobe_analytics/utils.js b/src/v0/destinations/adobe_analytics/utils.js index 55059884b1..97dc6e90bb 100644 --- a/src/v0/destinations/adobe_analytics/utils.js +++ b/src/v0/destinations/adobe_analytics/utils.js @@ -4,8 +4,8 @@ /* eslint-disable unicorn/no-for-loop */ /* eslint-disable no-restricted-syntax */ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isDefinedAndNotNull, getValueFromMessage } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const SOURCE_KEYS = ['properties', 'traits', 'context.traits', 'context']; @@ -75,6 +75,28 @@ function handleContextData(payload, destinationConfig, message) { return payload; } +/** + * This function is used for replacing '&', '<' and '>' with their respective HTML entities + * @param {*} inputString + * @returns string with HTML entities replaced + * + */ + +function escapeToHTML(inputString) { + if (typeof inputString !== 'string') { + return inputString; + } + return inputString.replace( + /[&<>]/g, + (match) => + ({ + '&': '&', + '<': '<', + '>': '>', + }[match]), + ); +} + /** * This function is used for populating the eVars and hVars in the payload * @param {*} destVarMapping @@ -90,16 +112,16 @@ function rudderPropToDestMap(destVarMapping, message, payload, destVarStrPrefix) let val = get(message, `properties.${key}`); if (isDefinedAndNotNull(val)) { const destVarKey = destVarStrPrefix + destVarMapping[key]; - mappedVar[destVarKey] = val; + mappedVar[destVarKey] = escapeToHTML(val); } else { SOURCE_KEYS.some((sourceKey) => { val = getMappingFieldValueFormMessage(message, sourceKey, key); if (isDefinedAndNotNull(val)) { - mappedVar[`${destVarStrPrefix}${[destVarMapping[key]]}`] = val; + mappedVar[`${destVarStrPrefix}${[destVarMapping[key]]}`] = escapeToHTML(val); } else { val = getValueByPath(message, key); if (isDefinedAndNotNull(val)) { - mappedVar[`${destVarStrPrefix}${[destVarMapping[key]]}`] = val; + mappedVar[`${destVarStrPrefix}${[destVarMapping[key]]}`] = escapeToHTML(val); } } }); @@ -147,13 +169,13 @@ function rudderPropToDestMapWithDelimitter(mapping, delimMapping, message, prefi `${prefix} mapping properties variable is neither a string nor an array`, ); } - + if (typeof val === 'string') { /* following regex is used to find the one or more commas separated/padded by white spaces. Example: val = 'r15,faze90R' , 'r1v, bvp, pol' */ - val = val.replace(/\s*,+\s*/g, delimMapping[key]); - // Above regex is good as for every comma with whitespace padding the no. of steps will increase by 4. + val = val.replace(/\s*,+\s*/g, delimMapping[key]); + // Above regex is good as for every comma with whitespace padding the no. of steps will increase by 4. } else { val = val.join(delimMapping[key]); } @@ -200,4 +222,5 @@ module.exports = { handleList, handleCustomProperties, stringifyValueAndJoinWithDelimiter, + escapeToHTML, }; diff --git a/src/v0/destinations/af/deleteUsers.js b/src/v0/destinations/af/deleteUsers.js index 7970d02c20..2d68549fcc 100644 --- a/src/v0/destinations/af/deleteUsers.js +++ b/src/v0/destinations/af/deleteUsers.js @@ -1,12 +1,16 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-param-reassign */ +const { + ConfigurationError, + InstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { generateUUID, isHttpStatusSuccess } = require('../../util'); -const { ConfigurationError, InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { executeCommonValidations } = require('../../util/regulation-api'); diff --git a/src/v0/destinations/af/transform.js b/src/v0/destinations/af/transform.js index 858adce147..4d7ed7e635 100644 --- a/src/v0/destinations/af/transform.js +++ b/src/v0/destinations/af/transform.js @@ -1,6 +1,7 @@ const get = require('get-value'); const set = require('set-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { removeUndefinedValues, @@ -15,7 +16,6 @@ const { isDefinedAndNotNullAndNotEmpty, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { Event, ENDPOINT, ConfigCategory, mappingConfig, nameToEventMap } = require('./config'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/airship/transform.js b/src/v0/destinations/airship/transform.js index a390ec8060..091c9b7f39 100644 --- a/src/v0/destinations/airship/transform.js +++ b/src/v0/destinations/airship/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -22,7 +23,6 @@ const { isEmptyObject, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const DEFAULT_ACCEPT_HEADER = 'application/vnd.urbanairship+json; version=3'; diff --git a/src/v0/destinations/algolia/transform.js b/src/v0/destinations/algolia/transform.js index c8b9be28dd..8e9cd57e8b 100644 --- a/src/v0/destinations/algolia/transform.js +++ b/src/v0/destinations/algolia/transform.js @@ -1,10 +1,10 @@ const set = require('set-value'); -const { EventType } = require('../../../constants'); const { InstrumentationError, ConfigurationError, PlatformError, -} = require('../../util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const { EventType } = require('../../../constants'); const { getValueFromMessage, constructPayload, diff --git a/src/v0/destinations/algolia/util.js b/src/v0/destinations/algolia/util.js index 89048f0e43..eddb4dc16d 100644 --- a/src/v0/destinations/algolia/util.js +++ b/src/v0/destinations/algolia/util.js @@ -1,5 +1,5 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const logger = require('../../../logger'); -const { InstrumentationError } = require('../../util/errorTypes'); const { EVENT_TYPES } = require('./config'); /** diff --git a/src/v0/destinations/am/config.js b/src/v0/destinations/am/config.js index 5e6fc06c27..3e51a67137 100644 --- a/src/v0/destinations/am/config.js +++ b/src/v0/destinations/am/config.js @@ -122,7 +122,8 @@ events.forEach((event) => { const DELETE_MAX_BATCH_SIZE = 100; const DESTINATION = 'amplitude'; const IDENTIFY_AM = '$identify'; - +const AMBatchSizeLimit = 20 * 1024 * 1024; // 20 MB +const AMBatchEventLimit = 500; // event size limit from sdk is 32KB => 15MB module.exports = { DESTINATION, Event, @@ -134,4 +135,6 @@ module.exports = { DELETE_MAX_BATCH_SIZE, batchEventsWithUserIdLengthLowerThanFive, IDENTIFY_AM, + AMBatchSizeLimit, + AMBatchEventLimit }; diff --git a/src/v0/destinations/am/deleteUsers.js b/src/v0/destinations/am/deleteUsers.js index c0402284b4..578c58fb5c 100644 --- a/src/v0/destinations/am/deleteUsers.js +++ b/src/v0/destinations/am/deleteUsers.js @@ -1,4 +1,5 @@ const btoa = require('btoa'); +const { ConfigurationError, NetworkError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const tags = require('../../util/tags'); const { @@ -6,7 +7,6 @@ const { getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); -const { ConfigurationError, NetworkError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const { DELETE_MAX_BATCH_SIZE } = require('./config'); const { getUserIdBatches } = require('../../util/deleteUserUtils'); diff --git a/src/v0/destinations/am/transform.js b/src/v0/destinations/am/transform.js index e6ccf585df..05a130d6e0 100644 --- a/src/v0/destinations/am/transform.js +++ b/src/v0/destinations/am/transform.js @@ -1,8 +1,10 @@ /* eslint-disable no-lonely-if */ /* eslint-disable no-nested-ternary */ /* eslint-disable no-param-reassign */ +const cloneDeep = require('lodash/cloneDeep'); const get = require('get-value'); const set = require('set-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType, SpecedTraits, @@ -26,6 +28,7 @@ const { isAppleFamily, isDefinedAndNotNullAndNotEmpty, simpleProcessRouterDest, + isValidInteger, } = require('../../util'); const { BASE_URL, @@ -34,17 +37,16 @@ const { mappingConfig, batchEventsWithUserIdLengthLowerThanFive, IDENTIFY_AM, + AMBatchSizeLimit, + AMBatchEventLimit, } = require('./config'); const tags = require('../../util/tags'); const AMUtils = require('./utils'); const logger = require('../../../logger'); -const { InstrumentationError } = require('../../util/errorTypes'); -const { JSON_MIME_TYPE } = require('../../util/constant'); -const AMBatchSizeLimit = 20 * 1024 * 1024; // 20 MB -const AMBatchEventLimit = 500; // event size limit from sdk is 32KB => 15MB +const { JSON_MIME_TYPE } = require('../../util/constant'); const EVENTS_KEY_PATH = 'body.JSON.events'; @@ -79,82 +81,96 @@ const aliasEndpoint = (destConfig) => { return retVal; }; -function handleSessionIdUnderRoot(message) { - const sessionId = get(message, 'session_id'); +const handleSessionIdUnderRoot = (sessionId) => { if (typeof sessionId === 'string') { - return sessionId.substr(sessionId.lastIndexOf(':') + 1, sessionId.length); + const extractedPart = sessionId.split(':').reverse(); + if (!isValidInteger(extractedPart[0])) return -1; + return Number(extractedPart[0]); } - return sessionId; -} + return Number(sessionId); +}; -function handleSessionIdUnderContext(message) { - let sessionId = get(message, 'context.sessionId'); - sessionId = Number(sessionId); - if (Number.isNaN(sessionId)) return -1; - return sessionId; -} +const handleSessionIdUnderContext = (sessionId) => { + if (!isValidInteger(sessionId)) return -1; + return Number(sessionId); +}; -function getSessionId(message) { - return get(message, 'session_id') - ? handleSessionIdUnderRoot(message) - : get(message, 'context.sessionId') - ? handleSessionIdUnderContext(message) - : -1; -} +const checkForJSONAndUserIdLengthAndDeviceId = (jsonBody, userId, deviceId) => + Object.keys(jsonBody).length === 0 || + (userId && + userId.length < 5 && + (!batchEventsWithUserIdLengthLowerThanFive || + (batchEventsWithUserIdLengthLowerThanFive && !deviceId))); +const getSessionId = (message) => { + let sessionId = -1; + const rootSessionId = get(message, 'session_id'); + if (rootSessionId) { + sessionId = handleSessionIdUnderRoot(rootSessionId); + if (sessionId !== -1) { + return sessionId; + } + } + const contextSessionId = get(message, 'context.sessionId'); + if (contextSessionId) { + sessionId = handleSessionIdUnderContext(contextSessionId); + } + return sessionId; +}; -function addMinIdlength() { - return { min_id_length: 1 }; -} +const addMinIdlength = () => ({ min_id_length: 1 }); -function setPriceQuanityInPayload(message, rawPayload) { +const setPriceQuanityInPayload = (message, rawPayload) => { let price; let quantity; - if (isDefinedAndNotNull(message.properties.price)) { + if (isDefinedAndNotNull(message.properties?.price)) { price = message.properties.price; - quantity = message.properties.quantity || 1; + quantity = message.properties?.quantity || 1; } else { - price = message.properties.revenue; + price = message.properties?.revenue; quantity = 1; } rawPayload.price = price; rawPayload.quantity = quantity; - rawPayload.revenue = message.properties.revenue; + rawPayload.revenue = message.properties?.revenue; return rawPayload; -} +}; -function createRevenuePayload(message, rawPayload) { - rawPayload.productId = message.properties.product_id; +const createRevenuePayload = (message, rawPayload) => { + rawPayload.productId = message.properties?.product_id; rawPayload.revenueType = - message.properties.revenueType || message.properties.revenue_type || 'Purchased'; + message.properties?.revenueType || message.properties?.revenue_type || 'Purchased'; rawPayload = setPriceQuanityInPayload(message, rawPayload); return rawPayload; -} +}; -function updateTraitsObject(property, traitsObject, actionKey) { +const updateTraitsObject = (property, traitsObject, actionKey) => { const propertyToUpdate = getValueFromMessage(traitsObject, property); if (traitsObject[actionKey] && property && typeof property === 'string') { traitsObject[actionKey][property] = propertyToUpdate; deleteObjectProperty(traitsObject, property); } return traitsObject; -} +}; -function prepareTraitsConfig(configPropertyTrait, actionKey, traitsObject) { +const prepareTraitsConfig = (configPropertyTrait, actionKey, traitsObject) => { traitsObject[actionKey] = {}; configPropertyTrait.forEach((traitsElement) => { - const property = traitsElement.traits; + const property = traitsElement?.traits; traitsObject = updateTraitsObject(property, traitsObject, actionKey); }); - if (Object.keys(traitsObject[actionKey]).length === 0) { + if ( + typeof traitsObject?.[actionKey] === 'object' && + Object.keys(traitsObject?.[actionKey] || {})?.length === 0 + ) { delete traitsObject[actionKey]; } return traitsObject; -} +}; -function handleTraits(messageTrait, destination) { +const handleTraits = (messageTrait, destination) => { let traitsObject = JSON.parse(JSON.stringify(messageTrait)); - if (destination.Config.traitsToIncrement) { + if (destination.Config?.traitsToIncrement) { const actionKey = '$add'; traitsObject = prepareTraitsConfig( destination.Config.traitsToIncrement, @@ -162,29 +178,41 @@ function handleTraits(messageTrait, destination) { traitsObject, ); } - if (destination.Config.traitsToSetOnce) { + if (destination.Config?.traitsToSetOnce) { const actionKey = '$setOnce'; traitsObject = prepareTraitsConfig(destination.Config.traitsToSetOnce, actionKey, traitsObject); } - if (destination.Config.traitsToAppend) { + if (destination.Config?.traitsToAppend) { const actionKey = '$append'; traitsObject = prepareTraitsConfig(destination.Config.traitsToAppend, actionKey, traitsObject); } - if (destination.Config.traitsToPrepend) { + if (destination.Config?.traitsToPrepend) { const actionKey = '$prepend'; traitsObject = prepareTraitsConfig(destination.Config.traitsToPrepend, actionKey, traitsObject); } return traitsObject; -} +}; + +const getScreenevTypeAndUpdatedProperties = (message, CATEGORY_KEY) => { + const name = message.name || message.event || get(message, CATEGORY_KEY); + + return { + eventType: `Viewed ${message.name || message.event || get(message, CATEGORY_KEY) || ''} Screen`, + updatedProperties: { + ...message.properties, + name, + }, + }; +}; -function handleMappingJsonObject( +const handleMappingJsonObject = ( mappingJson, sourceKey, validatePayload, payload, message, Config, -) { +) => { const { isFunc, funcName, outKey } = mappingJson[sourceKey]; if (isFunc) { if (validatePayload) { @@ -203,150 +231,242 @@ function handleMappingJsonObject( if (isDefinedAndNotNull(data)) { set(payload, outKey, data); delete message.traits[outKey]; - } else { - // get the destKey/outKey value from calling the util function - set(payload, outKey, AMUtils[funcName](message, sourceKey, Config)); + return; } + // get the destKey/outKey value from calling the util function + set(payload, outKey, AMUtils[funcName](message, sourceKey, Config)); } } -} +}; -function updateConfigProperty(message, payload, mappingJson, validatePayload, Config) { +const updateConfigProperty = (message, payload, mappingJson, validatePayload, Config) => { const sourceKeys = Object.keys(mappingJson); sourceKeys.forEach((sourceKey) => { // check if custom processing is required on the payload sourceKey ==> destKey if (typeof mappingJson[sourceKey] === 'object') { handleMappingJsonObject(mappingJson, sourceKey, validatePayload, payload, message, Config); - } else { - // For common config - if (validatePayload) { - // if data is present in traits assign - const messageData = get(message.traits, mappingJson[sourceKey]); - if (isDefinedAndNotNull(messageData)) { - set(payload, mappingJson[sourceKey], messageData); - } else { - const data = get(payload, mappingJson[sourceKey]); - if (!isDefinedAndNotNull(data)) { - const val = get(message, sourceKey); - if (val || val === false || val === 0) { - set(payload, mappingJson[sourceKey], val); - } + } else if (validatePayload) { + // if data is present in traits assign + const messageData = get(message.traits, mappingJson[sourceKey]); + if (isDefinedAndNotNull(messageData)) { + set(payload, mappingJson[sourceKey], messageData); + } else { + const data = get(payload, mappingJson[sourceKey]); + if (!isDefinedAndNotNull(data)) { + const val = get(message, sourceKey); + if (val || val === false || val === 0) { + set(payload, mappingJson[sourceKey], val); } } + } + } else { + const data = get(message.traits, mappingJson[sourceKey]); + if (isDefinedAndNotNull(data)) { + set(payload, mappingJson[sourceKey], data); } else { - const data = get(message.traits, mappingJson[sourceKey]); - if (isDefinedAndNotNull(data)) { - set(payload, mappingJson[sourceKey], data); - } else { - set(payload, mappingJson[sourceKey], get(message, sourceKey)); - } + set(payload, mappingJson[sourceKey], get(message, sourceKey)); } } }); -} +}; +const identifyBuilder = (message, destination, rawPayload) => { + // update payload user_properties from userProperties/traits/context.traits/nested traits of Rudder message + // traits like address converted to top level user properties (think we can skip this extra processing as AM supports nesting upto 40 levels) + let traits = getFieldValueFromMessage(message, 'traits'); + if (traits) { + traits = handleTraits(traits, destination); + } + rawPayload.user_properties = { + ...rawPayload.user_properties, + ...message.userProperties, + }; + if (traits) { + Object.keys(traits).forEach((trait) => { + if (SpecedTraits.includes(trait)) { + const mapping = TraitsMapping[trait]; + Object.keys(mapping).forEach((key) => { + const checkKey = get(rawPayload.user_properties, key); + // this is done only if we want to add default values under address to the user_properties + // these values are also sent to the destination at the top level. + if (!isDefinedAndNotNull(checkKey)) { + set(rawPayload, `user_properties.${key}`, get(traits, mapping[key])); + } + }); + } else { + set(rawPayload, `user_properties.${trait}`, get(traits, trait)); + } + }); + } + return rawPayload; +}; + +const getDefaultResponseData = (message, rawPayload, evType, groupInfo) => { + const traits = getFieldValueFromMessage(message, 'traits'); + set(rawPayload, 'event_properties', message.properties); + + if (traits) { + rawPayload.user_properties = { + ...rawPayload.user_properties, + ...traits, + }; + } -function getResponseData(evType, destination, rawPayload, message, groupInfo) { - let endpoint = defaultEndpoint(destination.Config); - let traits; + rawPayload.event_type = evType; + rawPayload.user_id = message.userId; + if (message.isRevenue) { + // making the revenue payload + rawPayload = createRevenuePayload(message, rawPayload); + // deleting the properties price, product_id, quantity and revenue from event_properties since it is already in root + if (rawPayload.event_properties) { + delete rawPayload.event_properties.price; + delete rawPayload.event_properties.product_id; + delete rawPayload.event_properties.quantity; + delete rawPayload.event_properties.revenue; + } + } + const groups = groupInfo && cloneDeep(groupInfo); + return { groups, rawPayload }; +}; +const getResponseData = (evType, destination, rawPayload, message, groupInfo) => { let groups; switch (evType) { case EventType.IDENTIFY: + // event_type for identify event is $identify + rawPayload.event_type = IDENTIFY_AM; + identifyBuilder(message, destination, rawPayload); + break; case EventType.GROUP: - endpoint = defaultEndpoint(destination.Config); // event_type for identify event is $identify rawPayload.event_type = IDENTIFY_AM; - - if (evType === EventType.IDENTIFY) { - // update payload user_properties from userProperties/traits/context.traits/nested traits of Rudder message - // traits like address converted to top level user properties (think we can skip this extra processing as AM supports nesting upto 40 levels) - traits = getFieldValueFromMessage(message, 'traits'); - if (traits) { - traits = handleTraits(traits, destination); - } - rawPayload.user_properties = { - ...rawPayload.user_properties, - ...message.userProperties, - }; - if (traits) { - Object.keys(traits).forEach((trait) => { - if (SpecedTraits.includes(trait)) { - const mapping = TraitsMapping[trait]; - Object.keys(mapping).forEach((key) => { - const checkKey = get(rawPayload.user_properties, key); - // this is done only if we want to add default values under address to the user_properties - // these values are also sent to the destination at the top level. - if (!isDefinedAndNotNull(checkKey)) { - set(rawPayload, `user_properties.${key}`, get(traits, mapping[key])); - } - }); - } else { - set(rawPayload, `user_properties.${trait}`, get(traits, trait)); - } - }); - } - } - - if ( - evType === EventType.GROUP && // for Rudder group call, update the user_properties with group info - // Refer (1.) - groupInfo && - groupInfo.group_type && - groupInfo.group_value - ) { + // for Rudder group call, update the user_properties with group info + if (groupInfo?.group_type && groupInfo?.group_value) { groups = {}; groups[groupInfo.group_type] = groupInfo.group_value; set(rawPayload, `user_properties.${[groupInfo.group_type]}`, groupInfo.group_value); } break; case EventType.ALIAS: - endpoint = aliasEndpoint(destination.Config); break; default: - traits = getFieldValueFromMessage(message, 'traits'); - set(rawPayload, 'event_properties', message.properties); - - if (traits) { - rawPayload.user_properties = { - ...rawPayload.user_properties, - ...traits, - }; - } + ({ groups, rawPayload } = getDefaultResponseData(message, rawPayload, evType, groupInfo)); + } + return { rawPayload, groups }; +}; - rawPayload.event_type = evType; - rawPayload.user_id = message.userId; - if (message.isRevenue) { - // making the revenue payload - rawPayload = createRevenuePayload(message, rawPayload); - // deleting the properties price, product_id, quantity and revenue from event_properties since it is already in root - if (rawPayload.event_properties) { - delete rawPayload.event_properties.price; - delete rawPayload.event_properties.product_id; - delete rawPayload.event_properties.quantity; - delete rawPayload.event_properties.revenue; - } - } - groups = groupInfo && Object.assign(groupInfo); +const buildPayloadForMobileChannel = (message, destination, payload) => { + if (!destination.Config.mapDeviceBrand) { + set(payload, 'device_brand', get(message, 'context.device.manufacturer')); } - return { endpoint, rawPayload, groups }; -} -function responseBuilderSimple( + const deviceId = get(message, 'context.device.id'); + const platform = get(message, 'context.device.type'); + const advertId = get(message, 'context.device.advertisingId'); + + if (platform) { + if (isAppleFamily(platform)) { + set(payload, 'idfa', advertId); + set(payload, 'idfv', deviceId); + } else if (platform.toLowerCase() === 'android') { + set(payload, 'adid', advertId); + } + } +}; +const nonAliasResponsebuilder = ( + message, + payload, + destination, + evType, + groupInfo, + rootElementName, +) => { + const respList = []; + const addOptions = 'options'; + const response = defaultRequestConfig(); + const groupResponse = defaultRequestConfig(); + const endpoint = defaultEndpoint(destination.Config); + if (message.channel === 'mobile') { + buildPayloadForMobileChannel(message, destination, payload); + } + payload.time = new Date(getFieldValueFromMessage(message, 'timestamp')).getTime(); + + // send user_id only when present, for anonymous users not required + if (message.userId && message.userId !== null) { + payload.user_id = message.userId; + } + payload.session_id = getSessionId(message); + + updateConfigProperty( + message, + payload, + mappingConfig[ConfigCategory.COMMON_CONFIG.name], + true, + destination.Config, + ); + + // we are not fixing the verson for android specifically any more because we've put a fix in iOS SDK + // for correct versionName + // ==================== + // fixVersion(payload, message); + + if (payload.user_properties) { + delete payload.user_properties.city; + delete payload.user_properties.country; + if (payload.user_properties.address) { + delete payload.user_properties.address.city; + delete payload.user_properties.address.country; + } + } + + if (!payload.user_id && !payload.device_id) { + logger.debug('Either of user ID or device ID fields must be specified'); + throw new InstrumentationError('Either of user ID or device ID fields must be specified'); + } + + payload.ip = getParsedIP(message); + payload.library = 'rudderstack'; + payload = removeUndefinedAndNullValues(payload); + response.endpoint = endpoint; + response.method = defaultPostRequestConfig.requestMethod; + response.headers = { + 'Content-Type': JSON_MIME_TYPE, + }; + response.userId = message.anonymousId; + response.body.JSON = { + api_key: destination.Config.apiKey, + [rootElementName]: [payload], + [addOptions]: addMinIdlength(), + }; + respList.push(response); + + // https://developers.amplitude.com/docs/group-identify-api + // Refer (1.), Rudder group call updates group propertiees. + if (evType === EventType.GROUP && groupInfo) { + groupResponse.method = defaultPostRequestConfig.requestMethod; + groupResponse.endpoint = groupEndpoint(destination.Config); + let groupPayload = cloneDeep(groupInfo); + groupResponse.userId = message.anonymousId; + groupPayload = removeUndefinedValues(groupPayload); + groupResponse.body.FORM = { + api_key: destination.Config.apiKey, + identification: [JSON.stringify(groupPayload)], + }; + respList.push(groupResponse); + } + return respList; +}; + +const responseBuilderSimple = ( groupInfo, rootElementName, message, evType, mappingJson, destination, -) { - let rawPayload = {}; - const addOptions = 'options'; +) => { + const rawPayload = {}; const respList = []; - const response = defaultRequestConfig(); - const groupResponse = defaultRequestConfig(); const aliasResponse = defaultRequestConfig(); - let endpoint = defaultEndpoint(destination.Config); - if ( EventType.IDENTIFY && // If mapped to destination, Add externalId to traits get(message, MappedToDestinationKey) @@ -375,7 +495,7 @@ function responseBuilderSimple( const oldKeys = Object.keys(campaign); // appends utm_ prefix to all the keys of campaign object. For example the `name` key in campaign object will be changed to `utm_name` oldKeys.forEach((oldKey) => { - Object.assign(campaign, { [`utm_${oldKey}`]: campaign[oldKey] }); + campaign[`utm_${oldKey}`] = campaign[oldKey]; delete campaign[oldKey]; }); @@ -390,14 +510,13 @@ function responseBuilderSimple( }; const respData = getResponseData(evType, destination, rawPayload, message, groupInfo); - const { groups } = respData; - ({ endpoint, rawPayload } = respData); + const { groups, rawPayload: updatedRawPayload } = respData; // for https://api.amplitude.com/2/httpapi , pass the "groups" key // refer (1.) for passing "groups" for Rudder group call // https://developers.amplitude.com/docs/http-api-v2#schemaevent - set(rawPayload, 'groups', groups); - let payload = removeUndefinedValues(rawPayload); + set(updatedRawPayload, 'groups', groups); + let payload = removeUndefinedValues(updatedRawPayload); let unmapUserId; if (evType === EventType.ALIAS) { // By default (1.), Alias config file populates user_id and global_user_id @@ -419,116 +538,65 @@ function responseBuilderSimple( }; respList.push(aliasResponse); } else { - if (message.channel === 'mobile') { - if (!destination.Config.mapDeviceBrand) { - set(payload, 'device_brand', get(message, 'context.device.manufacturer')); - } - - const deviceId = get(message, 'context.device.id'); - const platform = get(message, 'context.device.type'); - const advertId = get(message, 'context.device.advertisingId'); - - if (platform) { - if (isAppleFamily(platform)) { - set(payload, 'idfa', advertId); - set(payload, 'idfv', deviceId); - } else if (platform.toLowerCase() === 'android') { - set(payload, 'adid', advertId); - } - } - } - - payload.time = new Date(getFieldValueFromMessage(message, 'timestamp')).getTime(); - - // send user_id only when present, for anonymous users not required - if ( - message.userId && - message.userId !== '' && - message.userId !== 'null' && - message.userId !== null - ) { - payload.user_id = message.userId; - } - payload.session_id = getSessionId(message); - - updateConfigProperty( + return nonAliasResponsebuilder( message, payload, - mappingConfig[ConfigCategory.COMMON_CONFIG.name], - true, - destination.Config, + destination, + evType, + groupInfo, + rootElementName, ); + } + return respList; +}; - // we are not fixing the verson for android specifically any more because we've put a fix in iOS SDK - // for correct versionName - // ==================== - // fixVersion(payload, message); - - if (payload.user_properties) { - delete payload.user_properties.city; - delete payload.user_properties.country; - if (payload.user_properties.address) { - delete payload.user_properties.address.city; - delete payload.user_properties.address.country; - } - } - - if (!payload.user_id && !payload.device_id) { - logger.debug('Either of user ID or device ID fields must be specified'); - throw new InstrumentationError('Either of user ID or device ID fields must be specified'); - } - - payload.ip = getParsedIP(message); - payload.library = 'rudderstack'; - payload = removeUndefinedAndNullValues(payload); - response.endpoint = endpoint; - response.method = defaultPostRequestConfig.requestMethod; - response.headers = { - 'Content-Type': JSON_MIME_TYPE, - }; - response.userId = message.anonymousId; - response.body.JSON = { - api_key: destination.Config.apiKey, - [rootElementName]: [payload], - [addOptions]: addMinIdlength(), - }; - respList.push(response); - - // https://developers.amplitude.com/docs/group-identify-api - // Refer (1.), Rudder group call updates group propertiees. - if (evType === EventType.GROUP && groupInfo) { - groupResponse.method = defaultPostRequestConfig.requestMethod; - groupResponse.endpoint = groupEndpoint(destination.Config); - let groupPayload = Object.assign(groupInfo); - groupResponse.userId = message.anonymousId; - groupPayload = removeUndefinedValues(groupPayload); - groupResponse.body.FORM = { - api_key: destination.Config.apiKey, - identification: [JSON.stringify(groupPayload)], - }; - respList.push(groupResponse); +const getGroupInfo = (destination, groupInfo, groupTraits) => { + const { groupTypeTrait, groupValueTrait } = destination.Config; + if (groupTypeTrait && groupValueTrait) { + let updatedGroupInfo = { ...groupInfo }; + const groupTypeValue = get(groupTraits, groupTypeTrait); + const groupNameValue = get(groupTraits, groupValueTrait); + // since the property updates on group at https://api2.amplitude.com/groupidentify + // expects a string group name and value , so error out if the keys are not primitive + // Note: This different for groups object at https://api.amplitude.com/2/httpapi where the + // group value can be array of strings as well. + if ( + groupTypeValue && + typeof groupTypeValue === 'string' && + groupNameValue && + (typeof groupNameValue === 'string' || typeof groupNameValue === 'number') + ) { + updatedGroupInfo = {}; + updatedGroupInfo.group_type = groupTypeValue; + updatedGroupInfo.group_value = groupNameValue; + // passing the entire group traits without deleting the above keys + updatedGroupInfo.group_properties = groupTraits; + return updatedGroupInfo; } + logger.debug('Group call parameters are not valid'); + throw new InstrumentationError('Group call parameters are not valid'); } - - return respList; -} + return groupInfo; +}; // Generic process function which invokes specific handler functions depending on message type // and event type where applicable -function processSingleMessage(message, destination) { +const processSingleMessage = (message, destination) => { let payloadObjectName = 'events'; let evType; - let groupTraits; - let groupTypeTrait; - let groupValueTrait; // It is expected that Rudder alias. identify group calls won't have this set // To be used for track/page calls to associate the event to a group in AM let groupInfo = get(message, 'integrations.Amplitude.groups') || undefined; let category = ConfigCategory.DEFAULT; - + const { name, event, properties } = message; const messageType = message.type.toLowerCase(); const CATEGORY_KEY = 'properties.category'; - const { useUserDefinedPageEventName, userProvidedPageEventString } = destination.Config; + const { + useUserDefinedPageEventName, + userProvidedPageEventString, + useUserDefinedScreenEventName, + userProvidedScreenEventString, + } = destination.Config; switch (messageType) { case EventType.IDENTIFY: payloadObjectName = 'events'; // identify same as events @@ -545,27 +613,44 @@ function processSingleMessage(message, destination) { .trim(); evType = userProvidedPageEventString.trim() === '' - ? message.name + ? name : userProvidedPageEventString .trim() .replaceAll(/{{([^{}]+)}}/g, get(message, getMessagePath)); } else { - evType = `Viewed ${message.name || get(message, CATEGORY_KEY) || ''} Page`; + evType = `Viewed ${name || get(message, CATEGORY_KEY) || ''} Page`; } - message.properties = { - ...message.properties, - name: message.name || get(message, CATEGORY_KEY), + ...properties, + name: name || get(message, CATEGORY_KEY), }; category = ConfigCategory.PAGE; break; case EventType.SCREEN: - evType = `Viewed ${message.name || message.event || get(message, CATEGORY_KEY) || ''} Screen`; - message.properties = { - ...message.properties, - name: message.name || message.event || get(message, CATEGORY_KEY), - }; - category = ConfigCategory.SCREEN; + { + const { eventType, updatedProperties } = getScreenevTypeAndUpdatedProperties( + message, + CATEGORY_KEY, + ); + let customScreenEv = ''; + if (useUserDefinedScreenEventName) { + const getMessagePath = userProvidedScreenEventString + .substring( + userProvidedScreenEventString.indexOf('{') + 2, + userProvidedScreenEventString.indexOf('}'), + ) + .trim(); + customScreenEv = + userProvidedScreenEventString.trim() === '' + ? name + : userProvidedScreenEventString + .trim() + .replaceAll(/{{([^{}]+)}}/g, get(message, getMessagePath)); + } + evType = useUserDefinedScreenEventName ? customScreenEv : eventType; + message.properties = updatedProperties; + category = ConfigCategory.SCREEN; + } break; case EventType.GROUP: evType = 'group'; @@ -574,34 +659,13 @@ function processSingleMessage(message, destination) { // read from group traits from message // groupTraits => top level "traits" for JS SDK // groupTraits => "context.traits" for mobile SDKs - groupTraits = getFieldValueFromMessage(message, 'groupTraits'); + groupInfo = getGroupInfo( + destination, + groupInfo, + getFieldValueFromMessage(message, 'groupTraits'), + ); // read destination config related group settings // https://developers.amplitude.com/docs/group-identify-api - groupTypeTrait = get(destination, 'Config.groupTypeTrait'); - groupValueTrait = get(destination, 'Config.groupValueTrait'); - if (groupTypeTrait && groupValueTrait) { - const groupTypeValue = get(groupTraits, groupTypeTrait); - const groupNameValue = get(groupTraits, groupValueTrait); - // since the property updates on group at https://api2.amplitude.com/groupidentify - // expects a string group name and value , so error out if the keys are not primitive - // Note: This different for groups object at https://api.amplitude.com/2/httpapi where the - // group value can be array of strings as well. - if ( - groupTypeValue && - typeof groupTypeValue === 'string' && - groupNameValue && - (typeof groupNameValue === 'string' || typeof groupNameValue === 'number') - ) { - groupInfo = {}; - groupInfo.group_type = groupTypeValue; - groupInfo.group_value = groupNameValue; - // passing the entire group traits without deleting the above keys - groupInfo.group_properties = groupTraits; - } else { - logger.debug('Group call parameters are not valid'); - throw new InstrumentationError('Group call parameters are not valid'); - } - } break; case EventType.ALIAS: evType = 'alias'; @@ -611,21 +675,19 @@ function processSingleMessage(message, destination) { category = ConfigCategory.ALIAS; break; case EventType.TRACK: - evType = message.event; + evType = event; if (!isDefinedAndNotNullAndNotEmpty(evType)) { - throw new InstrumentationError('message type not defined'); + throw new InstrumentationError('Event not present. Please send event field'); } if ( - message.properties && - isDefinedAndNotNull(message.properties.revenue) && - isDefinedAndNotNull(message.properties.revenue_type) + properties && + isDefinedAndNotNull(properties?.revenue) && + isDefinedAndNotNull(properties?.revenue_type) ) { // if properties has revenue and revenue_type fields // consider the event as revenue event directly category = ConfigCategory.REVENUE; - break; } - break; default: logger.debug('could not determine type'); @@ -639,10 +701,10 @@ function processSingleMessage(message, destination) { mappingConfig[category.name], destination, ); -} +}; -function createProductPurchasedEvent(message, destination, product, counter) { - const eventClonePurchaseProduct = JSON.parse(JSON.stringify(message)); +const createProductPurchasedEvent = (message, destination, product, counter) => { + const eventClonePurchaseProduct = cloneDeep(message); eventClonePurchaseProduct.event = 'Product Purchased'; // In product purchased event event properties consists of the details of each product @@ -654,17 +716,17 @@ function createProductPurchasedEvent(message, destination, product, counter) { // need to modify the message id of each newly created event, as it is mapped to insert_id and that is used by Amplitude for dedup. eventClonePurchaseProduct.messageId = `${message.messageId}-${counter}`; return eventClonePurchaseProduct; -} +}; -function isProductArrayInPayload(message) { +const isProductArrayInPayload = (message) => { const isProductArray = - (message.properties.products && + (message.properties?.products && Array.isArray(message.properties.products) && message.properties.products.length > 0) === true; return isProductArray; -} +}; -function getProductPurchasedEvents(message, destination) { +const getProductPurchasedEvents = (message, destination) => { const productPurchasedEvents = []; if (isProductArrayInPayload(message)) { let counter = 0; @@ -682,16 +744,16 @@ function getProductPurchasedEvents(message, destination) { }); } return productPurchasedEvents; -} +}; -function trackRevenueEvent(message, destination) { +const trackRevenueEvent = (message, destination) => { let sendEvents = []; - const originalEvent = JSON.parse(JSON.stringify(message)); + const originalEvent = cloneDeep(message); if (destination.Config.trackProductsOnce === false) { if (isProductArrayInPayload(message)) { // when trackProductsOnce false no product array present - delete originalEvent.properties.products; + delete originalEvent.properties?.products; } else { // when product array is not there in payload, will track the revenue of the original event. originalEvent.isRevenue = true; @@ -719,16 +781,19 @@ function trackRevenueEvent(message, destination) { } } return sendEvents; -} +}; -function process(event) { +const process = (event) => { const respList = []; const { message, destination } = event; - const messageType = message.type.toLowerCase(); + const messageType = message.type?.toLowerCase(); const toSendEvents = []; + if (!destination?.Config?.apiKey) { + throw new ConfigurationError('No API Key is Found. Please Configure API key from dashbaord'); + } if (messageType === EventType.TRACK) { const { properties } = message; - if (properties && isDefinedAndNotNull(properties.revenue)) { + if (isDefinedAndNotNull(properties?.revenue)) { const revenueEvents = trackRevenueEvent(message, destination); revenueEvents.forEach((revenueEvent) => { toSendEvents.push(revenueEvent); @@ -744,9 +809,9 @@ function process(event) { respList.push(...processSingleMessage(sendEvent, destination)); }); return respList; -} +}; -function getBatchEvents(message, destination, metadata, batchEventResponse) { +const getBatchEvents = (message, destination, metadata, batchEventResponse) => { let batchComplete = false; const batchEventArray = get(batchEventResponse, 'batchedRequest.body.JSON.events') || []; const batchEventJobs = get(batchEventResponse, 'metadata') || []; @@ -760,18 +825,19 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { : incomingMessageEvent; const userId = incomingMessageEvent.user_id; - // delete the userId as it is less than 5 as AM is giving 400 - // that is not a documented behviour where it states if either deviceid or userid is present - // batch request won't return 400 - // { - // "code": 400, - // "events_with_invalid_id_lengths": { - // "user_id": [ - // 0 - // ] - // }, - // "error": "Invalid id length for user_id or device_id" - // } + /* delete the userId as it is less than 5 as AM is giving 400 + that is not a documented behviour where it states if either deviceid or userid is present + batch request won't return 400 + { + "code": 400, + "events_with_invalid_id_lengths": { + "user_id": [ + 0 + ] + }, + "error": "Invalid id length for user_id or device_id" + } + */ if (batchEventsWithUserIdLengthLowerThanFive && userId && userId.length < 5) { delete incomingMessageEvent.user_id; } @@ -782,10 +848,7 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { if (batchEventArray.length === 0) { if (JSON.stringify(incomingMessageJSON).length < AMBatchSizeLimit) { delete message.body.JSON.options; - batchEventResponse = Object.assign(batchEventResponse, { - batchedRequest: message, - }); - + batchEventResponse.batchedRequest = message; set(batchEventResponse, 'batchedRequest.endpoint', BATCH_ENDPOINT); batchEventResponse.metadata = [metadata]; } @@ -807,16 +870,16 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { } } return batchComplete; -} +}; -function batch(destEvents) { +const getFirstEvent = (messageEvent) => + messageEvent && Array.isArray(messageEvent) ? messageEvent[0] : messageEvent; +const batch = (destEvents) => { const respList = []; let batchEventResponse = defaultBatchRequestConfig(); let response; let isBatchComplete; let jsonBody; - let userId; - let deviceId; let messageEvent; let destinationObject; destEvents.forEach((ev) => { @@ -824,18 +887,11 @@ function batch(destEvents) { destinationObject = { ...destination }; jsonBody = get(message, 'body.JSON'); messageEvent = get(message, EVENTS_KEY_PATH); - userId = - messageEvent && Array.isArray(messageEvent) - ? messageEvent[0].user_id - : messageEvent - ? messageEvent.user_id - : undefined; - deviceId = - messageEvent && Array.isArray(messageEvent) - ? messageEvent[0].device_id - : messageEvent - ? messageEvent.device_id - : undefined; + const firstEvent = getFirstEvent(messageEvent); + + const userId = firstEvent?.user_id ?? undefined; + const deviceId = firstEvent?.device_id ?? undefined; + // this case shold not happen and should be filtered already // by the first pass of single event transformation if (messageEvent && !userId && !deviceId) { @@ -851,16 +907,13 @@ function batch(destEvents) { respList.push(errorResponse); return; } - // check if not a JSON body or (userId length < 5 && batchEventsWithUserIdLengthLowerThanFive is false) or - // (batchEventsWithUserIdLengthLowerThanFive is true and userId is less than 5 but deviceId not present) - // , send the event as is after batching - if ( - Object.keys(jsonBody).length === 0 || - (!batchEventsWithUserIdLengthLowerThanFive && userId && userId.length < 5) || - (batchEventsWithUserIdLengthLowerThanFive && userId && userId.length < 5 && !deviceId) - ) { + /* check if not a JSON body or (userId length < 5 && batchEventsWithUserIdLengthLowerThanFive is false) or + (batchEventsWithUserIdLengthLowerThanFive is true and userId is less than 5 but deviceId not present), + send the event as is after batching + */ + if (checkForJSONAndUserIdLengthAndDeviceId(jsonBody, userId, deviceId)) { response = defaultBatchRequestConfig(); - response = Object.assign(response, { batchedRequest: message }); + response.batchedRequest = message; response.metadata = [metadata]; response.destination = destinationObject; respList.push(response); @@ -868,8 +921,9 @@ function batch(destEvents) { // check if the event can be pushed to an existing batch isBatchComplete = getBatchEvents(message, destination, metadata, batchEventResponse); if (isBatchComplete) { - // if the batch is already complete, push it to response list - // and push the event to a new batch + /* if the batch is already complete, push it to response list + and push the event to a new batch + */ batchEventResponse.destination = destinationObject; respList.push({ ...batchEventResponse }); batchEventResponse = defaultBatchRequestConfig(); @@ -879,12 +933,12 @@ function batch(destEvents) { } }); // if there is some unfinished batch push it to response list - if (isBatchComplete !== undefined && isBatchComplete === false) { + if (isDefinedAndNotNull(isBatchComplete) && !isBatchComplete) { batchEventResponse.destination = destinationObject; respList.push(batchEventResponse); } return respList; -} +}; const processRouterDest = async (inputs, reqMetadata) => { const respList = await simpleProcessRouterDest(inputs, process, reqMetadata); diff --git a/src/v0/destinations/am/utils.js b/src/v0/destinations/am/utils.js index 33040c2146..b9925c20d8 100644 --- a/src/v0/destinations/am/utils.js +++ b/src/v0/destinations/am/utils.js @@ -13,65 +13,65 @@ const uaParser = require('@amplitude/ua-parser-js'); const logger = require('../../../logger'); const { isDefinedAndNotNull } = require('../../util'); -function getInfoFromUA(path, payload, defaultVal) { +const getInfoFromUA = (path, payload, defaultVal) => { const ua = get(payload, 'context.userAgent'); const devInfo = ua ? uaParser(ua) : {}; return get(devInfo, path) || defaultVal; -} +}; -function getOSName(payload, sourceKey) { +const getOSName = (payload, sourceKey) => { const payloadVal = get(payload, sourceKey); if (payload.channel && payload.channel.toLowerCase() === 'web') { return getInfoFromUA('browser.name', payload, payloadVal); } return payloadVal; -} +}; -function getOSVersion(payload, sourceKey) { +const getOSVersion = (payload, sourceKey) => { const payloadVal = get(payload, sourceKey); if (payload.channel && payload.channel.toLowerCase() === 'web') { return getInfoFromUA('browser.version', payload, payloadVal); } return payloadVal; -} +}; -function getDeviceModel(payload, sourceKey) { +const getDeviceModel = (payload, sourceKey) => { const payloadVal = get(payload, sourceKey); if (payload.channel && payload.channel.toLowerCase() === 'web') { return getInfoFromUA('os.name', payload, payloadVal); } return payloadVal; -} +}; -function getDeviceManufacturer(payload, sourceKey) { +const getDeviceManufacturer = (payload, sourceKey) => { const payloadVal = get(payload, sourceKey); if (payload.channel && payload.channel.toLowerCase() === 'web') { return getInfoFromUA('device.vendor', payload, payloadVal); } return payloadVal; -} +}; -function getPlatform(payload, sourceKey) { +const getPlatform = (payload, sourceKey) => { const payloadVal = get(payload, sourceKey); return payload.channel ? payload.channel.toLowerCase() === 'web' ? 'Web' : payloadVal : payloadVal; -} +}; -function getBrand(payload, sourceKey, Config) { +const getBrand = (payload, sourceKey, Config) => { if (Config.mapDeviceBrand) { const payloadVal = get(payload, sourceKey); return payloadVal; } return undefined; -} +}; -function getEventId(payload, sourceKey) { +const getEventId = (payload, sourceKey) => { const eventId = get(payload, sourceKey); if (isDefinedAndNotNull(eventId)) { @@ -80,7 +80,7 @@ function getEventId(payload, sourceKey) { } else return eventId; } return undefined; -} +}; module.exports = { getOSName, diff --git a/src/v0/destinations/appcues/transform.js b/src/v0/destinations/appcues/transform.js index 095256cc4e..57a54bce33 100644 --- a/src/v0/destinations/appcues/transform.js +++ b/src/v0/destinations/appcues/transform.js @@ -1,4 +1,5 @@ /* eslint-disable no-underscore-dangle */ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -9,7 +10,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig, getEndpoint } = require('./config'); diff --git a/src/v0/destinations/attentive_tag/transform.js b/src/v0/destinations/attentive_tag/transform.js index 231beec143..fa05eb6c21 100644 --- a/src/v0/destinations/attentive_tag/transform.js +++ b/src/v0/destinations/attentive_tag/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ConfigCategory, mappingConfig, BASE_URL } = require('./config'); const { @@ -18,7 +19,6 @@ const { getPropertiesKeyValidation, validateTimestamp, } = require('./util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, apiKey, endpoint) => { diff --git a/src/v0/destinations/attentive_tag/util.js b/src/v0/destinations/attentive_tag/util.js index 890f73cdc9..c96d03028f 100644 --- a/src/v0/destinations/attentive_tag/util.js +++ b/src/v0/destinations/attentive_tag/util.js @@ -1,13 +1,13 @@ /* eslint-disable no-restricted-syntax */ const get = require('get-value'); const moment = require('moment'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { constructPayload, isDefinedAndNotNull, getDestinationExternalID, isDefinedAndNotNullAndNotEmpty, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { mappingConfig, ConfigCategory } = require('./config'); /** diff --git a/src/v0/destinations/attribution/transform.js b/src/v0/destinations/attribution/transform.js index 712f3e5e5d..fa42a6238a 100644 --- a/src/v0/destinations/attribution/transform.js +++ b/src/v0/destinations/attribution/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { batchEndpoint } = require('./config'); const { defaultPostRequestConfig, @@ -5,7 +6,6 @@ const { removeUndefinedAndNullValues, getFieldValueFromMessage, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, attributionConfig) { diff --git a/src/v0/destinations/autopilot/transform.js b/src/v0/destinations/autopilot/transform.js index e0fe9aa400..e4a2c408af 100644 --- a/src/v0/destinations/autopilot/transform.js +++ b/src/v0/destinations/autopilot/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { @@ -9,7 +10,6 @@ const { simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyFields = [ diff --git a/src/v0/destinations/awin/transform.js b/src/v0/destinations/awin/transform.js index f6070fccd5..49a115c1ff 100644 --- a/src/v0/destinations/awin/transform.js +++ b/src/v0/destinations/awin/transform.js @@ -1,8 +1,8 @@ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { BASE_URL, ConfigCategory, mappingConfig } = require('./config'); const { defaultRequestConfig, constructPayload, simpleProcessRouterDest } = require('../../util'); const { getParams } = require('./utils'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const responseBuilder = (message, { Config }) => { const { advertiserId, eventsToTrack } = Config; diff --git a/src/v0/destinations/azure_event_hub/transform.js b/src/v0/destinations/azure_event_hub/transform.js index 6200e32ce7..98180b55b4 100644 --- a/src/v0/destinations/azure_event_hub/transform.js +++ b/src/v0/destinations/azure_event_hub/transform.js @@ -1,6 +1,5 @@ const cloneDeep = require('lodash/cloneDeep'); const { getIntegrationsObj } = require('../../util'); -// const { InstrumentationError } = require("../../util/errorTypes"); function process(event) { const { message, destination } = event; diff --git a/src/v0/destinations/blueshift/transform.js b/src/v0/destinations/blueshift/transform.js index b79af327d2..cdfbfe32e1 100644 --- a/src/v0/destinations/blueshift/transform.js +++ b/src/v0/destinations/blueshift/transform.js @@ -1,3 +1,8 @@ +const { + TransformationError, + InstrumentationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { constructPayload, @@ -10,11 +15,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { - TransformationError, - InstrumentationError, - ConfigurationError, -} = require('../../util/errorTypes'); const { MAPPING_CONFIG, diff --git a/src/v0/destinations/bqstream/transform.js b/src/v0/destinations/bqstream/transform.js index 55679b08a8..598a97946d 100644 --- a/src/v0/destinations/bqstream/transform.js +++ b/src/v0/destinations/bqstream/transform.js @@ -1,5 +1,6 @@ /* eslint-disable no-console */ const lodash = require('lodash'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultBatchRequestConfig, @@ -9,7 +10,6 @@ const { groupEventsByType, } = require('../../util'); const { MAX_ROWS_PER_REQUEST, DESTINATION } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const { getRearrangedEvents } = require('./util'); const getInsertIdColValue = (properties, insertIdCol) => { diff --git a/src/v0/destinations/branch/transform.js b/src/v0/destinations/branch/transform.js index 0d47fbd791..23dcd6c8db 100644 --- a/src/v0/destinations/branch/transform.js +++ b/src/v0/destinations/branch/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { endpoints } = require('./config'); const { categoriesList } = require('./data/eventMapping'); @@ -11,7 +12,6 @@ const { isAppleFamily, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilder(payload, message, destination, category) { diff --git a/src/v0/destinations/braze/braze.util.test.js b/src/v0/destinations/braze/braze.util.test.js index eb5a46fe34..9859e16152 100644 --- a/src/v0/destinations/braze/braze.util.test.js +++ b/src/v0/destinations/braze/braze.util.test.js @@ -1219,4 +1219,145 @@ describe('getPurchaseObjs', () => { ); } }); + + test('products having extra properties', () => { + const output = getPurchaseObjs( + { + properties: { + products: [ + { product_id: '123', price: 10.99, quantity: 2, random_extra_property_a: 'abc' }, + { product_id: '456', price: 5.49, quantity: 1, random_extra_property_b: 'efg' }, + { + product_id: '789', + price: 15.49, + quantity: 1, + random_extra_property_a: 'abc', + random_extra_property_b: 'efg', + random_extra_property_c: 'hij', + }, + ], + currency: 'USD', + }, + timestamp: '2023-08-04T12:34:56Z', + anonymousId: 'abc', + }, + { + sendPurchaseEventWithExtraProperties: true, + }, + ); + expect(output).toEqual([ + { + product_id: '123', + price: 10.99, + currency: 'USD', + quantity: 2, + time: '2023-08-04T12:34:56Z', + properties: { + random_extra_property_a: 'abc', + }, + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + { + product_id: '456', + price: 5.49, + currency: 'USD', + quantity: 1, + time: '2023-08-04T12:34:56Z', + properties: { + random_extra_property_b: 'efg', + }, + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + { + product_id: '789', + price: 15.49, + currency: 'USD', + quantity: 1, + time: '2023-08-04T12:34:56Z', + properties: { + random_extra_property_a: 'abc', + random_extra_property_b: 'efg', + random_extra_property_c: 'hij', + }, + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + ]); + }); + + test('products having extra properties with sendPurchaseEventWithExtraProperties as false', () => { + const output = getPurchaseObjs( + { + properties: { + products: [ + { product_id: '123', price: 10.99, quantity: 2, random_extra_property_a: 'abc' }, + { product_id: '456', price: 5.49, quantity: 1, random_extra_property_b: 'efg' }, + { + product_id: '789', + price: 15.49, + quantity: 1, + random_extra_property_a: 'abc', + random_extra_property_b: 'efg', + random_extra_property_c: 'hij', + }, + ], + currency: 'USD', + }, + timestamp: '2023-08-04T12:34:56Z', + anonymousId: 'abc', + }, + { + sendPurchaseEventWithExtraProperties: false, + }, + ); + expect(output).toEqual([ + { + product_id: '123', + price: 10.99, + currency: 'USD', + quantity: 2, + time: '2023-08-04T12:34:56Z', + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + { + product_id: '456', + price: 5.49, + currency: 'USD', + quantity: 1, + time: '2023-08-04T12:34:56Z', + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + { + product_id: '789', + price: 15.49, + currency: 'USD', + quantity: 1, + time: '2023-08-04T12:34:56Z', + _update_existing_only: false, + user_alias: { + alias_name: 'abc', + alias_label: 'rudder_id', + }, + }, + ]); + }); }); diff --git a/src/v0/destinations/braze/config.js b/src/v0/destinations/braze/config.js index 2e24f43f61..2bbade2754 100644 --- a/src/v0/destinations/braze/config.js +++ b/src/v0/destinations/braze/config.js @@ -56,6 +56,7 @@ const BRAZE_NON_BILLABLE_ATTRIBUTES = [ 'subscription_groups', ]; +const BRAZE_PURCHASE_STANDARD_PROPERTIES = ['product_id', 'sku', 'price', 'quantity', 'currency']; module.exports = { ConfigCategory, mappingConfig, @@ -64,6 +65,7 @@ module.exports = { getSubscriptionGroupEndPoint, getAliasMergeEndPoint, BRAZE_PARTNER_NAME, + BRAZE_PURCHASE_STANDARD_PROPERTIES, TRACK_BRAZE_MAX_REQ_COUNT, IDENTIFY_BRAZE_MAX_REQ_COUNT, DESTINATION, @@ -71,5 +73,5 @@ module.exports = { DEL_MAX_BATCH_SIZE, BRAZE_NON_BILLABLE_ATTRIBUTES, ALIAS_BRAZE_MAX_REQ_COUNT, - SUBSCRIPTION_BRAZE_MAX_REQ_COUNT + SUBSCRIPTION_BRAZE_MAX_REQ_COUNT, }; diff --git a/src/v0/destinations/braze/deleteUsers.js b/src/v0/destinations/braze/deleteUsers.js index 799aa3f9b4..b94d901138 100644 --- a/src/v0/destinations/braze/deleteUsers.js +++ b/src/v0/destinations/braze/deleteUsers.js @@ -1,3 +1,4 @@ +const { NetworkError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { processAxiosResponse, @@ -8,7 +9,6 @@ const { isHttpStatusSuccess } = require('../../util'); const { executeCommonValidations } = require('../../util/regulation-api'); const { DEL_MAX_BATCH_SIZE } = require('./config'); const { getUserIdBatches } = require('../../util/deleteUserUtils'); -const { NetworkError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const userDeletionHandler = async (userAttributes, config) => { diff --git a/src/v0/destinations/braze/networkHandler.js b/src/v0/destinations/braze/networkHandler.js index a141607fe9..c6cf7222ea 100644 --- a/src/v0/destinations/braze/networkHandler.js +++ b/src/v0/destinations/braze/networkHandler.js @@ -1,4 +1,5 @@ /* eslint-disable no-unused-vars */ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { isHttpStatusSuccess } = require('../../util/index'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { @@ -6,7 +7,6 @@ const { processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); const { DESTINATION } = require('./config'); -const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const stats = require('../../../util/stats'); diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 26fd86b3dd..38c4b348db 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -1,6 +1,8 @@ /* eslint-disable no-nested-ternary,no-param-reassign */ const lodash = require('lodash'); const get = require('get-value'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); +const { FilteredEventsError } = require('../../util/errorTypes'); const { BrazeDedupUtility, CustomAttributeOperationUtil, @@ -20,15 +22,11 @@ const { getFieldValueFromMessage, removeUndefinedValues, isHttpStatusSuccess, + isDefinedAndNotNull, simpleProcessRouterDestSync, simpleProcessRouterDest, isNewStatusCodesAccepted, } = require('../../util'); -const { - InstrumentationError, - NetworkError, - FilteredEventsError, -} = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig, @@ -98,7 +96,10 @@ function populateCustomAttributesWithOperation( // add,update,remove on json attributes if (enableNestedArrayOperations) { Object.keys(traits) - .filter((key) => typeof traits[key] === 'object' && !Array.isArray(traits[key])) + .filter( + (key) => + traits[key] !== null && typeof traits[key] === 'object' && !Array.isArray(traits[key]), + ) .forEach((key) => { if (traits[key][CustomAttributeOperationTypes.UPDATE]) { CustomAttributeOperationUtil.customAttributeUpdateOperation( @@ -153,11 +154,16 @@ function getUserAttributesObject(message, mappingJson, destination) { Object.keys(mappingJson).forEach((destKey) => { let value = get(traits, mappingJson[destKey]); if (value || (value === null && reservedKeys.includes(destKey))) { + // if email is not string remove it from attributes + if (destKey === 'email' && typeof value !== 'string') { + throw new InstrumentationError('Invalid email, email must be a valid string'); + } + // handle gender special case if (destKey === 'gender') { value = formatGender(value); - } else if (destKey === 'email' && value !== null) { - value = value?.toLowerCase(); + } else if (destKey === 'email' && isDefinedAndNotNull(value)) { + value = value.toString().toLowerCase(); } data[destKey] = value; } @@ -318,7 +324,7 @@ function processTrackEvent(messageType, message, destination, mappingJson, proce typeof eventName === 'string' && eventName.toLowerCase() === 'order completed' ) { - const purchaseObjs = getPurchaseObjs(message); + const purchaseObjs = getPurchaseObjs(message, destination.Config); // del used properties delete properties.products; diff --git a/src/v0/destinations/braze/util.js b/src/v0/destinations/braze/util.js index b3e60f2c6a..3b0855b338 100644 --- a/src/v0/destinations/braze/util.js +++ b/src/v0/destinations/braze/util.js @@ -21,11 +21,12 @@ const { SUBSCRIPTION_BRAZE_MAX_REQ_COUNT, ALIAS_BRAZE_MAX_REQ_COUNT, TRACK_BRAZE_MAX_REQ_COUNT, + BRAZE_PURCHASE_STANDARD_PROPERTIES, } = require('./config'); const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); const { isObject } = require('../../util'); const { removeUndefinedValues, getIntegrationsObj } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const getEndpointFromConfig = (destination) => { // Init -- mostly for test cases @@ -539,7 +540,7 @@ function addMandatoryPurchaseProperties(productId, price, currencyCode, quantity }; } -function getPurchaseObjs(message) { +function getPurchaseObjs(message, config) { // ref:https://www.braze.com/docs/api/objects_filters/purchase_object/ const validateForPurchaseEvent = (message) => { const { properties } = message; @@ -634,6 +635,10 @@ function getPurchaseObjs(message) { parseInt(quantity, 10), timestamp, ); + const extraProperties = _.omit(product, BRAZE_PURCHASE_STANDARD_PROPERTIES); + if (Object.keys(extraProperties).length > 0 && config.sendPurchaseEventWithExtraProperties) { + purchaseObj = { ...purchaseObj, properties: extraProperties }; + } purchaseObj = setExternalIdOrAliasObject(purchaseObj, message); purchaseObjs.push(purchaseObj); }); diff --git a/src/v0/destinations/campaign_manager/config.js b/src/v0/destinations/campaign_manager/config.js index 063f65cb14..b3a9531347 100644 --- a/src/v0/destinations/campaign_manager/config.js +++ b/src/v0/destinations/campaign_manager/config.js @@ -9,6 +9,8 @@ const ConfigCategories = { }, }; +const MAX_BATCH_CONVERSATIONS_SIZE = 1000; + const EncryptionEntityType = [ 'ENCRYPTION_ENTITY_TYPE_UNKNOWN', 'DCM_ACCOUNT', @@ -28,4 +30,5 @@ module.exports = { BASE_URL, EncryptionEntityType, EncryptionSource, + MAX_BATCH_CONVERSATIONS_SIZE, }; diff --git a/src/v0/destinations/campaign_manager/networkHandler.js b/src/v0/destinations/campaign_manager/networkHandler.js index cd98de253e..a1fa24835c 100644 --- a/src/v0/destinations/campaign_manager/networkHandler.js +++ b/src/v0/destinations/campaign_manager/networkHandler.js @@ -1,3 +1,5 @@ +/* eslint-disable no-restricted-syntax */ +const { AbortedError, RetryableError, NetworkError } = require('@rudderstack/integrations-lib'); const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); const { isHttpStatusSuccess, getAuthErrCategoryFromStCode } = require('../../util/index'); @@ -5,26 +7,47 @@ const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { AbortedError, RetryableError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); function checkIfFailuresAreRetryable(response) { + const { status } = response; try { - if (Array.isArray(response.status) && Array.isArray(response.status[0].errors)) { - return ( - response.status[0].errors[0].code !== 'PERMISSION_DENIED' && - response.status[0].errors[0].code !== 'INVALID_ARGUMENT' - ); + if (Array.isArray(status)) { + // iterate over each status, and if found retryable in conversations ..retry else discard + /* status : [{ + "conversion": { + object (Conversion) + }, + "errors": [ + { + object (ConversionError) + } + ], + "kind": string + }] */ + for (const st of status) { + for (const err of st.errors) { + // if code is any of these, event is not retryable + if ( + err.code === 'PERMISSION_DENIED' || + err.code === 'INVALID_ARGUMENT' || + err.code === 'NOT_FOUND' + ) { + return false; + } + } + } } return true; } catch (e) { - return true; + return false; } } const responseHandler = (destinationResponse) => { const message = `[CAMPAIGN_MANAGER Response Handler] - Request Processed Successfully`; const { response, status } = destinationResponse; + if (isHttpStatusSuccess(status)) { // check for Failures if (response.hasFailures === true) { @@ -53,7 +76,7 @@ const responseHandler = (destinationResponse) => { throw new NetworkError( `Campaign Manager: ${response.error?.message} during CAMPAIGN_MANAGER response transformation 3`, - status, + 500, { [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), }, diff --git a/src/v0/destinations/campaign_manager/transform.js b/src/v0/destinations/campaign_manager/transform.js index af097e5b4c..3b480dbac2 100644 --- a/src/v0/destinations/campaign_manager/transform.js +++ b/src/v0/destinations/campaign_manager/transform.js @@ -1,12 +1,16 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); +const lodash = require('lodash'); const { EventType } = require('../../../constants'); - const { constructPayload, defaultRequestConfig, defaultPostRequestConfig, + defaultBatchRequestConfig, removeUndefinedAndNullValues, + getSuccessRespEvents, isDefinedAndNotNull, - simpleProcessRouterDest, + checkInvalidRtTfEvents, + handleRtTfSingleEventError, getAccessToken, } = require('../../util'); @@ -16,11 +20,10 @@ const { BASE_URL, EncryptionEntityType, EncryptionSource, + MAX_BATCH_CONVERSATIONS_SIZE, } = require('./config'); const { convertToMicroseconds } = require('./util'); - -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function isEmptyObject(obj) { @@ -179,9 +182,110 @@ function process(event) { return response; } +const generateBatch = (eventKind, events) => { + const batchRequestObject = defaultBatchRequestConfig(); + const conversions = []; + let encryptionInfo = {}; + const metadata = []; + // extracting destination, message from the first event in a batch + const { destination, message } = events[0]; + // Batch event into dest batch structure + events.forEach((ev) => { + conversions.push(...ev.message.body.JSON.conversions); + metadata.push(ev.metadata); + if (ev.message.body.JSON.encryptionInfo) { + encryptionInfo = ev.message.body.JSON.encryptionInfo; + } + }); + + batchRequestObject.batchedRequest.body.JSON = { + kind: eventKind, + conversions, + }; + + if (Object.keys(encryptionInfo).length > 0) { + batchRequestObject.batchedRequest.body.JSON.encryptionInfo = encryptionInfo; + } + + batchRequestObject.batchedRequest.endpoint = message.endpoint; + + batchRequestObject.batchedRequest.headers = message.headers; + + return { + ...batchRequestObject, + metadata, + destination, + }; +}; + +const batchEvents = (eventChunksArray) => { + const batchedResponseList = []; + + // group batchInsert and batchUpdate payloads + const groupedEventChunks = lodash.groupBy( + eventChunksArray, + (event) => event.message.body.JSON.kind, + ); + Object.keys(groupedEventChunks).forEach((eventKind) => { + // eventChunks = [[e1,e2,e3,..batchSize],[e1,e2,e3,..batchSize]..] + const eventChunks = lodash.chunk(groupedEventChunks[eventKind], MAX_BATCH_CONVERSATIONS_SIZE); + eventChunks.forEach((chunk) => { + const batchEventResponse = generateBatch(eventKind, chunk); + batchedResponseList.push( + getSuccessRespEvents( + batchEventResponse.batchedRequest, + batchEventResponse.metadata, + batchEventResponse.destination, + true, + ), + ); + }); + }); + return batchedResponseList; +}; + const processRouterDest = async (inputs, reqMetadata) => { - const respList = await simpleProcessRouterDest(inputs, process, reqMetadata); - return respList; + const errorRespEvents = checkInvalidRtTfEvents(inputs); + if (errorRespEvents.length > 0) { + return errorRespEvents; + } + + const batchErrorRespList = []; + const eventChunksArray = []; + const { destination } = inputs[0]; + await Promise.all( + inputs.map(async (event) => { + try { + if (event.message.statusCode) { + // already transformed event + eventChunksArray.push({ + message: event.message, + metadata: event.metadata, + destination, + }); + } else { + // if not transformed + const proccessedRespList = process(event); + const transformedPayload = { + message: proccessedRespList, + metadata: event.metadata, + destination, + }; + eventChunksArray.push(transformedPayload); + } + } catch (error) { + const errRespEvent = handleRtTfSingleEventError(event, error, reqMetadata); + batchErrorRespList.push(errRespEvent); + } + }), + ); + + let batchResponseList = []; + if (eventChunksArray.length > 0) { + batchResponseList = batchEvents(eventChunksArray); + } + + return [...batchResponseList, ...batchErrorRespList]; }; module.exports = { process, processRouterDest }; diff --git a/src/v0/destinations/candu/transform.js b/src/v0/destinations/candu/transform.js index 659af36540..d114998484 100644 --- a/src/v0/destinations/candu/transform.js +++ b/src/v0/destinations/candu/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -6,7 +7,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { endpoint, identifyDataMapping, trackDataMapping } = require('./config'); const responseBuilder = (body, { Config }) => { diff --git a/src/v0/destinations/canny/transform.js b/src/v0/destinations/canny/transform.js index d837a8ddd3..f4364e1fb7 100644 --- a/src/v0/destinations/canny/transform.js +++ b/src/v0/destinations/canny/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ConfigCategory, mappingConfig, BASE_URL } = require('./config'); const { @@ -14,7 +15,6 @@ const { validateCreatePostFields, validateEventMapping, } = require('./util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (responseConfgs) => { diff --git a/src/v0/destinations/canny/util.js b/src/v0/destinations/canny/util.js index 002d9aa69f..59644bcd6b 100644 --- a/src/v0/destinations/canny/util.js +++ b/src/v0/destinations/canny/util.js @@ -1,8 +1,8 @@ const qs = require('qs'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const { getDestinationExternalID } = require('../../util'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const logger = require('../../../logger'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/clevertap/deleteUsers.js b/src/v0/destinations/clevertap/deleteUsers.js index 826c6c6939..3c07a63d93 100644 --- a/src/v0/destinations/clevertap/deleteUsers.js +++ b/src/v0/destinations/clevertap/deleteUsers.js @@ -1,3 +1,4 @@ +const { NetworkError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { getEndpoint, DEL_MAX_BATCH_SIZE } = require('./config'); const { @@ -6,7 +7,6 @@ const { } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); const { executeCommonValidations } = require('../../util/regulation-api'); -const { NetworkError, ConfigurationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { getUserIdBatches } = require('../../util/deleteUserUtils'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/clevertap/networkHandler.js b/src/v0/destinations/clevertap/networkHandler.js index 35c972e502..e17afb57d1 100644 --- a/src/v0/destinations/clevertap/networkHandler.js +++ b/src/v0/destinations/clevertap/networkHandler.js @@ -1,10 +1,10 @@ +const { NetworkError, AbortedError } = require('@rudderstack/integrations-lib'); const { isHttpStatusSuccess } = require('../../util/index'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, AbortedError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const responseHandler = (destinationResponse) => { diff --git a/src/v0/destinations/clevertap/transform.js b/src/v0/destinations/clevertap/transform.js index 5c1e28c086..efcd101668 100644 --- a/src/v0/destinations/clevertap/transform.js +++ b/src/v0/destinations/clevertap/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-param-reassign */ /* eslint-disable no-nested-ternary */ const get = require('get-value'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { getEndpoint, @@ -25,7 +26,6 @@ const { } = require('../../util'); const { generateClevertapBatchedPayload } = require('./utils'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const TIMESTAMP_KEY_PATH = 'context.traits.ts'; diff --git a/src/v0/destinations/clickup/transform.js b/src/v0/destinations/clickup/transform.js index d93e53b349..0637d65bd4 100644 --- a/src/v0/destinations/clickup/transform.js +++ b/src/v0/destinations/clickup/transform.js @@ -1,3 +1,4 @@ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -14,7 +15,6 @@ const { checkEventIfUIMapped, } = require('./util'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, createTaskEndPoint } = require('./config'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = async (payload, listId, apiToken) => { diff --git a/src/v0/destinations/clickup/util.js b/src/v0/destinations/clickup/util.js index 7b17f83bb6..148fe1bd07 100644 --- a/src/v0/destinations/clickup/util.js +++ b/src/v0/destinations/clickup/util.js @@ -1,3 +1,4 @@ +const { NetworkError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { httpGET } = require('../../../adapters/network'); const { processAxiosResponse, @@ -9,7 +10,6 @@ const { formatTimeStamp, } = require('../../util'); const { getCustomFieldsEndPoint } = require('./config'); -const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/confluent_cloud/transform.js b/src/v0/destinations/confluent_cloud/transform.js index e8f0f4d2e2..b33abc90cf 100644 --- a/src/v0/destinations/confluent_cloud/transform.js +++ b/src/v0/destinations/confluent_cloud/transform.js @@ -1,6 +1,5 @@ const cloneDeep = require('lodash/cloneDeep'); const { getIntegrationsObj } = require('../../util'); -// const { InstrumentationError } = require("../../util/errorTypes"); function process(event) { const { message, destination } = event; diff --git a/src/v0/destinations/courier/transform.js b/src/v0/destinations/courier/transform.js index 7d52b503d9..d5e25434ec 100644 --- a/src/v0/destinations/courier/transform.js +++ b/src/v0/destinations/courier/transform.js @@ -1,3 +1,8 @@ +const { + TransformationError, + InstrumentationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -6,11 +11,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { - TransformationError, - InstrumentationError, - ConfigurationError, -} = require('../../util/errorTypes'); const { API_URL } = require('./config'); const responseBuilder = (payload, endpoint, destination) => { diff --git a/src/v0/destinations/criteo_audience/networkHandler.js b/src/v0/destinations/criteo_audience/networkHandler.js index f4369cdc9e..18bd9a93a0 100644 --- a/src/v0/destinations/criteo_audience/networkHandler.js +++ b/src/v0/destinations/criteo_audience/networkHandler.js @@ -1,3 +1,10 @@ +const { + NetworkError, + ThrottledError, + NetworkInstrumentationError, + AbortedError, + RetryableError, +} = require('@rudderstack/integrations-lib'); const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); const { isHttpStatusSuccess } = require('../../util/index'); const { REFRESH_TOKEN } = require('../../../adapters/networkhandler/authConstants'); @@ -6,13 +13,6 @@ const { getDynamicErrorType, processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); -const { - NetworkError, - ThrottledError, - NetworkInstrumentationError, - AbortedError, - RetryableError, -} = require('../../util/errorTypes'); // https://developers.criteo.com/marketing-solutions/v2021.01/docs/how-to-handle-api-errors#:~:text=the%20response%20body.-,401,-Authentication%20error // Following fucntion tells us if there is a particular error code in the response. diff --git a/src/v0/destinations/criteo_audience/transform.js b/src/v0/destinations/criteo_audience/transform.js index 7ddbdbef20..25e53cc305 100644 --- a/src/v0/destinations/criteo_audience/transform.js +++ b/src/v0/destinations/criteo_audience/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { BASE_ENDPOINT, operation } = require('./config'); const { defaultRequestConfig, @@ -9,7 +10,6 @@ const { getEventType, getDestinationExternalIDInfoForRetl, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { MappedToDestinationKey } = require('../../../constants'); const { preparePayload } = require('./util'); diff --git a/src/v0/destinations/criteo_audience/util.js b/src/v0/destinations/criteo_audience/util.js index a7541f7911..d9d37bc331 100644 --- a/src/v0/destinations/criteo_audience/util.js +++ b/src/v0/destinations/criteo_audience/util.js @@ -1,6 +1,6 @@ const lodash = require('lodash'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { isDefinedAndNotNullAndNotEmpty } = require('../../util'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { MAX_IDENTIFIERS } = require('./config'); const populateIdentifiers = (audienceList, audienceType) => { diff --git a/src/v0/destinations/custify/deleteUsers.js b/src/v0/destinations/custify/deleteUsers.js index e90abe7abb..147fcc602c 100644 --- a/src/v0/destinations/custify/deleteUsers.js +++ b/src/v0/destinations/custify/deleteUsers.js @@ -1,9 +1,13 @@ +const { + ConfigurationError, + InstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const { httpDELETE } = require('../../../adapters/network'); const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { ConfigurationError, InstrumentationError, NetworkError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const tags = require('../../util/tags'); diff --git a/src/v0/destinations/custify/transform.js b/src/v0/destinations/custify/transform.js index fd81511982..6b08be1c56 100644 --- a/src/v0/destinations/custify/transform.js +++ b/src/v0/destinations/custify/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { ConfigCategory } = require('./config'); const { @@ -9,7 +10,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { processIdentify, processTrack, processGroup } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); /** diff --git a/src/v0/destinations/custify/util.js b/src/v0/destinations/custify/util.js index d943b5c8bf..ae6f21fe20 100644 --- a/src/v0/destinations/custify/util.js +++ b/src/v0/destinations/custify/util.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); const { ConfigCategory, MappingConfig, @@ -16,7 +17,6 @@ const { constructPayload, isHttpStatusSuccess, } = require('../../util'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/customerio/transform.js b/src/v0/destinations/customerio/transform.js index 5f953ee2f0..be4486717c 100644 --- a/src/v0/destinations/customerio/transform.js +++ b/src/v0/destinations/customerio/transform.js @@ -1,6 +1,7 @@ const get = require('get-value'); const btoa = require('btoa'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { @@ -12,6 +13,7 @@ const { adduserIdFromExternalId, getFieldValueFromMessage, handleRtTfSingleEventError, + validateEventName, } = require('../../util'); const logger = require('../../../logger'); @@ -23,7 +25,6 @@ const { defaultResponseBuilder, validateConfigFields, } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilder(message, evType, evName, destination, messageType) { @@ -101,6 +102,7 @@ function processSingleMessage(message, destination) { break; case EventType.TRACK: evType = 'event'; + validateEventName(message.event); evName = message.event; break; case EventType.ALIAS: @@ -113,6 +115,7 @@ function processSingleMessage(message, destination) { logger.error(`could not determine type ${messageType}`); throw new InstrumentationError(`could not determine type ${messageType}`); } + evName = evName ? String(evName) : evName; const response = responseBuilder(message, evType, evName, destination, messageType); // replace default domain with EU data center domainc for EU based account diff --git a/src/v0/destinations/customerio/util.js b/src/v0/destinations/customerio/util.js index 2e7f000fba..ef983748a5 100644 --- a/src/v0/destinations/customerio/util.js +++ b/src/v0/destinations/customerio/util.js @@ -1,6 +1,7 @@ const get = require('get-value'); const set = require('set-value'); const truncate = require('truncate-utf8-bytes'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { MAX_BATCH_SIZE, configFieldsToCheck } = require('./config'); const { constructPayload, @@ -10,7 +11,6 @@ const { defaultDeleteRequestConfig, isAppleFamily, validateEmail, - validateEventType, } = require('../../util'); const { EventType, SpecedTraits, TraitsMapping } = require('../../../constants'); @@ -29,8 +29,6 @@ const { DEVICE_REGISTER_ENDPOINT, } = require('./config'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); - const deviceRelatedEventNames = [ 'Application Installed', 'Application Opened', @@ -288,7 +286,6 @@ const defaultResponseBuilder = (message, evName, userId, evType, destination, me // 100 - len(`Viewed Screen`) = 86 trimmedEvName = `Viewed ${truncate(message.event || message.properties.name, 86)} Screen`; } else { - validateEventType(evName); trimmedEvName = truncate(evName, 100); } // anonymous_id needs to be sent for anon track calls to provide information on which anon user is being tracked diff --git a/src/v0/destinations/delighted/transform.js b/src/v0/destinations/delighted/transform.js index f5a2afdcaf..cf80dc878d 100644 --- a/src/v0/destinations/delighted/transform.js +++ b/src/v0/destinations/delighted/transform.js @@ -1,3 +1,8 @@ +const { + InstrumentationError, + ConfigurationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { getFieldValueFromMessage, @@ -20,11 +25,6 @@ const { userValidity, } = require('./util'); const { ENDPOINT, TRACKING_EXCLUSION_FIELDS, identifyMapping } = require('./config'); -const { - InstrumentationError, - ConfigurationError, - NetworkInstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyResponseBuilder = (message, { Config }) => { diff --git a/src/v0/destinations/delighted/util.js b/src/v0/destinations/delighted/util.js index 3cf26a3697..2c92685fd7 100644 --- a/src/v0/destinations/delighted/util.js +++ b/src/v0/destinations/delighted/util.js @@ -1,11 +1,11 @@ -const myAxios = require('../../../util/myAxios'); -const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const { getValueFromMessage } = require('../../util'); const { NetworkInstrumentationError, InstrumentationError, NetworkError, -} = require('../../util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const myAxios = require('../../../util/myAxios'); +const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); +const { getValueFromMessage } = require('../../util'); const { ENDPOINT } = require('./config'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/discord/transform.js b/src/v0/destinations/discord/transform.js index 4eb2f79235..714ee4f52b 100644 --- a/src/v0/destinations/discord/transform.js +++ b/src/v0/destinations/discord/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-nested-ternary */ /* eslint-disable no-prototype-builtins */ const Handlebars = require('handlebars'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -9,7 +10,6 @@ const { getFieldValueFromMessage, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { stringifyJSON, getName, diff --git a/src/v0/destinations/drip/transform.js b/src/v0/destinations/drip/transform.js index 9abe3e3f77..4ccba076d0 100644 --- a/src/v0/destinations/drip/transform.js +++ b/src/v0/destinations/drip/transform.js @@ -1,3 +1,8 @@ +const { + InstrumentationError, + ConfigurationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { getDestinationExternalID, @@ -31,11 +36,6 @@ const { createUpdateUser, createList, } = require('./util'); -const { - InstrumentationError, - ConfigurationError, - NetworkInstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyResponseBuilder = async (message, { Config }) => { diff --git a/src/v0/destinations/drip/util.js b/src/v0/destinations/drip/util.js index dbb59fc6af..a502cf0d20 100644 --- a/src/v0/destinations/drip/util.js +++ b/src/v0/destinations/drip/util.js @@ -1,8 +1,8 @@ +const { NetworkError, AbortedError } = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const logger = require('../../../logger'); const { constructPayload, isDefinedAndNotNull } = require('../../util'); -const { NetworkError, AbortedError } = require('../../util/errorTypes'); const { ENDPOINT, productMapping } = require('./config'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/engage/deleteUsers.js b/src/v0/destinations/engage/deleteUsers.js index 940529ea0c..a3c3055c7d 100644 --- a/src/v0/destinations/engage/deleteUsers.js +++ b/src/v0/destinations/engage/deleteUsers.js @@ -1,3 +1,4 @@ +const { ConfigurationError, NetworkError } = require('@rudderstack/integrations-lib'); const { httpDELETE } = require('../../../adapters/network'); const { processAxiosResponse, @@ -5,7 +6,6 @@ const { } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); const tags = require('../../util/tags'); -const { ConfigurationError, NetworkError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/engage/transform.js b/src/v0/destinations/engage/transform.js index 98b8bb2bb9..f5daafb98c 100644 --- a/src/v0/destinations/engage/transform.js +++ b/src/v0/destinations/engage/transform.js @@ -1,4 +1,5 @@ const { set } = require('lodash'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, constructPayload, @@ -14,7 +15,6 @@ const { getDestinationExternalID } = require('../../util'); const { EventType } = require('../../../constants'); const { mappingConfig, ConfigCategories } = require('./config'); const { refinePayload, generatePageName, getLists } = require('./utils'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const UID_ERROR_MSG = 'Neither externalId nor userId is available'; diff --git a/src/v0/destinations/eventbridge/transform.js b/src/v0/destinations/eventbridge/transform.js index 71c7731074..53c74d0f88 100644 --- a/src/v0/destinations/eventbridge/transform.js +++ b/src/v0/destinations/eventbridge/transform.js @@ -1,5 +1,5 @@ +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { removeUndefinedAndNullValues, simpleProcessRouterDest } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); function getResouceList(config) { let resource; diff --git a/src/v0/destinations/facebook_conversions/config.js b/src/v0/destinations/facebook_conversions/config.js index fc04f13be6..0c1fc12e15 100644 --- a/src/v0/destinations/facebook_conversions/config.js +++ b/src/v0/destinations/facebook_conversions/config.js @@ -1,7 +1,7 @@ const { getMappingConfig } = require('../../util'); const ENDPOINT = (datasetId, accessToken) => - `https://graph.facebook.com/v17.0/${datasetId}/events?access_token=${accessToken}`; + `https://graph.facebook.com/v18.0/${datasetId}/events?access_token=${accessToken}`; const CONFIG_CATEGORIES = { USERDATA: { diff --git a/src/v0/destinations/facebook_conversions/transform.js b/src/v0/destinations/facebook_conversions/transform.js index dec1ef2e6c..1bb97b2672 100644 --- a/src/v0/destinations/facebook_conversions/transform.js +++ b/src/v0/destinations/facebook_conversions/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-param-reassign */ const get = require('get-value'); const moment = require('moment'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, @@ -13,7 +14,6 @@ const { EventType } = require('../../../constants'); const { constructPayload, extractCustomFields, - flattenJson, getIntegrationsObj, getValidDynamicFormConfig, simpleProcessRouterDest, @@ -34,8 +34,6 @@ const { formingFinalResponse, } = require('../../util/facebookUtils'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); - const responseBuilderSimple = (message, category, destination) => { const { Config, ID } = destination; let { categoryToContent } = Config; @@ -74,8 +72,11 @@ const responseBuilderSimple = (message, category, destination) => { commonData.action_source = getActionSource(commonData, actionSource); let customData = {}; - customData = flattenJson( - extractCustomFields(message, customData, ['properties'], FB_CONVERSIONS_DEFAULT_EXCLUSION), + customData = extractCustomFields( + message, + customData, + ['properties'], + FB_CONVERSIONS_DEFAULT_EXCLUSION, ); customData = transformedPayloadData( diff --git a/src/v0/destinations/facebook_conversions/utils.js b/src/v0/destinations/facebook_conversions/utils.js index 270fac8c45..26204ec61a 100644 --- a/src/v0/destinations/facebook_conversions/utils.js +++ b/src/v0/destinations/facebook_conversions/utils.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES, OTHER_STANDARD_EVENTS, @@ -8,7 +9,6 @@ const { } = require('./config'); const { constructPayload, isObject, isAppleFamily } = require('../../util'); const { getContentType, getContentCategory } = require('../../util/facebookUtils'); -const { InstrumentationError } = require('../../util/errorTypes'); const getActionSource = (payload, fallbackActionSource) => { let actionSource = fallbackActionSource; @@ -44,7 +44,11 @@ const getCategoryFromEvent = (eventName) => { return category; }; -const populateContentsAndContentIDs = (productPropertiesArray, fallbackQuantity) => { +const populateContentsAndContentIDs = ( + productPropertiesArray, + fallbackQuantity, + fallbackDeliveryCategory, +) => { const contentIds = []; const contents = []; if (Array.isArray(productPropertiesArray)) { @@ -57,6 +61,7 @@ const populateContentsAndContentIDs = (productPropertiesArray, fallbackQuantity) id: productId, quantity: productProps.quantity || fallbackQuantity || 1, item_price: productProps.price, + delivery_category: productProps.delivery_category || fallbackDeliveryCategory, }); } } @@ -142,6 +147,7 @@ const populateCustomDataBasedOnCategory = (customData, message, category, catego const { contentIds, contents } = populateContentsAndContentIDs( message.properties?.products, message.properties?.quantity, + message.properties?.delivery_category, ); const contentCategory = eventTypeCustomData.content_category; diff --git a/src/v0/destinations/facebook_offline_conversions/transform.js b/src/v0/destinations/facebook_offline_conversions/transform.js index e30bc2fa9a..cc95270fcc 100644 --- a/src/v0/destinations/facebook_offline_conversions/transform.js +++ b/src/v0/destinations/facebook_offline_conversions/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, simpleProcessRouterDest, @@ -7,7 +8,6 @@ const { const { offlineConversionResponseBuilder, prepareUrls } = require('./utils'); const { EventType } = require('../../../constants'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const responseBuilder = (endpoint) => { if (endpoint) { diff --git a/src/v0/destinations/facebook_offline_conversions/utils.js b/src/v0/destinations/facebook_offline_conversions/utils.js index 819bf8056d..c48de4e0b9 100644 --- a/src/v0/destinations/facebook_offline_conversions/utils.js +++ b/src/v0/destinations/facebook_offline_conversions/utils.js @@ -1,5 +1,6 @@ const sha256 = require('sha256'); const get = require('get-value'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { isObject, formatTimeStamp, @@ -22,7 +23,6 @@ const { eventToStandardMapping, MATCH_KEY_FIELD_TYPE_DICTIONARY, } = require('./config'); -const { ConfigurationError } = require('../../util/errorTypes'); /** * @param {*} message diff --git a/src/v0/destinations/facebook_pixel/config.js b/src/v0/destinations/facebook_pixel/config.js index 99c3c70b2d..17d5887e1b 100644 --- a/src/v0/destinations/facebook_pixel/config.js +++ b/src/v0/destinations/facebook_pixel/config.js @@ -1,5 +1,7 @@ const { getMappingConfig } = require('../../util'); +const VERSION = 'v18.0'; + const CONFIG_CATEGORIES = { USERDATA: { standard: false, @@ -95,6 +97,7 @@ const OTHER_STANDARD_EVENTS = [ ]; const FB_PIXEL_DEFAULT_EXCLUSION = ['opt_out', 'event_id', 'action_source']; +const FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING = ['content_ids', 'contents']; const STANDARD_ECOMM_EVENTS_TYPE = [ CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED.type, CONFIG_CATEGORIES.PRODUCT_VIEWED.type, @@ -105,10 +108,12 @@ const STANDARD_ECOMM_EVENTS_TYPE = [ ]; module.exports = { + VERSION, CONFIG_CATEGORIES, MAPPING_CONFIG, ACTION_SOURCES_VALUES, FB_PIXEL_DEFAULT_EXCLUSION, + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING, STANDARD_ECOMM_EVENTS_TYPE, OTHER_STANDARD_EVENTS, DESTINATION: 'FACEBOOK_PIXEL', diff --git a/src/v0/destinations/facebook_pixel/transform.js b/src/v0/destinations/facebook_pixel/transform.js index 02c416cfde..8a63998b45 100644 --- a/src/v0/destinations/facebook_pixel/transform.js +++ b/src/v0/destinations/facebook_pixel/transform.js @@ -1,11 +1,14 @@ /* eslint-disable no-param-reassign */ const get = require('get-value'); const moment = require('moment'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const stats = require('../../../util/stats'); const { + VERSION, CONFIG_CATEGORIES, MAPPING_CONFIG, FB_PIXEL_DEFAULT_EXCLUSION, + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING, STANDARD_ECOMM_EVENTS_TYPE, } = require('./config'); const { EventType } = require('../../../constants'); @@ -36,8 +39,6 @@ const { formingFinalResponse, } = require('../../util/facebookUtils'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); - const responseBuilderSimple = (message, category, destination) => { const { Config, ID } = destination; const { pixelId, accessToken } = Config; @@ -65,7 +66,7 @@ const responseBuilderSimple = (message, category, destination) => { } = Config; const integrationsObj = getIntegrationsObj(message, 'fb_pixel'); - const endpoint = `https://graph.facebook.com/v17.0/${pixelId}/events?access_token=${accessToken}`; + const endpoint = `https://graph.facebook.com/${VERSION}/${pixelId}/events?access_token=${accessToken}`; const userData = fetchUserData( message, @@ -85,7 +86,12 @@ const responseBuilderSimple = (message, category, destination) => { if (category.type !== 'identify') { customData = flattenJson( - extractCustomFields(message, customData, ['properties'], FB_PIXEL_DEFAULT_EXCLUSION), + extractCustomFields( + message, + customData, + ['properties'], + [...FB_PIXEL_DEFAULT_EXCLUSION, ...FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING], + ), ); if (standardPageCall && category.type === 'page') { category.standard = true; @@ -125,6 +131,11 @@ const responseBuilderSimple = (message, category, destination) => { if (type === 'simple track') { customData.value = message.properties?.revenue; delete customData.revenue; + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING.forEach((customDataParameter) => { + if (message.properties?.[customDataParameter]) { + customData[customDataParameter] = message.properties[customDataParameter]; + } + }); } } } else { diff --git a/src/v0/destinations/facebook_pixel/utils.js b/src/v0/destinations/facebook_pixel/utils.js index d642c446fd..8a63a0b0fe 100644 --- a/src/v0/destinations/facebook_pixel/utils.js +++ b/src/v0/destinations/facebook_pixel/utils.js @@ -1,7 +1,12 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isObject } = require('../../util'); -const { ACTION_SOURCES_VALUES, CONFIG_CATEGORIES, OTHER_STANDARD_EVENTS } = require('./config'); +const { + ACTION_SOURCES_VALUES, + CONFIG_CATEGORIES, + OTHER_STANDARD_EVENTS, + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING, +} = require('./config'); const { getContentType, getContentCategory } = require('../../util/facebookUtils'); -const { InstrumentationError } = require('../../util/errorTypes'); /** format revenue according to fb standards with max two decimal places. * @param revenue @@ -54,7 +59,14 @@ const handleOrder = (message, categoryToContent) => { const contentType = getContentType(message, 'product', categoryToContent); const contentIds = []; const contents = []; - const { category, quantity, price, currency, contentName } = message.properties; + const { + category, + quantity, + price, + currency, + contentName, + delivery_category: deliveryCategory, + } = message.properties; if (products) { if (products.length > 0 && Array.isArray(products)) { products.forEach((singleProduct) => { @@ -67,6 +79,7 @@ const handleOrder = (message, categoryToContent) => { id: pId, quantity: singleProduct.quantity || quantity || 1, item_price: singleProduct.price || price, + delivery_category: singleProduct.delivery_category || deliveryCategory, }; contents.push(content); } @@ -262,6 +275,11 @@ const populateCustomDataBasedOnCategory = ( case 'page': // executed when page call is done with standard PageView turned on case 'otherStandard': updatedCustomData = { ...customData }; + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING.forEach((customDataParameter) => { + if (message.properties?.[customDataParameter]) { + updatedCustomData[customDataParameter] = message.properties[customDataParameter]; + } + }); break; default: throw new InstrumentationError(`${category.standard} type of standard event does not exist`); diff --git a/src/v0/destinations/factorsai/transform.js b/src/v0/destinations/factorsai/transform.js index dd2dad42fc..9824b73bbf 100644 --- a/src/v0/destinations/factorsai/transform.js +++ b/src/v0/destinations/factorsai/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -9,7 +10,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategories, mappingConfig, BASE_URL } = require('./config'); diff --git a/src/v0/destinations/fb/config.js b/src/v0/destinations/fb/config.js index 2ad9aeacba..0e52b42416 100644 --- a/src/v0/destinations/fb/config.js +++ b/src/v0/destinations/fb/config.js @@ -1,6 +1,8 @@ const fs = require('fs'); const path = require('path'); +const VERSION = 'v18.0'; + const getPath = (file) => path.resolve(__dirname, file); const baseMapping = JSON.parse(fs.readFileSync(getPath('./data/FbAppBasicMapping.json'))); @@ -20,6 +22,7 @@ const eventPropToTypeMapping = JSON.parse( ); module.exports = { + VERSION, baseMapping, eventNameMapping, eventPropsMapping, diff --git a/src/v0/destinations/fb/transform.js b/src/v0/destinations/fb/transform.js index 756c74ba83..e6f8e986cf 100644 --- a/src/v0/destinations/fb/transform.js +++ b/src/v0/destinations/fb/transform.js @@ -1,6 +1,7 @@ const get = require('get-value'); const set = require('set-value'); const sha256 = require('sha256'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { removeUndefinedValues, @@ -13,6 +14,7 @@ const { } = require('../../util'); const { + VERSION, baseMapping, eventNameMapping, eventPropsMapping, @@ -20,7 +22,6 @@ const { eventPropToTypeMapping, } = require('./config'); const logger = require('../../../logger'); -const { InstrumentationError } = require('../../util/errorTypes'); // const funcMap = { // integer: parseInt, @@ -250,7 +251,7 @@ function responseBuilderSimple(message, payload, destination) { // "https://graph.facebook.com/v13.0/644748472345539/activities" - const endpoint = `https://graph.facebook.com/v17.0/${appID}/activities`; + const endpoint = `https://graph.facebook.com/${VERSION}/${appID}/activities`; const response = defaultRequestConfig(); response.endpoint = endpoint; diff --git a/src/v0/destinations/fb_custom_audience/config.js b/src/v0/destinations/fb_custom_audience/config.js index 635ad2a9bb..284ab0d4a4 100644 --- a/src/v0/destinations/fb_custom_audience/config.js +++ b/src/v0/destinations/fb_custom_audience/config.js @@ -1,4 +1,4 @@ -const BASE_URL = 'https://graph.facebook.com/v17.0'; +const BASE_URL = 'https://graph.facebook.com/v18.0'; function getEndPoint(audienceId) { return `${BASE_URL}/${audienceId}/users`; @@ -93,7 +93,7 @@ const subTypeFields = [ // const MAX_USER_COUNT = 500; (using from destination definition) const USER_ADD = 'add'; const USER_DELETE = 'remove'; -/* No official Documentation is available for this but using trial +/* No official Documentation is available for this but using trial and error method we found that 65000 bytes is the maximum payload allowed size but we are 60000 just to be sure batching is done properly */ const maxPayloadSize = 60000; // bytes diff --git a/src/v0/destinations/fb_custom_audience/networkHandler.js b/src/v0/destinations/fb_custom_audience/networkHandler.js new file mode 100644 index 0000000000..0ea7aff7da --- /dev/null +++ b/src/v0/destinations/fb_custom_audience/networkHandler.js @@ -0,0 +1,6 @@ +const { networkHandler, errorResponseHandler } = require('../../util/facebookUtils/networkHandler'); + +module.exports = { + networkHandler, + errorResponseHandler, +}; diff --git a/src/v0/destinations/fb_custom_audience/transform.js b/src/v0/destinations/fb_custom_audience/transform.js index f31a3dd42e..9320a3476b 100644 --- a/src/v0/destinations/fb_custom_audience/transform.js +++ b/src/v0/destinations/fb_custom_audience/transform.js @@ -1,5 +1,10 @@ const lodash = require('lodash'); const get = require('get-value'); +const { + InstrumentationError, + TransformationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, defaultPostRequestConfig, @@ -26,11 +31,6 @@ const { } = require('./config'); const { MappedToDestinationKey } = require('../../../constants'); -const { - InstrumentationError, - TransformationError, - ConfigurationError, -} = require('../../util/errorTypes'); const responseBuilderSimple = (payload, audienceId) => { if (payload) { diff --git a/src/v0/destinations/fb_custom_audience/util.js b/src/v0/destinations/fb_custom_audience/util.js index 9e7198e393..47ccb9bf7d 100644 --- a/src/v0/destinations/fb_custom_audience/util.js +++ b/src/v0/destinations/fb_custom_audience/util.js @@ -2,11 +2,11 @@ const lodash = require('lodash'); const sha256 = require('sha256'); const get = require('get-value'); const jsonSize = require('json-size'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const stats = require('../../../util/stats'); const { isDefinedAndNotNull } = require('../../util'); const { maxPayloadSize } = require('./config'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); /** * Example payload ={ diff --git a/src/v0/destinations/firehose/transform.js b/src/v0/destinations/firehose/transform.js index b0dc841579..81e2a1ebc8 100644 --- a/src/v0/destinations/firehose/transform.js +++ b/src/v0/destinations/firehose/transform.js @@ -1,6 +1,6 @@ const isString = require('lodash/isString'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { getHashFromArray, simpleProcessRouterDest } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); function getDeliveryStreamMapTo(event) { const { message, destination } = event; diff --git a/src/v0/destinations/freshmarketer/config.js b/src/v0/destinations/freshmarketer/config.js index f1018d439c..a0d6449c3a 100644 --- a/src/v0/destinations/freshmarketer/config.js +++ b/src/v0/destinations/freshmarketer/config.js @@ -4,23 +4,23 @@ const CONFIG_CATEGORIES = { IDENTIFY: { name: 'FRESHMARKETERIdentifyConfig', type: 'identify', - baseUrl: '.myfreshworks.com/crm/sales/api/contacts/upsert', + baseUrl: '/crm/sales/api/contacts/upsert', }, GROUP: { name: 'FRESHMARKETERGroupConfig', type: 'group', - baseUrlAccount: '.myfreshworks.com/crm/sales/api/sales_accounts/upsert', - baseUrlList: '.myfreshworks.com/crm/sales/api/lists', + baseUrlAccount: '/crm/sales/api/sales_accounts/upsert', + baseUrlList: '/crm/sales/api/lists', }, SALES_ACTIVITY: { name: 'SalesActivityConfig', - baseUrlCreate: '.myfreshworks.com/crm/sales/api/sales_activities', - baseUrlListAll: '.myfreshworks.com/crm/sales/api/selector/sales_activity_types', + baseUrlCreate: '/crm/sales/api/sales_activities', + baseUrlListAll: '/crm/sales/api/selector/sales_activity_types', }, }; -const DELETE_ENDPOINT = '.myfreshworks.com/crm/sales/api/contacts/'; -const LIFECYCLE_STAGE_ENDPOINT = '.myfreshworks.com/crm/sales/api/selector/lifecycle_stages'; +const DELETE_ENDPOINT = '/crm/sales/api/contacts/'; +const LIFECYCLE_STAGE_ENDPOINT = '/crm/sales/api/selector/lifecycle_stages'; const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname); module.exports = { diff --git a/src/v0/destinations/freshmarketer/transform.js b/src/v0/destinations/freshmarketer/transform.js index 41c604d407..aa0e03811d 100644 --- a/src/v0/destinations/freshmarketer/transform.js +++ b/src/v0/destinations/freshmarketer/transform.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + InstrumentationError, + NetworkInstrumentationError, + TransformationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -9,11 +14,6 @@ const { getValidDynamicFormConfig, simpleProcessRouterDest, } = require('../../util'); -const { - InstrumentationError, - NetworkInstrumentationError, - TransformationError, -} = require('../../util/errorTypes'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { diff --git a/src/v0/destinations/freshmarketer/utils.js b/src/v0/destinations/freshmarketer/utils.js index 5b47bb9170..6fa1fe9976 100644 --- a/src/v0/destinations/freshmarketer/utils.js +++ b/src/v0/destinations/freshmarketer/utils.js @@ -1,5 +1,10 @@ /* eslint-disable no-param-reassign */ const get = require('get-value'); +const { + InstrumentationError, + NetworkInstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const logger = require('../../../logger'); const { httpPOST, httpGET } = require('../../../adapters/network'); const { @@ -13,11 +18,6 @@ const { getFieldValueFromMessage, } = require('../../util'); const { CONFIG_CATEGORIES, LIFECYCLE_STAGE_ENDPOINT } = require('./config'); -const { - InstrumentationError, - NetworkInstrumentationError, - NetworkError, -} = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); @@ -203,7 +203,7 @@ const updateAccountWOContact = (payload, Config) => { */ const updateContactWithList = (userId, listId, Config) => { const response = defaultRequestConfig(); - response.endpoint = `https://${Config.domain}.myfreshworks.com/crm/sales/api/lists/${listId}/add_contacts`; + response.endpoint = `https://${Config.domain}/crm/sales/api/lists/${listId}/add_contacts`; response.headers = getHeaders(Config.apiKey); response.body.JSON = { ids: [userId], diff --git a/src/v0/destinations/freshsales/config.js b/src/v0/destinations/freshsales/config.js index c6ae4b8165..62f54c1297 100644 --- a/src/v0/destinations/freshsales/config.js +++ b/src/v0/destinations/freshsales/config.js @@ -4,23 +4,23 @@ const CONFIG_CATEGORIES = { IDENTIFY: { name: 'identifyConfig', type: 'identify', - baseUrl: '.myfreshworks.com/crm/sales/api/contacts/upsert', + baseUrl: '/crm/sales/api/contacts/upsert', method: 'POST', }, GROUP: { name: 'groupConfig', type: 'group', - baseUrlAccount: '.myfreshworks.com/crm/sales/api/sales_accounts/upsert', + baseUrlAccount: '/crm/sales/api/sales_accounts/upsert', method: 'POST', }, SALES_ACTIVITY: { name: 'SalesActivityConfig', - baseUrlCreate: '.myfreshworks.com/crm/sales/api/sales_activities', - baseUrlListAll: '.myfreshworks.com/crm/sales/api/selector/sales_activity_types', + baseUrlCreate: '/crm/sales/api/sales_activities', + baseUrlListAll: '/crm/sales/api/selector/sales_activity_types', }, }; -const LIFECYCLE_STAGE_ENDPOINT = '.myfreshworks.com/crm/sales/api/selector/lifecycle_stages'; +const LIFECYCLE_STAGE_ENDPOINT = '/crm/sales/api/selector/lifecycle_stages'; const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname); module.exports = { diff --git a/src/v0/destinations/freshsales/transform.js b/src/v0/destinations/freshsales/transform.js index cd7518a101..096a2d749c 100644 --- a/src/v0/destinations/freshsales/transform.js +++ b/src/v0/destinations/freshsales/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -8,9 +9,8 @@ const { defaultPostRequestConfig, getValidDynamicFormConfig, simpleProcessRouterDest, - validateEventType, + validateEventName, } = require('../../util'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { getUserAccountDetails, @@ -67,7 +67,6 @@ const identifyResponseBuilder = (message, { Config }) => { * @returns */ const trackResponseBuilder = async (message, { Config }, event) => { - validateEventType(event); let payload; const response = defaultRequestConfig(); @@ -125,9 +124,6 @@ const groupResponseBuilder = async (message, { Config }) => { // Checks if there are any mapping events for the track event and returns them function eventMappingHandler(message, destination) { const event = get(message, 'event'); - if (!event) { - throw new InstrumentationError('Event name is required'); - } let { rudderEventsToFreshsalesEvents } = destination.Config; const mappedEvents = new Set(); @@ -161,6 +157,7 @@ const processEvent = async (message, destination) => { response = identifyResponseBuilder(message, destination); break; case EventType.TRACK: { + validateEventName(message.event); const mappedEvents = eventMappingHandler(message, destination); if (mappedEvents.length > 0) { const respList = await Promise.all( diff --git a/src/v0/destinations/freshsales/utils.js b/src/v0/destinations/freshsales/utils.js index b30d9fa16b..96acabb037 100644 --- a/src/v0/destinations/freshsales/utils.js +++ b/src/v0/destinations/freshsales/utils.js @@ -1,5 +1,10 @@ /* eslint-disable no-param-reassign */ const get = require('get-value'); +const { + NetworkInstrumentationError, + InstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const { httpPOST, httpGET } = require('../../../adapters/network'); const { processAxiosResponse, @@ -10,11 +15,6 @@ const { defaultPostRequestConfig, getFieldValueFromMessage, } = require('../../util'); -const { - NetworkInstrumentationError, - InstrumentationError, - NetworkError, -} = require('../../util/errorTypes'); const { CONFIG_CATEGORIES, LIFECYCLE_STAGE_ENDPOINT } = require('./config'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/ga/deleteUsers.js b/src/v0/destinations/ga/deleteUsers.js index cf4694f44a..bb909a0053 100644 --- a/src/v0/destinations/ga/deleteUsers.js +++ b/src/v0/destinations/ga/deleteUsers.js @@ -1,7 +1,7 @@ const { isEmpty } = require('lodash'); +const { InstrumentationError, OAuthSecretError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); -const { InstrumentationError, OAuthSecretError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const { GA_USER_DELETION_ENDPOINT } = require('./config'); const { gaResponseHandler } = require('./networkHandler'); diff --git a/src/v0/destinations/ga/networkHandler.js b/src/v0/destinations/ga/networkHandler.js index a12f9594cd..57db1cb7af 100644 --- a/src/v0/destinations/ga/networkHandler.js +++ b/src/v0/destinations/ga/networkHandler.js @@ -1,3 +1,4 @@ +const { NetworkError, InvalidAuthTokenError } = require('@rudderstack/integrations-lib'); const { REFRESH_TOKEN, AUTH_STATUS_INACTIVE, @@ -7,7 +8,6 @@ const { getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, InvalidAuthTokenError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); /** diff --git a/src/v0/destinations/ga/transform.js b/src/v0/destinations/ga/transform.js index c10697c4e1..32e94bdd41 100644 --- a/src/v0/destinations/ga/transform.js +++ b/src/v0/destinations/ga/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-nested-ternary */ const get = require('get-value'); const md5 = require('md5'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { Event, GA_ENDPOINT, ConfigCategory, mappingConfig, nameToEventMap } = require('./config'); const { setContextualFields } = require('./utils'); @@ -19,7 +20,6 @@ const { } = require('../../util'); const { isDefinedAndNotNull } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const gaDisplayName = 'Google Analytics'; diff --git a/src/v0/destinations/ga/utils.js b/src/v0/destinations/ga/utils.js index 0d3a2f9798..617f2522a0 100644 --- a/src/v0/destinations/ga/utils.js +++ b/src/v0/destinations/ga/utils.js @@ -1,4 +1,4 @@ -const { InstrumentationError } = require('../../util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { GA_ENDPOINT } = require('./config'); /** diff --git a/src/v0/destinations/ga360/transform.js b/src/v0/destinations/ga360/transform.js index c60ea47551..3655c330d5 100644 --- a/src/v0/destinations/ga360/transform.js +++ b/src/v0/destinations/ga360/transform.js @@ -1,5 +1,6 @@ const get = require('get-value'); const md5 = require('md5'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { Event, GA_ENDPOINT, ConfigCategory, mappingConfig, nameToEventMap } = require('./config'); const { @@ -12,7 +13,6 @@ const { getDestinationExternalID, simpleProcessRouterDest, } = require('../../util'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const gaDisplayName = 'Google Analytics'; diff --git a/src/v0/destinations/ga4/networkHandler.js b/src/v0/destinations/ga4/networkHandler.js index e90d2c3095..b62fcc8d3b 100644 --- a/src/v0/destinations/ga4/networkHandler.js +++ b/src/v0/destinations/ga4/networkHandler.js @@ -1,3 +1,4 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { getDynamicErrorType, @@ -5,7 +6,6 @@ const { } = require('../../../adapters/utils/networkUtils'); const { isDefinedAndNotNull, isDefined, isHttpStatusSuccess } = require('../../util'); -const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const responseHandler = (destinationResponse, dest) => { diff --git a/src/v0/destinations/ga4/transform.js b/src/v0/destinations/ga4/transform.js index d1d0790fa9..d8fc531e92 100644 --- a/src/v0/destinations/ga4/transform.js +++ b/src/v0/destinations/ga4/transform.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + ConfigurationError, + InstrumentationError, + UnsupportedEventError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { isEmptyObject, @@ -11,11 +16,6 @@ const { getDestinationExternalID, removeUndefinedAndNullValues, } = require('../../util'); -const { - ConfigurationError, - InstrumentationError, - UnsupportedEventError, -} = require('../../util/errorTypes'); const { ENDPOINT, mappingConfig, diff --git a/src/v0/destinations/ga4/utils.js b/src/v0/destinations/ga4/utils.js index d356300ff7..e4db494727 100644 --- a/src/v0/destinations/ga4/utils.js +++ b/src/v0/destinations/ga4/utils.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isEmpty, constructPayload, @@ -7,7 +8,6 @@ const { extractCustomFields, isDefinedAndNotNull, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { mappingConfig, ConfigCategory } = require('./config'); /** diff --git a/src/v0/destinations/gainsight/transform.js b/src/v0/destinations/gainsight/transform.js index f58fc0d566..f47296f066 100644 --- a/src/v0/destinations/gainsight/transform.js +++ b/src/v0/destinations/gainsight/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-nested-ternary */ const set = require('set-value'); const get = require('get-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { identifyMapping, @@ -28,7 +29,6 @@ const { renameCustomFieldsFromMap, getConfigOrThrowError, } = require('./util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); /** diff --git a/src/v0/destinations/gainsight/util.js b/src/v0/destinations/gainsight/util.js index 3c986b420d..39e666c1a5 100644 --- a/src/v0/destinations/gainsight/util.js +++ b/src/v0/destinations/gainsight/util.js @@ -1,7 +1,11 @@ +const { + ConfigurationError, + RetryableError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const logger = require('../../../logger'); -const { ConfigurationError, RetryableError, NetworkError } = require('../../util/errorTypes'); const { ENDPOINTS, getLookupPayload } = require('./config'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/gainsight_px/transform.js b/src/v0/destinations/gainsight_px/transform.js index ab66b87c5a..4d91980f11 100644 --- a/src/v0/destinations/gainsight_px/transform.js +++ b/src/v0/destinations/gainsight_px/transform.js @@ -1,4 +1,5 @@ /* eslint-disable no-nested-ternary */ +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { isEmptyObject, @@ -29,7 +30,6 @@ const { groupMapping, identifyMapping, } = require('./config'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); /** diff --git a/src/v0/destinations/gainsight_px/util.js b/src/v0/destinations/gainsight_px/util.js index 6900180ab5..5109286b3f 100644 --- a/src/v0/destinations/gainsight_px/util.js +++ b/src/v0/destinations/gainsight_px/util.js @@ -1,6 +1,6 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { ENDPOINTS } = require('./config'); -const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js index e25349dfdc..8ac432935f 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js @@ -1,5 +1,6 @@ const { get, set } = require('lodash'); const sha256 = require('sha256'); +const { NetworkError, NetworkInstrumentationError } = require('@rudderstack/integrations-lib'); const { prepareProxyRequest, handleHttpRequest } = require('../../../adapters/network'); const { isHttpStatusSuccess, getAuthErrCategoryFromStCode } = require('../../util/index'); const { CONVERSION_ACTION_ID_CACHE_TTL } = require('./config'); @@ -12,7 +13,7 @@ const { getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { BASE_ENDPOINT } = require('./config'); -const { NetworkError, NetworkInstrumentationError } = require('../../util/errorTypes'); + const tags = require('../../util/tags'); const ERROR_MSG_PATH = 'response[0].error.message'; diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/transform.js b/src/v0/destinations/google_adwords_enhanced_conversions/transform.js index 898c3f95b0..0be7c3f0ee 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/transform.js +++ b/src/v0/destinations/google_adwords_enhanced_conversions/transform.js @@ -2,6 +2,7 @@ const get = require('get-value'); const { cloneDeep } = require('lodash'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { constructPayload, defaultRequestConfig, @@ -11,8 +12,6 @@ const { getAccessToken, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); - const { trackMapping, BASE_ENDPOINT } = require('./config'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js index 71fdccff20..a87a2431f2 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js @@ -1,6 +1,11 @@ const set = require('set-value'); const get = require('get-value'); const sha256 = require('sha256'); +const { + AbortedError, + NetworkInstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const { prepareProxyRequest, httpSend, httpPOST } = require('../../../adapters/network'); const { isHttpStatusSuccess, @@ -15,11 +20,6 @@ const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { - AbortedError, - NetworkInstrumentationError, - NetworkError, -} = require('../../util/errorTypes'); const tags = require('../../util/tags'); const conversionCustomVariableCache = new Cache(CONVERSION_CUSTOM_VARIABLE_CACHE_TTL); diff --git a/src/v0/destinations/google_adwords_offline_conversions/transform.js b/src/v0/destinations/google_adwords_offline_conversions/transform.js index 0186739d37..397895c603 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/transform.js +++ b/src/v0/destinations/google_adwords_offline_conversions/transform.js @@ -1,4 +1,5 @@ const { set, get } = require('lodash'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { getHashFromArrayWithDuplicate, @@ -21,7 +22,6 @@ const { requestBuilder, getClickConversionPayloadAndEndpoint, } = require('./utils'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const helper = require('./helper'); /** diff --git a/src/v0/destinations/google_adwords_offline_conversions/utils.js b/src/v0/destinations/google_adwords_offline_conversions/utils.js index 7fa5eb29af..c69c5a436f 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/utils.js +++ b/src/v0/destinations/google_adwords_offline_conversions/utils.js @@ -1,5 +1,10 @@ const sha256 = require('sha256'); const { get, set, cloneDeep } = require('lodash'); +const { + AbortedError, + ConfigurationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { isHttpStatusSuccess, @@ -24,7 +29,6 @@ const { } = require('./config'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); const Cache = require('../../util/cache'); -const { AbortedError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const helper = require('./helper'); const conversionActionIdCache = new Cache(CONVERSION_ACTION_ID_CACHE_TTL); diff --git a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js index b8470f9d28..5be8597bdb 100644 --- a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js +++ b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js @@ -1,3 +1,4 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { httpSend, prepareProxyRequest } = require('../../../adapters/network'); const { isHttpStatusSuccess, getAuthErrCategoryFromStCode } = require('../../util/index'); @@ -5,7 +6,6 @@ const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); /** * This function helps to create a offlineUserDataJobs diff --git a/src/v0/destinations/google_adwords_remarketing_lists/transform.js b/src/v0/destinations/google_adwords_remarketing_lists/transform.js index f8cd7c7037..884fcd71f6 100644 --- a/src/v0/destinations/google_adwords_remarketing_lists/transform.js +++ b/src/v0/destinations/google_adwords_remarketing_lists/transform.js @@ -1,5 +1,6 @@ const sha256 = require('sha256'); const get = require('get-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const logger = require('../../../logger'); const { isDefinedAndNotNullAndNotEmpty, @@ -14,7 +15,6 @@ const { getAccessToken, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { offlineDataJobsMapping, addressInfoMapping, diff --git a/src/v0/destinations/google_cloud_function/util.js b/src/v0/destinations/google_cloud_function/util.js index 0a4fb9f4de..8f85460902 100644 --- a/src/v0/destinations/google_cloud_function/util.js +++ b/src/v0/destinations/google_cloud_function/util.js @@ -1,4 +1,4 @@ -const { ConfigurationError } = require('../../util/errorTypes'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); /** * validate destination config diff --git a/src/v0/destinations/googlepubsub/transform.js b/src/v0/destinations/googlepubsub/transform.js index 44208735e0..7a022d6c29 100644 --- a/src/v0/destinations/googlepubsub/transform.js +++ b/src/v0/destinations/googlepubsub/transform.js @@ -1,5 +1,5 @@ +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { simpleProcessRouterDest } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); const { getTopic, createAttributesMetadata } = require('./util'); diff --git a/src/v0/destinations/googlesheets/transform.js b/src/v0/destinations/googlesheets/transform.js index 6cfb3f1d1e..6e27f6192c 100644 --- a/src/v0/destinations/googlesheets/transform.js +++ b/src/v0/destinations/googlesheets/transform.js @@ -1,12 +1,12 @@ /* eslint-disable no-nested-ternary */ const get = require('get-value'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { getValueFromMessage, getSuccessRespEvents, handleRtTfSingleEventError, checkInvalidRtTfEvents, } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); const SOURCE_KEYS = ['properties', 'traits', 'context.traits']; diff --git a/src/v0/destinations/heap/transform.js b/src/v0/destinations/heap/transform.js index 32196eb7be..4256324165 100644 --- a/src/v0/destinations/heap/transform.js +++ b/src/v0/destinations/heap/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { EventType } = require('../../../constants'); const { @@ -8,7 +9,6 @@ const { flattenJson, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(message, category, destination) { diff --git a/src/v0/destinations/hs/HSTransform-v1.js b/src/v0/destinations/hs/HSTransform-v1.js index 30546ad8f6..51feebea74 100644 --- a/src/v0/destinations/hs/HSTransform-v1.js +++ b/src/v0/destinations/hs/HSTransform-v1.js @@ -1,5 +1,10 @@ const get = require('get-value'); const lodash = require('lodash'); +const { + InstrumentationError, + ConfigurationError, + TransformationError, +} = require('@rudderstack/integrations-lib'); const { MappedToDestinationKey, GENERIC_TRUE_VALUES } = require('../../../constants'); const { defaultGetRequestConfig, @@ -14,11 +19,6 @@ const { getDestinationExternalID, getDestinationExternalIDInfoForRetl, } = require('../../util'); -const { - InstrumentationError, - ConfigurationError, - TransformationError, -} = require('../../util/errorTypes'); const { BATCH_CONTACT_ENDPOINT, MAX_BATCH_SIZE, diff --git a/src/v0/destinations/hs/HSTransform-v2.js b/src/v0/destinations/hs/HSTransform-v2.js index 26c12d3eea..2acdd82152 100644 --- a/src/v0/destinations/hs/HSTransform-v2.js +++ b/src/v0/destinations/hs/HSTransform-v2.js @@ -1,5 +1,10 @@ const get = require('get-value'); const lodash = require('lodash'); +const { + TransformationError, + ConfigurationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { MappedToDestinationKey, GENERIC_TRUE_VALUES } = require('../../../constants'); const { defaultPostRequestConfig, @@ -16,11 +21,6 @@ const { getDestinationExternalIDInfoForRetl, getDestinationExternalIDObjectForRetl, } = require('../../util'); -const { - TransformationError, - ConfigurationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { IDENTIFY_CRM_UPDATE_CONTACT, IDENTIFY_CRM_CREATE_NEW_CONTACT, diff --git a/src/v0/destinations/hs/transform.js b/src/v0/destinations/hs/transform.js index a2326e0395..c26e024a6c 100644 --- a/src/v0/destinations/hs/transform.js +++ b/src/v0/destinations/hs/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { checkInvalidRtTfEvents, @@ -19,7 +20,6 @@ const { getProperties, validateDestinationConfig, } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const processSingleMessage = async (message, destination, propertyMap) => { if (!message.type) { diff --git a/src/v0/destinations/hs/util.js b/src/v0/destinations/hs/util.js index eb062b0c39..f83ce0b6de 100644 --- a/src/v0/destinations/hs/util.js +++ b/src/v0/destinations/hs/util.js @@ -1,4 +1,10 @@ const get = require('get-value'); +const { + NetworkInstrumentationError, + InstrumentationError, + ConfigurationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const { httpGET, httpPOST } = require('../../../adapters/network'); const { processAxiosResponse, @@ -12,12 +18,6 @@ const { getDestinationExternalIDInfoForRetl, getValueFromMessage, } = require('../../util'); -const { - NetworkInstrumentationError, - InstrumentationError, - ConfigurationError, - NetworkError, -} = require('../../util/errorTypes'); const { CONTACT_PROPERTY_MAP_ENDPOINT, IDENTIFY_CRM_SEARCH_CONTACT, @@ -607,7 +607,8 @@ const splitEventsForCreateUpdate = async (inputs, destination) => { const { destinationExternalId } = getDestinationExternalIDInfoForRetl(message, DESTINATION); const filteredInfo = updateHubspotIds.filter( - (update) => update.property.toString().toLowerCase() === destinationExternalId.toString().toLowerCase(), + (update) => + update.property.toString().toLowerCase() === destinationExternalId.toString().toLowerCase(), ); if (filteredInfo.length > 0) { diff --git a/src/v0/destinations/impact/transform.js b/src/v0/destinations/impact/transform.js index 026318cec7..2eefdf7992 100644 --- a/src/v0/destinations/impact/transform.js +++ b/src/v0/destinations/impact/transform.js @@ -1,5 +1,10 @@ const sha1 = require('js-sha1'); const btoa = require('btoa'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { @@ -17,11 +22,6 @@ const { removeUndefinedAndNullValues, isDefinedAndNotNullAndNotEmpty, } = require('../../util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); /** * This function takes the transformed payload, endpoint and destination Config as input and returns the prepared response. diff --git a/src/v0/destinations/indicative/transform.js b/src/v0/destinations/indicative/transform.js index 81eb19f320..000998c3b8 100644 --- a/src/v0/destinations/indicative/transform.js +++ b/src/v0/destinations/indicative/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { @@ -9,7 +10,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { getUAInfo } = require('./utils'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const handleProperties = (properties) => { diff --git a/src/v0/destinations/intercom/deleteUsers.js b/src/v0/destinations/intercom/deleteUsers.js index 9241a22906..e11d352117 100644 --- a/src/v0/destinations/intercom/deleteUsers.js +++ b/src/v0/destinations/intercom/deleteUsers.js @@ -1,8 +1,8 @@ +const { NetworkError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, ConfigurationError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/intercom/networkHandler.js b/src/v0/destinations/intercom/networkHandler.js index 33f78e8cf6..a4106257b3 100644 --- a/src/v0/destinations/intercom/networkHandler.js +++ b/src/v0/destinations/intercom/networkHandler.js @@ -1,8 +1,7 @@ +const { RetryableError } = require('@rudderstack/integrations-lib'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); -const { RetryableError } = require('../../util/errorTypes'); - const errorResponseHandler = (destinationResponse, dest) => { const { status } = destinationResponse; if (status === 408) { diff --git a/src/v0/destinations/intercom/transform.js b/src/v0/destinations/intercom/transform.js index 552c80527c..212eaba13b 100644 --- a/src/v0/destinations/intercom/transform.js +++ b/src/v0/destinations/intercom/transform.js @@ -1,5 +1,6 @@ const md5 = require('md5'); const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { ConfigCategory, @@ -18,7 +19,6 @@ const { flattenJson, } = require('../../util'); const { separateReservedAndRestMetadata } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function getCompanyAttribute(company) { diff --git a/src/v0/destinations/iterable/deleteUsers.js b/src/v0/destinations/iterable/deleteUsers.js index 834cccd4cb..a179a8930f 100644 --- a/src/v0/destinations/iterable/deleteUsers.js +++ b/src/v0/destinations/iterable/deleteUsers.js @@ -1,8 +1,8 @@ +const { NetworkError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { httpDELETE } = require('../../../adapters/network'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, ConfigurationError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/iterable/transform.js b/src/v0/destinations/iterable/transform.js index c54b579a52..64bdcfcfa4 100644 --- a/src/v0/destinations/iterable/transform.js +++ b/src/v0/destinations/iterable/transform.js @@ -1,5 +1,6 @@ const lodash = require('lodash'); const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getCatalogEndpoint, hasMultipleResponses, @@ -26,7 +27,6 @@ const { } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { mappingConfig, ConfigCategory } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const { EventType, MappedToDestinationKey } = require('../../../constants'); /** diff --git a/src/v0/destinations/iterable/util.js b/src/v0/destinations/iterable/util.js index 0b7e402f01..7c1509c2b7 100644 --- a/src/v0/destinations/iterable/util.js +++ b/src/v0/destinations/iterable/util.js @@ -1,6 +1,7 @@ const lodash = require('lodash'); const get = require('get-value'); const jsonSize = require('json-size'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { isAppleFamily, constructPayload, @@ -20,7 +21,6 @@ const { } = require('./config'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { EventType, MappedToDestinationKey } = require('../../../constants'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const MESSAGE_JSON_PATH = 'message.body.JSON'; diff --git a/src/v0/destinations/june/transform.js b/src/v0/destinations/june/transform.js index f85cb0fd3d..c8f3206903 100644 --- a/src/v0/destinations/june/transform.js +++ b/src/v0/destinations/june/transform.js @@ -1,3 +1,4 @@ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { isEmptyObject, constructPayload, @@ -10,7 +11,6 @@ const { const { EventType } = require('../../../constants'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = (payload, endpoint, destination) => { const destPayload = payload; diff --git a/src/v0/destinations/kafka/transform.js b/src/v0/destinations/kafka/transform.js index 39334b5f52..b08c717475 100644 --- a/src/v0/destinations/kafka/transform.js +++ b/src/v0/destinations/kafka/transform.js @@ -8,7 +8,6 @@ const { getSuccessRespEvents, getErrorRespEvents, } = require('../../util'); -// const { InstrumentationError } = require("../../util/errorTypes"); const filterConfigTopics = (message, destination) => { const { Config } = destination; diff --git a/src/v0/destinations/keen/transform.js b/src/v0/destinations/keen/transform.js index 6d99c90dcc..b68b5e5e1d 100644 --- a/src/v0/destinations/keen/transform.js +++ b/src/v0/destinations/keen/transform.js @@ -2,6 +2,7 @@ /* eslint-disable no-nested-ternary */ const isIp = require('is-ip'); const validUrl = require('valid-url'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultPostRequestConfig, @@ -10,7 +11,6 @@ const { getFieldValueFromMessage, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { ENDPOINT } = require('./config'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/kissmetrics/transform.js b/src/v0/destinations/kissmetrics/transform.js index 3e2c5593de..b24395076c 100644 --- a/src/v0/destinations/kissmetrics/transform.js +++ b/src/v0/destinations/kissmetrics/transform.js @@ -9,6 +9,7 @@ const is = require('is'); const extend = require('@ndhoule/extend'); const each = require('component-each'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultGetRequestConfig, @@ -17,7 +18,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { ENDPOINT } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); // source : https://github.com/segment-integrations/analytics.js-integration-kissmetrics/blob/master/lib/index.js function toUnixTimestamp(date) { diff --git a/src/v0/destinations/klaviyo/transform.js b/src/v0/destinations/klaviyo/transform.js index 5ad9b1869d..9273b6a048 100644 --- a/src/v0/destinations/klaviyo/transform.js +++ b/src/v0/destinations/klaviyo/transform.js @@ -2,6 +2,7 @@ /* eslint-disable no-underscore-dangle */ /* eslint-disable array-callback-return */ const get = require('get-value'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType, WhiteListedTraits, MappedToDestinationKey } = require('../../../constants'); const { CONFIG_CATEGORIES, @@ -36,7 +37,6 @@ const { flattenJson, isNewStatusCodesAccepted, } = require('../../util'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); /** @@ -93,6 +93,10 @@ const identifyRequestHandler = async (message, category, destination, reqMetadat data.attributes.properties = flattenProperties ? flattenJson(data.attributes.properties, '.', 'normal', false) : data.attributes.properties; + + if (isEmptyObject(data.attributes.properties)) { + delete data.attributes.properties; + } const payload = { data: removeUndefinedAndNullValues(data), }; @@ -373,8 +377,9 @@ const processRouterDest = async (inputs, reqMetadata) => { eventDestination, false, HTTP_STATUS_CODES.SUPPRESS_EVENTS, - ), error - } + ), + error, + }; } return getSuccessRespEvents(message, [metadata], eventDestination); }); diff --git a/src/v0/destinations/klaviyo/util.js b/src/v0/destinations/klaviyo/util.js index 4304edd78f..60b334f3a2 100644 --- a/src/v0/destinations/klaviyo/util.js +++ b/src/v0/destinations/klaviyo/util.js @@ -1,5 +1,6 @@ const { defaultRequestConfig } = require('rudder-transformer-cdk/build/utils'); const lodash = require('lodash'); +const { NetworkError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { WhiteListedTraits } = require('../../../constants'); const { @@ -15,9 +16,7 @@ const { const tags = require('../../util/tags'); const { handleHttpRequest } = require('../../../adapters/network'); const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); -const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const { client: errNotificationClient } = require('../../../util/errorNotifier'); const { BASE_ENDPOINT, MAPPING_CONFIG, CONFIG_CATEGORIES, MAX_BATCH_SIZE } = require('./config'); const REVISION_CONSTANT = '2023-02-22'; @@ -69,11 +68,6 @@ const getIdFromNewOrExistingProfile = async (endpoint, payload, requestOptions) let statusCode = resp.status; if (resp.status === 201 || resp.status === 409) { // retryable error if the profile id is not found in the response - errNotificationClient.notify( - new Error('Klaviyo: ProfileId not found'), - 'Profile Id not Found in the response', - JSON.stringify(resp.response), - ); statusCode = 500; } diff --git a/src/v0/destinations/kochava/transform.js b/src/v0/destinations/kochava/transform.js index c5a4fec81f..e9cf2eb1a0 100644 --- a/src/v0/destinations/kochava/transform.js +++ b/src/v0/destinations/kochava/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { KOCHAVA_ENDPOINT, @@ -11,7 +12,6 @@ const { formatTimeStamp, isAppleFamily, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); // build final response // -------------------- diff --git a/src/v0/destinations/kustomer/transform.js b/src/v0/destinations/kustomer/transform.js index 2898f0dfc2..e5010f55e0 100644 --- a/src/v0/destinations/kustomer/transform.js +++ b/src/v0/destinations/kustomer/transform.js @@ -1,5 +1,6 @@ /* eslint-disable no-nested-ternary */ const get = require('get-value'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, DEFAULT_BASE_ENDPOINT } = require('./config'); const { @@ -13,7 +14,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { fetchKustomer, handleAdvancedtransformations } = require('./util'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); // Function responsible for constructing the Kustomer (User) Payload for identify diff --git a/src/v0/destinations/kustomer/util.js b/src/v0/destinations/kustomer/util.js index 31157b2738..571a03f139 100644 --- a/src/v0/destinations/kustomer/util.js +++ b/src/v0/destinations/kustomer/util.js @@ -2,11 +2,11 @@ const lodash = require('lodash'); const set = require('set-value'); const get = require('get-value'); +const { NetworkError, AbortedError } = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { DEFAULT_BASE_ENDPOINT } = require('./config'); const { getType, isDefinedAndNotNull, isObject } = require('../../util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, AbortedError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); /** diff --git a/src/v0/destinations/lambda/transform.js b/src/v0/destinations/lambda/transform.js index 221ef18186..1570a69ec3 100644 --- a/src/v0/destinations/lambda/transform.js +++ b/src/v0/destinations/lambda/transform.js @@ -1,6 +1,6 @@ const _ = require('lodash'); const { getErrorRespEvents, getSuccessRespEvents } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const DEFAULT_INVOCATION_TYPE = 'Event'; // asynchronous invocation const MAX_PAYLOAD_SIZE_IN_KB = 256; // only for asynchronous invocation diff --git a/src/v0/destinations/leanplum/transform.js b/src/v0/destinations/leanplum/transform.js index 9a5462f2e5..df075dd631 100644 --- a/src/v0/destinations/leanplum/transform.js +++ b/src/v0/destinations/leanplum/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ConfigCategory, mappingConfig, ENDPOINT, API_VERSION } = require('./config'); const { @@ -7,7 +8,6 @@ const { constructPayload, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function preparePayload(message, name, destination) { diff --git a/src/v0/destinations/lemnisk/transform.js b/src/v0/destinations/lemnisk/transform.js index 1d6d9a89fb..905199079b 100644 --- a/src/v0/destinations/lemnisk/transform.js +++ b/src/v0/destinations/lemnisk/transform.js @@ -1,3 +1,8 @@ +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, @@ -14,11 +19,6 @@ const { isDefinedAndNotNullAndNotEmpty, } = require('../../util'); const { fetchPlatform } = require('./utils'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (message, category, destination, platform) => { diff --git a/src/v0/destinations/lemnisk/utils.js b/src/v0/destinations/lemnisk/utils.js index 207122153d..28de9ab354 100644 --- a/src/v0/destinations/lemnisk/utils.js +++ b/src/v0/destinations/lemnisk/utils.js @@ -1,4 +1,4 @@ -const { ConfigurationError } = require('../../util/errorTypes'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); /** * Fetches the platform type from the destination Config diff --git a/src/v0/destinations/lytics/transform.js b/src/v0/destinations/lytics/transform.js index a8d489fa5f..c3a971adba 100644 --- a/src/v0/destinations/lytics/transform.js +++ b/src/v0/destinations/lytics/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, @@ -14,7 +15,6 @@ const { flattenJson, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilderSimple = (message, category, destination) => { diff --git a/src/v0/destinations/mailchimp/transform.js b/src/v0/destinations/mailchimp/transform.js index ced92ddea1..894f70672a 100644 --- a/src/v0/destinations/mailchimp/transform.js +++ b/src/v0/destinations/mailchimp/transform.js @@ -1,4 +1,5 @@ const lodash = require('lodash'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { defaultPutRequestConfig, handleRtTfSingleEventError, @@ -23,7 +24,6 @@ const { stringifyPropertiesValues, } = require('./utils'); const { MAX_BATCH_SIZE, VALID_STATUSES, TRACK_CONFIG } = require('./config'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilderSimple = (finalPayload, endpoint, Config, audienceId) => { diff --git a/src/v0/destinations/mailchimp/utils.js b/src/v0/destinations/mailchimp/utils.js index 5a6d62c72c..e1e2e9883b 100644 --- a/src/v0/destinations/mailchimp/utils.js +++ b/src/v0/destinations/mailchimp/utils.js @@ -1,5 +1,6 @@ const get = require('get-value'); const md5 = require('md5'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { MappedToDestinationKey } = require('../../../constants'); const logger = require('../../../logger'); @@ -15,7 +16,6 @@ const { defaultBatchRequestConfig, constructPayload, } = require('../../util'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const { MERGE_CONFIG, MERGE_ADDRESS, SUBSCRIPTION_STATUS, VALID_STATUSES } = require('./config'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); diff --git a/src/v0/destinations/mailjet/transform.js b/src/v0/destinations/mailjet/transform.js index 3e3cfe5c81..9156bf45e9 100644 --- a/src/v0/destinations/mailjet/transform.js +++ b/src/v0/destinations/mailjet/transform.js @@ -1,4 +1,5 @@ const lodash = require('lodash'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { getErrorRespEvents, getSuccessRespEvents, @@ -12,7 +13,6 @@ const { const { MAX_BATCH_SIZE } = require('./config'); const { EventType } = require('../../../constants'); const { createOrUpdateContactResponseBuilder } = require('./utils'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload) => { diff --git a/src/v0/destinations/mailmodo/transform.js b/src/v0/destinations/mailmodo/transform.js index 39783c864f..756522939d 100644 --- a/src/v0/destinations/mailmodo/transform.js +++ b/src/v0/destinations/mailmodo/transform.js @@ -1,6 +1,7 @@ const lodash = require('lodash'); const get = require('get-value'); const { isEmpty } = require('lodash'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ConfigCategory, IDENTIFY_MAX_BATCH_SIZE, mappingConfig, BASE_URL } = require('./config'); const { @@ -14,7 +15,6 @@ const { handleRtTfSingleEventError, } = require('../../util'); const { deduceAddressFields, extractCustomProperties } = require('./utils'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (responseConfgs) => { diff --git a/src/v0/destinations/marketo/config.js b/src/v0/destinations/marketo/config.js index 5d70cc0425..604be41dc0 100644 --- a/src/v0/destinations/marketo/config.js +++ b/src/v0/destinations/marketo/config.js @@ -14,24 +14,18 @@ const DESTINATION = 'marketo'; const formatConfig = (destination) => ({ ID: destination.ID, ...destination.Config, - customActivityEventMap: getHashFromArray( - destination.Config.customActivityEventMap, - 'from', - 'to', - false, - ), + customActivityEventMap: destination.Config?.rudderEventsMapping + ? getHashFromArray(destination.Config.rudderEventsMapping, 'event', 'marketoActivityId', false) + : getHashFromArray(destination.Config.customActivityEventMap, 'from', 'to', false), customActivityPropertyMap: getHashFromArray( destination.Config.customActivityPropertyMap, 'from', 'to', false, ), - customActivityPrimaryKeyMap: getHashFromArray( - destination.Config.customActivityPrimaryKeyMap, - 'from', - 'to', - false, - ), + customActivityPrimaryKeyMap: destination.Config?.rudderEventsMapping + ? getHashFromArray(destination.Config.rudderEventsMapping, 'event', 'marketoPrimarykey', false) + : getHashFromArray(destination.Config.customActivityPrimaryKeyMap, 'from', 'to', false), leadTraitMapping: getHashFromArray(destination.Config.leadTraitMapping, 'from', 'to', false), responseRules: destination.DestinationDefinition ? destination.DestinationDefinition.ResponseRules diff --git a/src/v0/destinations/marketo/transform.js b/src/v0/destinations/marketo/transform.js index b23d992b64..5000ef506b 100644 --- a/src/v0/destinations/marketo/transform.js +++ b/src/v0/destinations/marketo/transform.js @@ -3,6 +3,11 @@ /* eslint-disable no-use-before-define */ const get = require('get-value'); const cloneDeep = require('lodash/cloneDeep'); +const { + InstrumentationError, + ConfigurationError, + UnauthorizedError, +} = require('@rudderstack/integrations-lib'); const stats = require('../../../util/stats'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { @@ -38,11 +43,6 @@ const { getResponseHandlerData, } = require('./util'); const logger = require('../../../logger'); -const { - InstrumentationError, - ConfigurationError, - UnauthorizedError, -} = require('../../util/errorTypes'); const userIdLeadCache = new Cache(USER_LEAD_CACHE_TTL); // 1 day const emailLeadCache = new Cache(USER_LEAD_CACHE_TTL); // 1 day diff --git a/src/v0/destinations/marketo/util.js b/src/v0/destinations/marketo/util.js index 0de14e2072..203e0bf859 100644 --- a/src/v0/destinations/marketo/util.js +++ b/src/v0/destinations/marketo/util.js @@ -1,9 +1,3 @@ -const { httpGET, httpPOST } = require('../../../adapters/network'); -const { - getDynamicErrorType, - processAxiosResponse, -} = require('../../../adapters/utils/networkUtils'); -const { isHttpStatusSuccess } = require('../../util/index'); const { NetworkError, AbortedError, @@ -11,7 +5,13 @@ const { RetryableError, UnhandledStatusCodeError, InstrumentationError, -} = require('../../util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const { httpGET, httpPOST } = require('../../../adapters/network'); +const { + getDynamicErrorType, + processAxiosResponse, +} = require('../../../adapters/utils/networkUtils'); +const { isHttpStatusSuccess } = require('../../util/index'); const tags = require('../../util/tags'); /** diff --git a/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js b/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js index 04eadc4c51..e6f5662000 100644 --- a/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js +++ b/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js @@ -1,8 +1,8 @@ /* eslint-disable no-restricted-syntax */ /* eslint-disable no-prototype-builtins */ +const { PlatformError } = require('@rudderstack/integrations-lib'); const { getAccessToken } = require('./util'); const { handleHttpRequest } = require('../../../adapters/network'); -const { PlatformError } = require('../../util/errorTypes'); const stats = require('../../../util/stats'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { diff --git a/src/v0/destinations/marketo_bulk_upload/fileUpload.js b/src/v0/destinations/marketo_bulk_upload/fileUpload.js index 2c77cd6e29..c7212ff9cb 100644 --- a/src/v0/destinations/marketo_bulk_upload/fileUpload.js +++ b/src/v0/destinations/marketo_bulk_upload/fileUpload.js @@ -1,6 +1,12 @@ /* eslint-disable no-plusplus */ const FormData = require('form-data'); const fs = require('fs'); +const { + NetworkError, + ConfigurationError, + RetryableError, + TransformationError, +} = require('@rudderstack/integrations-lib'); const { getAccessToken, getMarketoFilePath, @@ -16,12 +22,6 @@ const { isDefinedAndNotNullAndNotEmpty, } = require('../../util'); const { handleHttpRequest } = require('../../../adapters/network'); -const { - NetworkError, - ConfigurationError, - RetryableError, - TransformationError, -} = require('../../util/errorTypes'); const { client } = require('../../../util/errorNotifier'); const stats = require('../../../util/stats'); diff --git a/src/v0/destinations/marketo_bulk_upload/marketo_bulk_upload.util.test.js b/src/v0/destinations/marketo_bulk_upload/marketo_bulk_upload.util.test.js index 777301b6c3..78ac7c9e48 100644 --- a/src/v0/destinations/marketo_bulk_upload/marketo_bulk_upload.util.test.js +++ b/src/v0/destinations/marketo_bulk_upload/marketo_bulk_upload.util.test.js @@ -4,7 +4,7 @@ const { handleFileUploadResponse, } = require('./util'); -const { AbortedError, RetryableError } = require('../../util/errorTypes'); +const { AbortedError, RetryableError } = require('@rudderstack/integrations-lib'); describe('handleCommonErrorResponse', () => { test('should throw AbortedError for abortable error codes', () => { diff --git a/src/v0/destinations/marketo_bulk_upload/poll.js b/src/v0/destinations/marketo_bulk_upload/poll.js index 5e37fd7c0e..3ad458c545 100644 --- a/src/v0/destinations/marketo_bulk_upload/poll.js +++ b/src/v0/destinations/marketo_bulk_upload/poll.js @@ -1,8 +1,8 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { removeUndefinedValues, isHttpStatusSuccess } = require('../../util'); const { getAccessToken, handlePollResponse, hydrateStatusForServer } = require('./util'); const { handleHttpRequest } = require('../../../adapters/network'); const stats = require('../../../util/stats'); -const { NetworkError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { POLL_ACTIVITY } = require('./config'); diff --git a/src/v0/destinations/marketo_bulk_upload/transform.js b/src/v0/destinations/marketo_bulk_upload/transform.js index d5764ee6c3..5431e67d38 100644 --- a/src/v0/destinations/marketo_bulk_upload/transform.js +++ b/src/v0/destinations/marketo_bulk_upload/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getHashFromArray, getFieldValueFromMessage, @@ -5,7 +6,6 @@ const { defaultRequestConfig, } = require('../../util'); const { EventType } = require('../../../constants'); -const { InstrumentationError } = require('../../util/errorTypes'); function responseBuilderSimple(message, destination) { const payload = {}; diff --git a/src/v0/destinations/marketo_bulk_upload/util.js b/src/v0/destinations/marketo_bulk_upload/util.js index a60f57e50b..7b329a3441 100644 --- a/src/v0/destinations/marketo_bulk_upload/util.js +++ b/src/v0/destinations/marketo_bulk_upload/util.js @@ -1,10 +1,10 @@ -const { handleHttpRequest } = require('../../../adapters/network'); const { AbortedError, RetryableError, NetworkError, TransformationError, -} = require('../../util/errorTypes'); +} = require('@rudderstack/integrations-lib'); +const { handleHttpRequest } = require('../../../adapters/network'); const tags = require('../../util/tags'); const { isHttpStatusSuccess, generateUUID } = require('../../util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); diff --git a/src/v0/destinations/marketo_static_list/testData/constants.js b/src/v0/destinations/marketo_static_list/testData/constants.js new file mode 100644 index 0000000000..2c420c6bc2 --- /dev/null +++ b/src/v0/destinations/marketo_static_list/testData/constants.js @@ -0,0 +1,45 @@ +const EXTERNAL_ID = 'marketoStaticListId'; +const TOKEN = 'Bearer access_token_success'; +const CONTENT_TYPE = 'application/json'; +const DEST_CONFIG = { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1234, +}; +const DEST_DEFINITION = { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', +}; +const DEST_OBJECT = { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: DEST_DEFINITION, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, +}; +const MESSAGE_SOURCES_CONTEXT = { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', +}; + +module.exports = { + EXTERNAL_ID, + TOKEN, + CONTENT_TYPE, + DEST_OBJECT, + DEST_DEFINITION, + MESSAGE_SOURCES_CONTEXT, + DEST_CONFIG, +}; diff --git a/src/v0/destinations/marketo_static_list/testData/testData.js b/src/v0/destinations/marketo_static_list/testData/testData.js new file mode 100644 index 0000000000..45328436ce --- /dev/null +++ b/src/v0/destinations/marketo_static_list/testData/testData.js @@ -0,0 +1,3085 @@ +const { + EXTERNAL_ID, + TOKEN, + CONTENT_TYPE, + DEST_OBJECT, + DEST_DEFINITION, + MESSAGE_SOURCES_CONTEXT, + DEST_CONFIG, +} = require('./constants'); + +const recordInputs = [ + { + destination: DEST_OBJECT, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1001, + }, + channel: 'sources', + context: { + sources: MESSAGE_SOURCES_CONTEXT, + externalId: [ + { + type: EXTERNAL_ID, + id: 'id001', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 1, + }, + }, + { + destination: DEST_OBJECT, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1002, + }, + channel: 'sources', + context: { + sources: MESSAGE_SOURCES_CONTEXT, + externalId: [ + { + type: EXTERNAL_ID, + id: 'id002', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 2, + }, + }, + { + destination: DEST_OBJECT, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1003, + }, + channel: 'sources', + context: { + sources: MESSAGE_SOURCES_CONTEXT, + externalId: [ + { + type: EXTERNAL_ID, + id: 'id001', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 3, + }, + }, + { + destination: DEST_OBJECT, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + id: 'id002', + type: EXTERNAL_ID, + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2001', + }, + type: 'record', + }, + metadata: { + jobId: 4, + }, + }, +]; + +const recordOutput = [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id001/leads.json?id=1001&id=1003', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 1, + }, + { + jobId: 3, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=2001', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=1002', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 2, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, +]; + +const audiencelistInputs = [ + { + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo', + DestinationDefinition: DEST_DEFINITION, + Config: DEST_CONFIG, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + userId: 'user 1', + anonymousId: 'anon-id-new', + event: 'event1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + id: 501, + }, + { + id: 502, + }, + { + id: 503, + }, + ], + remove: [ + { + id: 704, + }, + { + id: 705, + }, + { + id: 706, + }, + ], + }, + enablePartialFailure: true, + }, + context: { + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 1, + }, + }, + { + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo', + DestinationDefinition: DEST_DEFINITION, + Config: DEST_CONFIG, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + userId: 'user 1', + anonymousId: 'anon-id-new', + event: 'event1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + id: 0, + }, + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + { + id: 4, + }, + { + id: 5, + }, + { + id: 6, + }, + { + id: 7, + }, + { + id: 8, + }, + { + id: 9, + }, + { + id: 10, + }, + { + id: 11, + }, + { + id: 12, + }, + { + id: 13, + }, + { + id: 14, + }, + { + id: 15, + }, + { + id: 16, + }, + { + id: 17, + }, + { + id: 18, + }, + { + id: 19, + }, + { + id: 20, + }, + { + id: 21, + }, + { + id: 22, + }, + { + id: 23, + }, + { + id: 24, + }, + { + id: 25, + }, + { + id: 26, + }, + { + id: 27, + }, + { + id: 28, + }, + { + id: 29, + }, + { + id: 30, + }, + { + id: 31, + }, + { + id: 32, + }, + { + id: 33, + }, + { + id: 34, + }, + { + id: 35, + }, + { + id: 36, + }, + { + id: 37, + }, + { + id: 38, + }, + { + id: 39, + }, + { + id: 40, + }, + { + id: 41, + }, + { + id: 42, + }, + { + id: 43, + }, + { + id: 44, + }, + { + id: 45, + }, + { + id: 46, + }, + { + id: 47, + }, + { + id: 48, + }, + { + id: 49, + }, + { + id: 50, + }, + { + id: 51, + }, + { + id: 52, + }, + { + id: 53, + }, + { + id: 54, + }, + { + id: 55, + }, + { + id: 56, + }, + { + id: 57, + }, + { + id: 58, + }, + { + id: 59, + }, + { + id: 60, + }, + { + id: 61, + }, + { + id: 62, + }, + { + id: 63, + }, + { + id: 64, + }, + { + id: 65, + }, + { + id: 66, + }, + { + id: 67, + }, + { + id: 68, + }, + { + id: 69, + }, + { + id: 70, + }, + { + id: 71, + }, + { + id: 72, + }, + { + id: 73, + }, + { + id: 74, + }, + { + id: 75, + }, + { + id: 76, + }, + { + id: 77, + }, + { + id: 78, + }, + { + id: 79, + }, + { + id: 80, + }, + { + id: 81, + }, + { + id: 82, + }, + { + id: 83, + }, + { + id: 84, + }, + { + id: 85, + }, + { + id: 86, + }, + { + id: 87, + }, + { + id: 88, + }, + { + id: 89, + }, + { + id: 90, + }, + { + id: 91, + }, + { + id: 92, + }, + { + id: 93, + }, + { + id: 94, + }, + { + id: 95, + }, + { + id: 96, + }, + { + id: 97, + }, + { + id: 98, + }, + { + id: 99, + }, + { + id: 100, + }, + { + id: 101, + }, + { + id: 102, + }, + { + id: 103, + }, + { + id: 104, + }, + { + id: 105, + }, + { + id: 106, + }, + { + id: 107, + }, + { + id: 108, + }, + { + id: 109, + }, + { + id: 110, + }, + { + id: 111, + }, + { + id: 112, + }, + { + id: 113, + }, + { + id: 114, + }, + { + id: 115, + }, + { + id: 116, + }, + { + id: 117, + }, + { + id: 118, + }, + { + id: 119, + }, + { + id: 120, + }, + { + id: 121, + }, + { + id: 122, + }, + { + id: 123, + }, + { + id: 124, + }, + { + id: 125, + }, + { + id: 126, + }, + { + id: 127, + }, + { + id: 128, + }, + { + id: 129, + }, + { + id: 130, + }, + { + id: 131, + }, + { + id: 132, + }, + { + id: 133, + }, + { + id: 134, + }, + { + id: 135, + }, + { + id: 136, + }, + { + id: 137, + }, + { + id: 138, + }, + { + id: 139, + }, + { + id: 140, + }, + { + id: 141, + }, + { + id: 142, + }, + { + id: 143, + }, + { + id: 144, + }, + { + id: 145, + }, + { + id: 146, + }, + { + id: 147, + }, + { + id: 148, + }, + { + id: 149, + }, + { + id: 150, + }, + { + id: 151, + }, + { + id: 152, + }, + { + id: 153, + }, + { + id: 154, + }, + { + id: 155, + }, + { + id: 156, + }, + { + id: 157, + }, + { + id: 158, + }, + { + id: 159, + }, + { + id: 160, + }, + { + id: 161, + }, + { + id: 162, + }, + { + id: 163, + }, + { + id: 164, + }, + { + id: 165, + }, + { + id: 166, + }, + { + id: 167, + }, + { + id: 168, + }, + { + id: 169, + }, + { + id: 170, + }, + { + id: 171, + }, + { + id: 172, + }, + { + id: 173, + }, + { + id: 174, + }, + { + id: 175, + }, + { + id: 176, + }, + { + id: 177, + }, + { + id: 178, + }, + { + id: 179, + }, + { + id: 180, + }, + { + id: 181, + }, + { + id: 182, + }, + { + id: 183, + }, + { + id: 184, + }, + { + id: 185, + }, + { + id: 186, + }, + { + id: 187, + }, + { + id: 188, + }, + { + id: 189, + }, + { + id: 190, + }, + { + id: 191, + }, + { + id: 192, + }, + { + id: 193, + }, + { + id: 194, + }, + { + id: 195, + }, + { + id: 196, + }, + { + id: 197, + }, + { + id: 198, + }, + { + id: 199, + }, + { + id: 200, + }, + { + id: 201, + }, + { + id: 202, + }, + { + id: 203, + }, + { + id: 204, + }, + { + id: 205, + }, + { + id: 206, + }, + { + id: 207, + }, + { + id: 208, + }, + { + id: 209, + }, + { + id: 210, + }, + { + id: 211, + }, + { + id: 212, + }, + { + id: 213, + }, + { + id: 214, + }, + { + id: 215, + }, + { + id: 216, + }, + { + id: 217, + }, + { + id: 218, + }, + { + id: 219, + }, + { + id: 220, + }, + { + id: 221, + }, + { + id: 222, + }, + { + id: 223, + }, + { + id: 224, + }, + { + id: 225, + }, + { + id: 226, + }, + { + id: 227, + }, + { + id: 228, + }, + { + id: 229, + }, + { + id: 230, + }, + { + id: 231, + }, + { + id: 232, + }, + { + id: 233, + }, + { + id: 234, + }, + { + id: 235, + }, + { + id: 236, + }, + { + id: 237, + }, + { + id: 238, + }, + { + id: 239, + }, + { + id: 240, + }, + { + id: 241, + }, + { + id: 242, + }, + { + id: 243, + }, + { + id: 244, + }, + { + id: 245, + }, + { + id: 246, + }, + { + id: 247, + }, + { + id: 248, + }, + { + id: 249, + }, + { + id: 250, + }, + { + id: 251, + }, + { + id: 252, + }, + { + id: 253, + }, + { + id: 254, + }, + { + id: 255, + }, + { + id: 256, + }, + { + id: 257, + }, + { + id: 258, + }, + { + id: 259, + }, + { + id: 260, + }, + { + id: 261, + }, + { + id: 262, + }, + { + id: 263, + }, + { + id: 264, + }, + { + id: 265, + }, + { + id: 266, + }, + { + id: 267, + }, + { + id: 268, + }, + { + id: 269, + }, + { + id: 270, + }, + { + id: 271, + }, + { + id: 272, + }, + { + id: 273, + }, + { + id: 274, + }, + { + id: 275, + }, + { + id: 276, + }, + { + id: 277, + }, + { + id: 278, + }, + { + id: 279, + }, + { + id: 280, + }, + { + id: 281, + }, + { + id: 282, + }, + { + id: 283, + }, + { + id: 284, + }, + { + id: 285, + }, + { + id: 286, + }, + { + id: 287, + }, + { + id: 288, + }, + { + id: 289, + }, + { + id: 290, + }, + { + id: 291, + }, + { + id: 292, + }, + { + id: 293, + }, + { + id: 294, + }, + { + id: 295, + }, + { + id: 296, + }, + { + id: 297, + }, + { + id: 298, + }, + { + id: 299, + }, + { + id: 300, + }, + { + id: 301, + }, + { + id: 302, + }, + { + id: 303, + }, + { + id: 304, + }, + { + id: 305, + }, + { + id: 306, + }, + { + id: 307, + }, + { + id: 308, + }, + { + id: 309, + }, + { + id: 310, + }, + { + id: 311, + }, + { + id: 312, + }, + { + id: 313, + }, + { + id: 314, + }, + { + id: 315, + }, + { + id: 316, + }, + { + id: 317, + }, + { + id: 318, + }, + { + id: 319, + }, + { + id: 320, + }, + { + id: 321, + }, + { + id: 322, + }, + { + id: 323, + }, + { + id: 324, + }, + { + id: 325, + }, + { + id: 326, + }, + { + id: 327, + }, + { + id: 328, + }, + { + id: 329, + }, + { + id: 330, + }, + { + id: 331, + }, + { + id: 332, + }, + { + id: 333, + }, + { + id: 334, + }, + { + id: 335, + }, + { + id: 336, + }, + { + id: 337, + }, + { + id: 338, + }, + { + id: 339, + }, + { + id: 340, + }, + { + id: 341, + }, + { + id: 342, + }, + { + id: 343, + }, + { + id: 344, + }, + { + id: 345, + }, + { + id: 346, + }, + { + id: 347, + }, + { + id: 348, + }, + { + id: 349, + }, + { + id: 350, + }, + ], + }, + enablePartialFailure: true, + }, + context: { + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 2, + }, + }, +]; + +const reqMetadata = { + namespace: 'Unknown', + cluster: 'Unknown', + features: {}, +}; + +const largeRecordOutput = [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=351&id=352&id=353&id=354&id=355&id=356&id=357&id=358&id=359&id=360&id=361&id=362&id=363&id=364&id=365&id=366&id=367&id=368&id=369&id=370&id=371&id=372&id=373&id=374&id=375&id=376&id=377&id=378&id=379&id=380&id=381&id=382&id=383&id=384&id=385&id=386&id=387&id=388&id=389&id=390&id=391&id=392&id=393&id=394&id=395&id=396&id=397&id=398&id=399&id=400&id=401&id=402&id=403&id=404&id=405&id=406&id=407&id=408&id=409&id=410&id=411&id=412&id=413&id=414&id=415&id=416&id=417&id=418&id=419&id=420&id=421&id=422&id=423&id=424&id=425&id=426&id=427&id=428&id=429&id=430&id=431&id=432&id=433&id=434&id=435&id=436&id=437&id=438&id=439&id=440&id=441&id=442&id=443&id=444&id=445&id=446&id=447&id=448&id=449&id=450', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 351, + }, + { + jobId: 352, + }, + { + jobId: 353, + }, + { + jobId: 354, + }, + { + jobId: 355, + }, + { + jobId: 356, + }, + { + jobId: 357, + }, + { + jobId: 358, + }, + { + jobId: 359, + }, + { + jobId: 360, + }, + { + jobId: 361, + }, + { + jobId: 362, + }, + { + jobId: 363, + }, + { + jobId: 364, + }, + { + jobId: 365, + }, + { + jobId: 366, + }, + { + jobId: 367, + }, + { + jobId: 368, + }, + { + jobId: 369, + }, + { + jobId: 370, + }, + { + jobId: 371, + }, + { + jobId: 372, + }, + { + jobId: 373, + }, + { + jobId: 374, + }, + { + jobId: 375, + }, + { + jobId: 376, + }, + { + jobId: 377, + }, + { + jobId: 378, + }, + { + jobId: 379, + }, + { + jobId: 380, + }, + { + jobId: 381, + }, + { + jobId: 382, + }, + { + jobId: 383, + }, + { + jobId: 384, + }, + { + jobId: 385, + }, + { + jobId: 386, + }, + { + jobId: 387, + }, + { + jobId: 388, + }, + { + jobId: 389, + }, + { + jobId: 390, + }, + { + jobId: 391, + }, + { + jobId: 392, + }, + { + jobId: 393, + }, + { + jobId: 394, + }, + { + jobId: 395, + }, + { + jobId: 396, + }, + { + jobId: 397, + }, + { + jobId: 398, + }, + { + jobId: 399, + }, + { + jobId: 400, + }, + { + jobId: 401, + }, + { + jobId: 402, + }, + { + jobId: 403, + }, + { + jobId: 404, + }, + { + jobId: 405, + }, + { + jobId: 406, + }, + { + jobId: 407, + }, + { + jobId: 408, + }, + { + jobId: 409, + }, + { + jobId: 410, + }, + { + jobId: 411, + }, + { + jobId: 412, + }, + { + jobId: 413, + }, + { + jobId: 414, + }, + { + jobId: 415, + }, + { + jobId: 416, + }, + { + jobId: 417, + }, + { + jobId: 418, + }, + { + jobId: 419, + }, + { + jobId: 420, + }, + { + jobId: 421, + }, + { + jobId: 422, + }, + { + jobId: 423, + }, + { + jobId: 424, + }, + { + jobId: 425, + }, + { + jobId: 426, + }, + { + jobId: 427, + }, + { + jobId: 428, + }, + { + jobId: 429, + }, + { + jobId: 430, + }, + { + jobId: 431, + }, + { + jobId: 432, + }, + { + jobId: 433, + }, + { + jobId: 434, + }, + { + jobId: 435, + }, + { + jobId: 436, + }, + { + jobId: 437, + }, + { + jobId: 438, + }, + { + jobId: 439, + }, + { + jobId: 440, + }, + { + jobId: 441, + }, + { + jobId: 442, + }, + { + jobId: 443, + }, + { + jobId: 444, + }, + { + jobId: 445, + }, + { + jobId: 446, + }, + { + jobId: 447, + }, + { + jobId: 448, + }, + { + jobId: 449, + }, + { + jobId: 450, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299&id=300', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 1, + }, + { + jobId: 2, + }, + { + jobId: 3, + }, + { + jobId: 4, + }, + { + jobId: 5, + }, + { + jobId: 6, + }, + { + jobId: 7, + }, + { + jobId: 8, + }, + { + jobId: 9, + }, + { + jobId: 10, + }, + { + jobId: 11, + }, + { + jobId: 12, + }, + { + jobId: 13, + }, + { + jobId: 14, + }, + { + jobId: 15, + }, + { + jobId: 16, + }, + { + jobId: 17, + }, + { + jobId: 18, + }, + { + jobId: 19, + }, + { + jobId: 20, + }, + { + jobId: 21, + }, + { + jobId: 22, + }, + { + jobId: 23, + }, + { + jobId: 24, + }, + { + jobId: 25, + }, + { + jobId: 26, + }, + { + jobId: 27, + }, + { + jobId: 28, + }, + { + jobId: 29, + }, + { + jobId: 30, + }, + { + jobId: 31, + }, + { + jobId: 32, + }, + { + jobId: 33, + }, + { + jobId: 34, + }, + { + jobId: 35, + }, + { + jobId: 36, + }, + { + jobId: 37, + }, + { + jobId: 38, + }, + { + jobId: 39, + }, + { + jobId: 40, + }, + { + jobId: 41, + }, + { + jobId: 42, + }, + { + jobId: 43, + }, + { + jobId: 44, + }, + { + jobId: 45, + }, + { + jobId: 46, + }, + { + jobId: 47, + }, + { + jobId: 48, + }, + { + jobId: 49, + }, + { + jobId: 50, + }, + { + jobId: 51, + }, + { + jobId: 52, + }, + { + jobId: 53, + }, + { + jobId: 54, + }, + { + jobId: 55, + }, + { + jobId: 56, + }, + { + jobId: 57, + }, + { + jobId: 58, + }, + { + jobId: 59, + }, + { + jobId: 60, + }, + { + jobId: 61, + }, + { + jobId: 62, + }, + { + jobId: 63, + }, + { + jobId: 64, + }, + { + jobId: 65, + }, + { + jobId: 66, + }, + { + jobId: 67, + }, + { + jobId: 68, + }, + { + jobId: 69, + }, + { + jobId: 70, + }, + { + jobId: 71, + }, + { + jobId: 72, + }, + { + jobId: 73, + }, + { + jobId: 74, + }, + { + jobId: 75, + }, + { + jobId: 76, + }, + { + jobId: 77, + }, + { + jobId: 78, + }, + { + jobId: 79, + }, + { + jobId: 80, + }, + { + jobId: 81, + }, + { + jobId: 82, + }, + { + jobId: 83, + }, + { + jobId: 84, + }, + { + jobId: 85, + }, + { + jobId: 86, + }, + { + jobId: 87, + }, + { + jobId: 88, + }, + { + jobId: 89, + }, + { + jobId: 90, + }, + { + jobId: 91, + }, + { + jobId: 92, + }, + { + jobId: 93, + }, + { + jobId: 94, + }, + { + jobId: 95, + }, + { + jobId: 96, + }, + { + jobId: 97, + }, + { + jobId: 98, + }, + { + jobId: 99, + }, + { + jobId: 100, + }, + { + jobId: 101, + }, + { + jobId: 102, + }, + { + jobId: 103, + }, + { + jobId: 104, + }, + { + jobId: 105, + }, + { + jobId: 106, + }, + { + jobId: 107, + }, + { + jobId: 108, + }, + { + jobId: 109, + }, + { + jobId: 110, + }, + { + jobId: 111, + }, + { + jobId: 112, + }, + { + jobId: 113, + }, + { + jobId: 114, + }, + { + jobId: 115, + }, + { + jobId: 116, + }, + { + jobId: 117, + }, + { + jobId: 118, + }, + { + jobId: 119, + }, + { + jobId: 120, + }, + { + jobId: 121, + }, + { + jobId: 122, + }, + { + jobId: 123, + }, + { + jobId: 124, + }, + { + jobId: 125, + }, + { + jobId: 126, + }, + { + jobId: 127, + }, + { + jobId: 128, + }, + { + jobId: 129, + }, + { + jobId: 130, + }, + { + jobId: 131, + }, + { + jobId: 132, + }, + { + jobId: 133, + }, + { + jobId: 134, + }, + { + jobId: 135, + }, + { + jobId: 136, + }, + { + jobId: 137, + }, + { + jobId: 138, + }, + { + jobId: 139, + }, + { + jobId: 140, + }, + { + jobId: 141, + }, + { + jobId: 142, + }, + { + jobId: 143, + }, + { + jobId: 144, + }, + { + jobId: 145, + }, + { + jobId: 146, + }, + { + jobId: 147, + }, + { + jobId: 148, + }, + { + jobId: 149, + }, + { + jobId: 150, + }, + { + jobId: 151, + }, + { + jobId: 152, + }, + { + jobId: 153, + }, + { + jobId: 154, + }, + { + jobId: 155, + }, + { + jobId: 156, + }, + { + jobId: 157, + }, + { + jobId: 158, + }, + { + jobId: 159, + }, + { + jobId: 160, + }, + { + jobId: 161, + }, + { + jobId: 162, + }, + { + jobId: 163, + }, + { + jobId: 164, + }, + { + jobId: 165, + }, + { + jobId: 166, + }, + { + jobId: 167, + }, + { + jobId: 168, + }, + { + jobId: 169, + }, + { + jobId: 170, + }, + { + jobId: 171, + }, + { + jobId: 172, + }, + { + jobId: 173, + }, + { + jobId: 174, + }, + { + jobId: 175, + }, + { + jobId: 176, + }, + { + jobId: 177, + }, + { + jobId: 178, + }, + { + jobId: 179, + }, + { + jobId: 180, + }, + { + jobId: 181, + }, + { + jobId: 182, + }, + { + jobId: 183, + }, + { + jobId: 184, + }, + { + jobId: 185, + }, + { + jobId: 186, + }, + { + jobId: 187, + }, + { + jobId: 188, + }, + { + jobId: 189, + }, + { + jobId: 190, + }, + { + jobId: 191, + }, + { + jobId: 192, + }, + { + jobId: 193, + }, + { + jobId: 194, + }, + { + jobId: 195, + }, + { + jobId: 196, + }, + { + jobId: 197, + }, + { + jobId: 198, + }, + { + jobId: 199, + }, + { + jobId: 200, + }, + { + jobId: 201, + }, + { + jobId: 202, + }, + { + jobId: 203, + }, + { + jobId: 204, + }, + { + jobId: 205, + }, + { + jobId: 206, + }, + { + jobId: 207, + }, + { + jobId: 208, + }, + { + jobId: 209, + }, + { + jobId: 210, + }, + { + jobId: 211, + }, + { + jobId: 212, + }, + { + jobId: 213, + }, + { + jobId: 214, + }, + { + jobId: 215, + }, + { + jobId: 216, + }, + { + jobId: 217, + }, + { + jobId: 218, + }, + { + jobId: 219, + }, + { + jobId: 220, + }, + { + jobId: 221, + }, + { + jobId: 222, + }, + { + jobId: 223, + }, + { + jobId: 224, + }, + { + jobId: 225, + }, + { + jobId: 226, + }, + { + jobId: 227, + }, + { + jobId: 228, + }, + { + jobId: 229, + }, + { + jobId: 230, + }, + { + jobId: 231, + }, + { + jobId: 232, + }, + { + jobId: 233, + }, + { + jobId: 234, + }, + { + jobId: 235, + }, + { + jobId: 236, + }, + { + jobId: 237, + }, + { + jobId: 238, + }, + { + jobId: 239, + }, + { + jobId: 240, + }, + { + jobId: 241, + }, + { + jobId: 242, + }, + { + jobId: 243, + }, + { + jobId: 244, + }, + { + jobId: 245, + }, + { + jobId: 246, + }, + { + jobId: 247, + }, + { + jobId: 248, + }, + { + jobId: 249, + }, + { + jobId: 250, + }, + { + jobId: 251, + }, + { + jobId: 252, + }, + { + jobId: 253, + }, + { + jobId: 254, + }, + { + jobId: 255, + }, + { + jobId: 256, + }, + { + jobId: 257, + }, + { + jobId: 258, + }, + { + jobId: 259, + }, + { + jobId: 260, + }, + { + jobId: 261, + }, + { + jobId: 262, + }, + { + jobId: 263, + }, + { + jobId: 264, + }, + { + jobId: 265, + }, + { + jobId: 266, + }, + { + jobId: 267, + }, + { + jobId: 268, + }, + { + jobId: 269, + }, + { + jobId: 270, + }, + { + jobId: 271, + }, + { + jobId: 272, + }, + { + jobId: 273, + }, + { + jobId: 274, + }, + { + jobId: 275, + }, + { + jobId: 276, + }, + { + jobId: 277, + }, + { + jobId: 278, + }, + { + jobId: 279, + }, + { + jobId: 280, + }, + { + jobId: 281, + }, + { + jobId: 282, + }, + { + jobId: 283, + }, + { + jobId: 284, + }, + { + jobId: 285, + }, + { + jobId: 286, + }, + { + jobId: 287, + }, + { + jobId: 288, + }, + { + jobId: 289, + }, + { + jobId: 290, + }, + { + jobId: 291, + }, + { + jobId: 292, + }, + { + jobId: 293, + }, + { + jobId: 294, + }, + { + jobId: 295, + }, + { + jobId: 296, + }, + { + jobId: 297, + }, + { + jobId: 298, + }, + { + jobId: 299, + }, + { + jobId: 300, + }, + { + jobId: 301, + }, + { + jobId: 302, + }, + { + jobId: 303, + }, + { + jobId: 304, + }, + { + jobId: 305, + }, + { + jobId: 306, + }, + { + jobId: 307, + }, + { + jobId: 308, + }, + { + jobId: 309, + }, + { + jobId: 310, + }, + { + jobId: 311, + }, + { + jobId: 312, + }, + { + jobId: 313, + }, + { + jobId: 314, + }, + { + jobId: 315, + }, + { + jobId: 316, + }, + { + jobId: 317, + }, + { + jobId: 318, + }, + { + jobId: 319, + }, + { + jobId: 320, + }, + { + jobId: 321, + }, + { + jobId: 322, + }, + { + jobId: 323, + }, + { + jobId: 324, + }, + { + jobId: 325, + }, + { + jobId: 326, + }, + { + jobId: 327, + }, + { + jobId: 328, + }, + { + jobId: 329, + }, + { + jobId: 330, + }, + { + jobId: 331, + }, + { + jobId: 332, + }, + { + jobId: 333, + }, + { + jobId: 334, + }, + { + jobId: 335, + }, + { + jobId: 336, + }, + { + jobId: 337, + }, + { + jobId: 338, + }, + { + jobId: 339, + }, + { + jobId: 340, + }, + { + jobId: 341, + }, + { + jobId: 342, + }, + { + jobId: 343, + }, + { + jobId: 344, + }, + { + jobId: 345, + }, + { + jobId: 346, + }, + { + jobId: 347, + }, + { + jobId: 348, + }, + { + jobId: 349, + }, + { + jobId: 350, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, +]; + +const mixedBatchOutput = [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=911&id=912&id=913&id=914&id=915&id=916&id=917&id=918&id=919&id=920', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 911, + }, + { + jobId: 912, + }, + { + jobId: 913, + }, + { + jobId: 914, + }, + { + jobId: 915, + }, + { + jobId: 916, + }, + { + jobId: 917, + }, + { + jobId: 918, + }, + { + jobId: 919, + }, + { + jobId: 920, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=901&id=902&id=903&id=904&id=905&id=906&id=907&id=908&id=909&id=910', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 901, + }, + { + jobId: 902, + }, + { + jobId: 903, + }, + { + jobId: 904, + }, + { + jobId: 905, + }, + { + jobId: 906, + }, + { + jobId: 907, + }, + { + jobId: 908, + }, + { + jobId: 909, + }, + { + jobId: 910, + }, + ], + batched: true, + statusCode: 200, + destination: DEST_OBJECT, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=704&id=705&id=706', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=501&id=502&id=503', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 1, + }, + ], + batched: false, + statusCode: 200, + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo', + DestinationDefinition: DEST_DEFINITION, + Config: DEST_CONFIG, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=300&id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350', + headers: { + Authorization: TOKEN, + 'Content-Type': CONTENT_TYPE, + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 2, + }, + ], + batched: false, + statusCode: 200, + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo', + DestinationDefinition: DEST_DEFINITION, + Config: DEST_CONFIG, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, +]; + +const recordEventGenerator = (id, action, externalId) => { + // this function is used to generate record events for testing + const testRecordEvent = { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: DEST_DEFINITION, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action, + fields: { + id, + }, + channel: 'sources', + context: { + sources: MESSAGE_SOURCES_CONTEXT, + externalId: [ + { + type: EXTERNAL_ID, + id: externalId, + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: id, + }, + }; + return testRecordEvent; +}; + +module.exports = { + recordInputs, + audiencelistInputs, + reqMetadata, + recordOutput, + largeRecordOutput, + mixedBatchOutput, + recordEventGenerator, +}; diff --git a/src/v0/destinations/marketo_static_list/transform.js b/src/v0/destinations/marketo_static_list/transform.js index 156e26270b..294e34f91b 100644 --- a/src/v0/destinations/marketo_static_list/transform.js +++ b/src/v0/destinations/marketo_static_list/transform.js @@ -1,9 +1,11 @@ const lodash = require('lodash'); const cloneDeep = require('lodash/cloneDeep'); +const { InstrumentationError, UnauthorizedError } = require('@rudderstack/integrations-lib'); const { defaultPostRequestConfig, defaultDeleteRequestConfig, generateErrorObject, + simpleProcessRouterDest, } = require('../../util'); const { AUTH_CACHE_TTL, JSON_MIME_TYPE } = require('../../util/constant'); const { getIds, validateMessageType } = require('./util'); @@ -11,12 +13,11 @@ const { getDestinationExternalID, defaultRequestConfig, getErrorRespEvents, - simpleProcessRouterDest, } = require('../../util'); const { formatConfig, MAX_LEAD_IDS_SIZE } = require('./config'); const Cache = require('../../util/cache'); const { getAuthToken } = require('../marketo/transform'); -const { InstrumentationError, UnauthorizedError } = require('../../util/errorTypes'); +const { processRecordInputs } = require('./transformV2'); const authCache = new Cache(AUTH_CACHE_TTL); // 1 hr @@ -57,8 +58,8 @@ const batchResponseBuilder = (message, Config, token, leadIds, operation) => { return response; }; -const processEvent = (input) => { - const { token, message, destination } = input; +const processEvent = (event) => { + const { token, message, destination } = event; const { Config } = destination; validateMessageType(message, ['audiencelist']); const response = []; @@ -70,77 +71,92 @@ const processEvent = (input) => { if (message.properties?.listData?.remove) { toRemove = getIds(message.properties.listData.remove); } - if ( - (Array.isArray(toAdd) && toAdd.length > 0) || - (Array.isArray(toRemove) && toRemove.length > 0) - ) { - if (Array.isArray(toAdd) && toAdd.length > 0) { - const payload = batchResponseBuilder(message, Config, token, toAdd, 'add'); - if (payload) { - response.push(...payload); - } + if (Array.isArray(toRemove) && toRemove.length > 0) { + const payload = batchResponseBuilder(message, Config, token, toRemove, 'remove'); + if (payload) { + response.push(...payload); } - if (Array.isArray(toRemove) && toRemove.length > 0) { - const payload = batchResponseBuilder(message, Config, token, toRemove, 'remove'); - if (payload) { - response.push(...payload); - } + } + if (Array.isArray(toAdd) && toAdd.length > 0) { + const payload = batchResponseBuilder(message, Config, token, toAdd, 'add'); + if (payload) { + response.push(...payload); } - } else { + } + if (response.length === 0) { throw new InstrumentationError( 'Invalid leadIds format or no leadIds found neither to add nor to remove', ); } return response; }; -const process = async (event) => { - const token = await getAuthToken(formatConfig(event.destination)); +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const process = async (event, _processParams) => { + const token = await getAuthToken(formatConfig(event.destination)); if (!token) { throw new UnauthorizedError('Authorization failed'); } - const response = processEvent({ ...event, token }); + const updatedEvent = { ...event, token }; + const response = processEvent(updatedEvent); return response; }; const processRouterDest = async (inputs, reqMetadata) => { // Token needs to be generated for marketo which will be done on input level. // If destination information is not present Error should be thrown - let token; + + const { destination } = inputs[0]; try { - token = await getAuthToken(formatConfig(inputs[0].destination)); + const token = await getAuthToken(formatConfig(destination)); if (!token) { - const errResp = { - status: 400, - message: 'Authorisation failed', - responseTransformFailure: true, - statTags: {}, - }; - const respEvents = getErrorRespEvents( - inputs.map((input) => input.metadata), - errResp.status, - errResp.message, - errResp.statTags, - ); - return [{ ...respEvents, destination: inputs?.[0]?.destination }]; + throw new UnauthorizedError('Could not retrieve authorisation token'); } } catch (error) { - // Not using handleRtTfSingleEventError here as this is for multiple events - const errObj = generateErrorObject(error); - const respEvents = getErrorRespEvents( - inputs.map((input) => input.metadata), - errObj.status, - errObj.message, - errObj.statTags, + const errorObj = generateErrorObject(error); + const errResponses = inputs.map((input) => + getErrorRespEvents(input.metadata, errorObj.status, errorObj.message, errorObj.statTags), ); - return [{ ...respEvents, destination: inputs?.[0]?.destination }]; + + return errResponses; } - // Checking previous status Code. Initially setting to false. - // If true then previous status is 500 and every subsequent event output should be - // sent with status code 500 to the router to be retried. - const tokenisedInputs = inputs.map((input) => ({ ...input, token })); - const respList = await simpleProcessRouterDest(tokenisedInputs, processEvent, reqMetadata); + // use lodash.groupby to group the inputs based on message type + const transformedRecordEvent = []; + let transformedAudienceEvent = []; + const groupedInputs = lodash.groupBy(inputs, (input) => input.message.type?.toLowerCase()); + + const respList = []; + // process record events + if (groupedInputs.record) { + const groupedRecordInputs = groupedInputs.record; + const { staticListId } = destination.Config; + const externalIdGroupedRecordInputs = lodash.groupBy( + groupedRecordInputs, + (input) => getDestinationExternalID(input.message, 'marketoStaticListId') || staticListId, + ); + const alltransformedGroupedRecordEvent = await Promise.all( + Object.keys(externalIdGroupedRecordInputs).map(async (key) => { + const transformedGroupedRecordEvent = await processRecordInputs( + externalIdGroupedRecordInputs[key], + destination, + key, + ); + return transformedGroupedRecordEvent; + }), + ); + + transformedRecordEvent.push(...alltransformedGroupedRecordEvent.flat()); + } + // process audiencelist events + if (groupedInputs.audiencelist) { + transformedAudienceEvent = await simpleProcessRouterDest( + groupedInputs.audiencelist, + process, + reqMetadata, + ); + } + respList.push(...transformedRecordEvent, ...transformedAudienceEvent); return respList; }; @@ -152,16 +168,20 @@ const processRouterDest = async (inputs, reqMetadata) => { function processMetadataForRouter(output) { const { metadata, destination } = output; const clonedMetadata = cloneDeep(metadata); - clonedMetadata.forEach((metadataElement) => { - // eslint-disable-next-line no-param-reassign - metadataElement.destInfo = { authKey: destination.ID }; - }); + if (Array.isArray(clonedMetadata)) { + clonedMetadata.forEach((metadataElement) => { + // eslint-disable-next-line no-param-reassign + metadataElement.destInfo = { authKey: destination?.ID }; + }); + } return clonedMetadata; } module.exports = { process, + processEvent, processRouterDest, processMetadataForRouter, authCache, + batchResponseBuilder, }; diff --git a/src/v0/destinations/marketo_static_list/transform.test.js b/src/v0/destinations/marketo_static_list/transform.test.js new file mode 100644 index 0000000000..3c387c4295 --- /dev/null +++ b/src/v0/destinations/marketo_static_list/transform.test.js @@ -0,0 +1,138 @@ +const { processRouterDest } = require('./transform'); +const axios = require('axios'); +const MockAxiosAdapter = require('axios-mock-adapter'); +const { + recordInputs, + audiencelistInputs, + reqMetadata, + recordOutput, + largeRecordOutput, + mixedBatchOutput, + recordEventGenerator, +} = require('./testData/testData'); + +const mockAdapter = new MockAxiosAdapter(axios, { onNoMatch: 'throwException' }); +beforeAll(() => { + mockAdapter + .onGet('https://marketo_acct_id_success.mktorest.com/identity/oauth/token') + .reply(200, { access_token: 'access_token_success' }); +}); +describe('Unit cases covering the router flow for both record and audiencelist event types', () => { + it('Sending a small batch of only record events (4 events)', async () => { + const inputs = recordInputs; + const result = await processRouterDest(inputs, reqMetadata); + + // assert that the result is as expected + expect(result.length).toEqual(3); + expect(result[0].batchedRequest.length).toEqual(1); // 1 batched request for 2 record events + expect(result[1].batchedRequest.length).toEqual(1); // 1 batched request for 1 record events + expect(result[2].batchedRequest.length).toEqual(1); // 1 batched request for 1 record events + expect(result[0].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id001/leads.json?id=1001&id=1003', + ); // 1 api call for 2 leadIds + expect(result[1].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=2001', + ); // 1 api call for 1 leadId + expect(result[2].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=1002', + ); // 1 api call for 1 leadId + expect(result[1].batchedRequest[0].method).toEqual('DELETE'); // DELETE requests are sent first + expect(result[0].metadata.length).toEqual(2); // 2 metadata objects for 2 record events + expect(result[1].metadata.length).toEqual(1); // 1 metadata object for 1 record event + expect(result[2].metadata.length).toEqual(1); // 1 metadata object for 1 record event + expect(result).toEqual(recordOutput); // overall result should be equal to the expected output + }); + + it('Sending a large batch of only record events (450 events: 350 inserts | 100 deletes )', async () => { + const largeRecordInputs = []; + for (let index = 0; index < 350; index++) { + largeRecordInputs.push(recordEventGenerator(index + 1, 'insert', 1122)); + } + for (let index = 350; index < 450; index++) { + largeRecordInputs.push(recordEventGenerator(index + 1, 'delete', 1122)); + } + const result = await processRouterDest(largeRecordInputs, reqMetadata); + + // assert that the result is as expected + /* + Total 3 API calls + 1. 1 API call for 100 DELETE requests + 2. 1 API call for 100 POST requests = limit reached for Marketo, leads split to next API call + 3. 1 API call for 50 POST requests + */ + expect(result.length).toEqual(2); + expect(result[0].batchedRequest.length).toEqual(1); // 1 batched request for 1 record event + expect(result[1].batchedRequest.length).toEqual(2); // 1 batched request for 2 record events + expect(result[0].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=351&id=352&id=353&id=354&id=355&id=356&id=357&id=358&id=359&id=360&id=361&id=362&id=363&id=364&id=365&id=366&id=367&id=368&id=369&id=370&id=371&id=372&id=373&id=374&id=375&id=376&id=377&id=378&id=379&id=380&id=381&id=382&id=383&id=384&id=385&id=386&id=387&id=388&id=389&id=390&id=391&id=392&id=393&id=394&id=395&id=396&id=397&id=398&id=399&id=400&id=401&id=402&id=403&id=404&id=405&id=406&id=407&id=408&id=409&id=410&id=411&id=412&id=413&id=414&id=415&id=416&id=417&id=418&id=419&id=420&id=421&id=422&id=423&id=424&id=425&id=426&id=427&id=428&id=429&id=430&id=431&id=432&id=433&id=434&id=435&id=436&id=437&id=438&id=439&id=440&id=441&id=442&id=443&id=444&id=445&id=446&id=447&id=448&id=449&id=450', + ); + expect(result[1].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299&id=300', + ); + expect(result[1].batchedRequest[1].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350', + ); + expect(result[0].batchedRequest[0].method).toEqual('DELETE'); // DELETE requests are sent first + expect(result[1].batchedRequest[0].method).toEqual('POST'); + expect(result[1].batchedRequest[1].method).toEqual('POST'); + expect(result[0].metadata.length).toEqual(100); // 100 metadata objects for 100 record events + expect(result[1].metadata.length).toEqual(350); // 350 metadata objects for 350 record events + expect(result).toEqual(largeRecordOutput); // overall result should be equal to the expected output + }); + + it('Sending a mixed batch of record and audiencelist events (22 events: 10 inserts | 10 deletes | 2 audiencelist (⌐■_■) )', async () => { + const mixedBatchInputs = []; + for (let index = 900; index < 910; index++) { + mixedBatchInputs.push(recordEventGenerator(index + 1, 'insert', 1122)); + } + for (let index = 910; index < 920; index++) { + mixedBatchInputs.push(recordEventGenerator(index + 1, 'delete', 1122)); + } + mixedBatchInputs.push(...audiencelistInputs); + const result = await processRouterDest(mixedBatchInputs, reqMetadata); + + // assert that the result is as expected + /* + Total 4 API calls + 1. 1 API call for 10 DELETE requests + 2. 1 API call for 10 POST requests = limit reached for Marketo, leads split to next API call + 3. 1 API call for 2 POST requests + 4. 1 API call for 2 POST requests + */ + expect(result.length).toEqual(4); + expect(result[0].batchedRequest.length).toEqual(1); // 1 batched request for 1 record event + expect(result[1].batchedRequest.length).toEqual(1); // 1 batched request for 1 record event + expect(result[2].batchedRequest.length).toEqual(2); // 1 batched request for 2 audiencelist events + expect(result[3].batchedRequest.length).toEqual(2); // 1 batched request for 2 audiencelist events + expect(result[0].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=911&id=912&id=913&id=914&id=915&id=916&id=917&id=918&id=919&id=920', + ); + expect(result[1].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=901&id=902&id=903&id=904&id=905&id=906&id=907&id=908&id=909&id=910', + ); + expect(result[2].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=704&id=705&id=706', + ); + expect(result[2].batchedRequest[1].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=501&id=502&id=503', + ); + expect(result[3].batchedRequest[0].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299', + ); + expect(result[2].batchedRequest[1].endpoint).toEqual( + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=501&id=502&id=503', + ); + expect(result[0].batchedRequest[0].method).toEqual('DELETE'); // DELETE requests are sent first + expect(result[1].batchedRequest[0].method).toEqual('POST'); + expect(result[1].batchedRequest[0].method).toEqual('POST'); + expect(result[2].batchedRequest[0].method).toEqual('DELETE'); + expect(result[0].metadata.length).toEqual(10); + expect(result[1].metadata.length).toEqual(10); + expect(result[2].metadata.length).toEqual(1); + expect(result[3].metadata.length).toEqual(1); + expect(result).toEqual(mixedBatchOutput); // overall result should be equal to the expected output + }); +}); +afterAll(() => { + mockAdapter.restore(); +}); diff --git a/src/v0/destinations/marketo_static_list/transformV2.js b/src/v0/destinations/marketo_static_list/transformV2.js new file mode 100644 index 0000000000..912d548d09 --- /dev/null +++ b/src/v0/destinations/marketo_static_list/transformV2.js @@ -0,0 +1,143 @@ +const lodash = require('lodash'); +const { InstrumentationError, UnauthorizedError } = require('@rudderstack/integrations-lib'); +const { + defaultPostRequestConfig, + defaultDeleteRequestConfig, + defaultRequestConfig, + getSuccessRespEvents, + isDefinedAndNotNull, + generateErrorObject, + getErrorRespEvents, +} = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); +const { MAX_LEAD_IDS_SIZE } = require('./config'); +const { getAuthToken } = require('../marketo/transform'); +const { formatConfig } = require('../marketo/config'); + +/** + * Generates the final response structure to be sent to the destination + * @param {*} endPoint + * @param {*} leadIds + * @param {*} operation + * @param {*} token + * @returns batched response + */ +const responseBuilder = (endPoint, leadIds, operation, token) => { + let updatedEndpoint = endPoint; + if (leadIds.length > 0) { + leadIds.forEach((id) => { + updatedEndpoint = `${updatedEndpoint}id=${id}&`; + }); + } + updatedEndpoint = updatedEndpoint.slice(0, -1); + const response = defaultRequestConfig(); + response.endpoint = updatedEndpoint; + if (operation === 'insert') { + response.method = defaultPostRequestConfig.requestMethod; + } else { + response.method = defaultDeleteRequestConfig.requestMethod; + } + response.headers = { + Authorization: `Bearer ${token}`, + 'Content-Type': JSON_MIME_TYPE, + }; + return response; +}; + +/** + * The function is responsible for building the batched response for a given set of record inputs. + * @param {*} groupedRecordInputs + * @param {*} Config + * @param {*} token + * @param {*} leadIds + * @param {*} operation + * @returns an array of response objects, where each object represents a batched response for a chunk of lead IDs. + */ +const batchResponseBuilder = (listId, Config, token, leadIds, operation) => { + const { accountId } = Config; + const endpoint = `https://${accountId}.mktorest.com/rest/v1/lists/${listId}/leads.json?`; + const response = []; + const leadIdsChunks = lodash.chunk(leadIds, MAX_LEAD_IDS_SIZE); + leadIdsChunks.forEach((ids) => { + response.push(responseBuilder(endpoint, ids, operation, token)); + }); + return response; +}; + +/** + * A function that processes a list of grouped record inputs. + * It iterates through each input and groups the field IDs based on the action. + * @param {*} groupedRecordInputs + * @param {*} destination + * @param {*} listId + * @returns An array containing the batched responses for the insert and delete actions along with the metadata. + */ +async function processRecordInputs(groupedRecordInputs, destination, listId) { + const token = await getAuthToken(formatConfig(destination)); + if (!token) { + throw new UnauthorizedError('Authorization failed'); + } + const { Config } = destination; + + // iterate through each input and group field id based on action + const insertFields = []; + const deleteFields = []; + const successMetadataForInsert = []; + const successMetadataForDelete = []; + const errorMetadata = []; + + groupedRecordInputs.forEach((input) => { + const { fields, action } = input.message; + const fieldId = fields?.id; + if (action === 'insert' && isDefinedAndNotNull(fieldId)) { + insertFields.push(fieldId); + successMetadataForInsert.push(input.metadata); + } else if (action === 'delete' && isDefinedAndNotNull(fieldId)) { + deleteFields.push(fieldId); + successMetadataForDelete.push(input.metadata); + } else { + errorMetadata.push(input.metadata); + } + }); + const deletePayloads = batchResponseBuilder(listId, Config, token, deleteFields, 'delete'); + + const deleteResponse = getSuccessRespEvents( + deletePayloads, + successMetadataForDelete, + destination, + true, + ); + + const insertPayloads = batchResponseBuilder(listId, Config, token, insertFields, 'insert'); + + const insertResponse = getSuccessRespEvents( + insertPayloads, + successMetadataForInsert, + destination, + true, + ); + + const error = new InstrumentationError( + 'Invalid action type or no leadIds found neither to add nor to remove', + ); + const errorObj = generateErrorObject(error); + const errorResponseList = errorMetadata.map((metadata) => + getErrorRespEvents(metadata, errorObj.status, errorObj.message, errorObj.statTags), + ); + const finalResponse = []; + if (deleteResponse.batchedRequest.length > 0) { + finalResponse.push(deleteResponse); + } + if (insertResponse.batchedRequest.length > 0) { + finalResponse.push(insertResponse); + } + if (errorResponseList.length > 0) { + finalResponse.push(...errorResponseList); + } + return finalResponse; + // return [deleteResponse, insertResponse, ...errorResponseList]; +} + +module.exports = { + processRecordInputs, +}; diff --git a/src/v0/destinations/marketo_static_list/util.js b/src/v0/destinations/marketo_static_list/util.js index 2d4fe493a0..c6959cb256 100644 --- a/src/v0/destinations/marketo_static_list/util.js +++ b/src/v0/destinations/marketo_static_list/util.js @@ -1,4 +1,5 @@ -const { InstrumentationError } = require('../../util/errorTypes'); +/* eslint-disable unicorn/consistent-destructuring */ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); /** * Fetches the ids from the array of objects diff --git a/src/v0/destinations/mautic/transform.js b/src/v0/destinations/mautic/transform.js index 12b0d06b6f..13808f6e3c 100644 --- a/src/v0/destinations/mautic/transform.js +++ b/src/v0/destinations/mautic/transform.js @@ -1,3 +1,8 @@ +const { + TransformationError, + InstrumentationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, constructPayload, @@ -20,11 +25,6 @@ const { const { EventType } = require('../../../constants'); const { mappingConfig, ConfigCategories } = require('./config'); -const { - TransformationError, - InstrumentationError, - ConfigurationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = async (payload, endpoint, method, messageType, Config) => { diff --git a/src/v0/destinations/mautic/utils.js b/src/v0/destinations/mautic/utils.js index f9dd787d9d..d8ad8dbffc 100644 --- a/src/v0/destinations/mautic/utils.js +++ b/src/v0/destinations/mautic/utils.js @@ -1,5 +1,10 @@ /* eslint-disable no-return-assign, no-param-reassign, no-restricted-syntax */ const get = require('get-value'); +const { + NetworkError, + InstrumentationError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { getFieldValueFromMessage } = require('../../util'); const { BASE_URL, lookupFieldMap } = require('./config'); const { httpGET } = require('../../../adapters/network'); @@ -7,7 +12,6 @@ const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/moengage/transform.js b/src/v0/destinations/moengage/transform.js index d87d931817..8a16d9c7a7 100644 --- a/src/v0/destinations/moengage/transform.js +++ b/src/v0/destinations/moengage/transform.js @@ -1,4 +1,9 @@ const btoa = require('btoa'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, @@ -16,11 +21,6 @@ const { simpleProcessRouterDest, isAppleFamily, } = require('../../util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(message, category, destination) { @@ -119,7 +119,7 @@ const processEvent = (message, destination) => { response = responseBuilderSimple(message, category, destination); // only if device information is present device info will be added/updated // with an identify call otherwise only user info will be added/updated - if (message.context.device && message.context.device.type && message.context.device.token) { + if (message?.context?.device?.type && message?.context?.device?.token) { // build the response response = [ // user api payload (output for identify) diff --git a/src/v0/destinations/monday/transform.js b/src/v0/destinations/monday/transform.js index 34ada34780..152b42f8d0 100644 --- a/src/v0/destinations/monday/transform.js +++ b/src/v0/destinations/monday/transform.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ENDPOINT } = require('./config'); const { populatePayload, getBoardDetails, checkAllowedEventNameFromUI } = require('./util'); @@ -8,13 +13,8 @@ const { removeUndefinedAndNullValues, simpleProcessRouterDest, getDestinationExternalID, - validateEventType, + validateEventName, } = require('../../util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, apiToken) => { @@ -42,7 +42,7 @@ const trackResponseBuilder = async (message, { Config }) => { const { apiToken } = Config; let boardId = getDestinationExternalID(message, 'boardId'); const event = get(message, 'event'); - validateEventType(event); + validateEventName(event); if (!boardId) { boardId = Config.boardId; } diff --git a/src/v0/destinations/monday/util.js b/src/v0/destinations/monday/util.js index 5f260aabae..a66dd63dff 100644 --- a/src/v0/destinations/monday/util.js +++ b/src/v0/destinations/monday/util.js @@ -1,8 +1,12 @@ const { isNumber } = require('lodash'); +const { + NetworkError, + ConfigurationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { httpPOST } = require('../../../adapters/network'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); const { getDestinationExternalID, isDefinedAndNotNull } = require('../../util'); -const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/monetate/transform.js b/src/v0/destinations/monetate/transform.js index e4d1f28b61..26a88e686b 100644 --- a/src/v0/destinations/monetate/transform.js +++ b/src/v0/destinations/monetate/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { removeUndefinedValues, simpleProcessRouterDest } = require('../../util'); const { handleProductViewed, @@ -11,7 +12,6 @@ const { } = require('./utils'); const { EventType } = require('../../../constants'); const { mappingConfig } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); function track(message, destination) { const rawPayload = constructPayload(message, mappingConfig.MONETATETrack); diff --git a/src/v0/destinations/monetate/utils.js b/src/v0/destinations/monetate/utils.js index 7facc2617d..1fe899f120 100644 --- a/src/v0/destinations/monetate/utils.js +++ b/src/v0/destinations/monetate/utils.js @@ -1,6 +1,6 @@ const set = require('set-value'); const get = require('get-value'); -const { InstrumentationError } = require('../../util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isDefinedAndNotNull, defaultRequestConfig, getValueFromMessage } = require('../../util'); const { ENDPOINT } = require('./config'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/mp/config.js b/src/v0/destinations/mp/config.js index 41a801e9da..35b40294f5 100644 --- a/src/v0/destinations/mp/config.js +++ b/src/v0/destinations/mp/config.js @@ -11,6 +11,9 @@ const ConfigCategory = { IDENTIFY: { name: 'MPIdentifyConfig', }, + SET_ONCE: { + name: 'MPSetOnceConfig', + }, PROFILE_ANDROID: { name: 'MPProfilePropertiesAndroid', }, diff --git a/src/v0/destinations/mp/data/MPSetOnceConfig.json b/src/v0/destinations/mp/data/MPSetOnceConfig.json new file mode 100644 index 0000000000..e5aaf851a3 --- /dev/null +++ b/src/v0/destinations/mp/data/MPSetOnceConfig.json @@ -0,0 +1,122 @@ +[ + { + "destKey": "$created", + "sourceKeys": "createdAt", + "required": false + }, + { + "destKey": "$email", + "sourceKeys": "email", + "required": false + }, + { + "destKey": "$first_name", + "sourceKeys": ["firstName", "firstname", "first_name"], + "required": false + }, + { + "destKey": "$last_name", + "sourceKeys": ["lastName", "lastname", "last_name"], + "required": false + }, + { + "destKey": "$name", + "sourceKeys": "name", + "required": false + }, + { + "destKey": "$username", + "sourceKeys": ["username", "userName"], + "required": false + }, + { + "destKey": "$phone", + "sourceKeys": "phone", + "required": false + }, + { + "destKey": "$avatar", + "sourceKeys": "avatar", + "required": false + }, + { + "destKey": "$country_code", + "sourceKeys": ["country", "address.country"], + "required": false + }, + { + "destKey": "$city", + "sourceKeys": ["city", "address.city"], + "required": false + }, + { + "destKey": "$region", + "sourceKeys": ["state", "address.state", "location.region"], + "required": false + }, + { + "destKey": "$unsubscribed", + "sourceKeys": "unsubscribed", + "required": false + }, + { + "destKey": "$geo_source", + "sourceKeys": "location.geoSource", + "required": false + }, + { + "destKey": "$timezone", + "sourceKeys": "location.timezone", + "required": false + }, + { + "destKey": "$latitude", + "sourceKeys": "location.latitude", + "required": false + }, + { + "destKey": "$longitude", + "sourceKeys": "location.longitude", + "required": false + }, + { + "destKey": "$carrier", + "sourceKeys": "network.carrier", + "required": false + }, + { + "destKey": "$manufacturer", + "sourceKeys": "device.manufacturer", + "required": false + }, + { + "destKey": "$model", + "sourceKeys": "device.model", + "required": false + }, + { + "destKey": "$screen_height", + "sourceKeys": "screen.height", + "required": false + }, + { + "destKey": "$screen_width", + "sourceKeys": "screen.width", + "required": false + }, + { + "destKey": "$wifi", + "sourceKeys": "network.wifi", + "required": false + }, + { + "destKey": "$initial_referrer", + "sourceKeys": "page.initial_referrer", + "required": false + }, + { + "destKey": "$initial_referring_domain", + "sourceKeys": ["page.initial_referring_domain", "page.initialReferringDomain"], + "required": false + } +] diff --git a/src/v0/destinations/mp/deleteUsers.js b/src/v0/destinations/mp/deleteUsers.js index 5b86cae6ae..f01475ef2b 100644 --- a/src/v0/destinations/mp/deleteUsers.js +++ b/src/v0/destinations/mp/deleteUsers.js @@ -1,4 +1,5 @@ const lodash = require('lodash'); +const { ConfigurationError, NetworkError } = require('@rudderstack/integrations-lib'); const { handleHttpRequest } = require('../../../adapters/network'); const { isHttpStatusSuccess } = require('../../util'); const { @@ -7,7 +8,6 @@ const { DISTINCT_ID_MAX_BATCH_SIZE, } = require('./config'); const { executeCommonValidations } = require('../../util/regulation-api'); -const { ConfigurationError, NetworkError } = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/mp/transform.js b/src/v0/destinations/mp/transform.js index a5f1bf2d9d..3d0aaa7c4c 100644 --- a/src/v0/destinations/mp/transform.js +++ b/src/v0/destinations/mp/transform.js @@ -1,5 +1,6 @@ const lodash = require('lodash'); const get = require('get-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { base64Convertor, @@ -16,6 +17,7 @@ const { checkInvalidRtTfEvents, handleRtTfSingleEventError, groupEventsByType, + parseConfigArray, } = require('../../util'); const { ConfigCategory, @@ -34,8 +36,8 @@ const { combineBatchRequestsWithSameJobIds, groupEventsByEndpoint, batchEvents, + trimTraits, } = require('./util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { CommonUtils } = require('../../../util/common'); // ref: https://help.mixpanel.com/hc/en-us/articles/115004613766-Default-Properties-Collected-by-Mixpanel @@ -226,17 +228,51 @@ const processTrack = (message, destination) => { return returnValue; }; +const createSetOnceResponse = (message, type, destination, setOnce) => { + const payload = { + $set_once: setOnce, + $token: destination.Config.token, + $distinct_id: message.userId || message.anonymousId, + }; + + if (destination?.Config.identityMergeApi === 'simplified') { + payload.$distinct_id = message.userId || `$device:${message.anonymousId}`; + } + + return responseBuilderSimple(payload, message, type, destination.Config); +}; + const processIdentifyEvents = async (message, type, destination) => { + const messageClone = { ...message }; + let seggregatedTraits = {}; const returnValue = []; + let setOnceProperties = []; + + // making payload for set_once properties + if (destination.Config.setOnceProperties && destination.Config.setOnceProperties.length > 0) { + setOnceProperties = parseConfigArray(destination.Config.setOnceProperties, 'property'); + seggregatedTraits = trimTraits( + messageClone.traits, + messageClone.context.traits, + setOnceProperties, + ); + messageClone.traits = seggregatedTraits.traits; + messageClone.context.traits = seggregatedTraits.contextTraits; + if (Object.keys(seggregatedTraits.setOnce).length > 0) { + returnValue.push( + createSetOnceResponse(messageClone, type, destination, seggregatedTraits.setOnce), + ); + } + } // Creating the user profile // https://developer.mixpanel.com/reference/profile-set - returnValue.push(createIdentifyResponse(message, type, destination, responseBuilderSimple)); + returnValue.push(createIdentifyResponse(messageClone, type, destination, responseBuilderSimple)); if ( destination.Config?.identityMergeApi !== 'simplified' && - message.userId && - message.anonymousId && + messageClone.userId && + messageClone.anonymousId && isImportAuthCredentialsAvailable(destination) ) { // If userId and anonymousId both are present and required credentials for /import @@ -245,13 +281,13 @@ const processIdentifyEvents = async (message, type, destination) => { const trackPayload = { event: '$merge', properties: { - $distinct_ids: [message.userId, message.anonymousId], + $distinct_ids: [messageClone.userId, messageClone.anonymousId], token: destination.Config.token, }, }; const identifyTrackResponse = responseBuilderSimple( trackPayload, - message, + messageClone, 'merge', destination.Config, ); @@ -440,7 +476,6 @@ const processRouterDest = async (inputs, reqMetadata) => { destination: event.destination, }; } - let processedEvents = await process(event); processedEvents = CommonUtils.toArray(processedEvents); return processedEvents.map((res) => ({ diff --git a/src/v0/destinations/mp/util.js b/src/v0/destinations/mp/util.js index 30173fd514..bb8f36fdbe 100644 --- a/src/v0/destinations/mp/util.js +++ b/src/v0/destinations/mp/util.js @@ -1,5 +1,7 @@ +const lodash = require('lodash'); const set = require('set-value'); const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isDefined, constructPayload, @@ -13,6 +15,7 @@ const { defaultBatchRequestConfig, IsGzipSupported, isObject, + isDefinedAndNotNullAndNotEmpty, } = require('../../util'); const { ConfigCategory, @@ -20,12 +23,12 @@ const { GEO_SOURCE_ALLOWED_VALUES, mappingConfig, } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const { CommonUtils } = require('../../../util/common'); const mPIdentifyConfigJson = mappingConfig[ConfigCategory.IDENTIFY.name]; const mPProfileAndroidConfigJson = mappingConfig[ConfigCategory.PROFILE_ANDROID.name]; const mPProfileIosConfigJson = mappingConfig[ConfigCategory.PROFILE_IOS.name]; +const mPSetOnceConfigJson = mappingConfig[ConfigCategory.SET_ONCE.name]; /** * this function has been used to create @@ -322,6 +325,72 @@ const combineBatchRequestsWithSameJobIds = (inputBatches) => { return combineBatches(combineBatches(inputBatches)); }; +/** + * Trims the traits and contextTraits objects based on the setOnceProperties array and returns an object containing the modified traits, contextTraits, and setOnce properties. + * + * @param {object} traits - An object representing the traits. + * @param {object} contextTraits - An object representing the context traits. + * @param {string[]} setOnceProperties - An array of property paths to be considered for the setOnce transformation. + * @returns {object} - An object containing the modified traits, contextTraits, and setOnce properties. + * + * @example + * const traits = { name: 'John', age: 30 }; + * const contextTraits = { country: 'USA', language: 'English', address: { city: 'New York', state: 'NY' }}}; + * const setOnceProperties = ['name', 'country', 'address.city']; + * + * const result = trimTraits(traits, contextTraits, setOnceProperties); + * // Output: { traits: { age: 30 }, contextTraits: { language: 'English' }, setOnce: { $name: 'John', $country_code: 'USA', city: 'New York'} } + */ +function trimTraits(traits, contextTraits, setOnceProperties) { + let sentOnceTransformedPayload; + // Create a copy of the original traits object + const traitsCopy = { ...traits }; + const contextTraitsCopy = { ...contextTraits }; + + // Initialize setOnce object + const setOnceEligible = {}; + + // Step 1: find the k-v pairs of setOnceProperties in traits and contextTraits + + setOnceProperties.forEach((propertyPath) => { + const propName = lodash.last(propertyPath.split('.')); + + const traitsValue = get(traitsCopy, propertyPath); + const contextTraitsValue = get(contextTraitsCopy, propertyPath); + + if (isDefinedAndNotNullAndNotEmpty(traitsValue)) { + setOnceEligible[propName] = traitsValue; + lodash.unset(traitsCopy, propertyPath); + } + if (isDefinedAndNotNullAndNotEmpty(contextTraitsValue)) { + if (!setOnceEligible.hasOwnProperty(propName)) { + setOnceEligible[propName] = contextTraitsValue; + } + lodash.unset(contextTraitsCopy, propertyPath); + } + }); + + if (setOnceEligible && Object.keys(setOnceEligible).length > 0) { + // Step 2: transform properties eligible as per rudderstack declared identify event mapping + // setOnce should have all traits from message.traits and message.context.traits by now + sentOnceTransformedPayload = constructPayload(setOnceEligible, mPSetOnceConfigJson); + + // Step 3: combine the transformed and custom setOnce traits + sentOnceTransformedPayload = extractCustomFields( + setOnceEligible, + sentOnceTransformedPayload, + 'root', + MP_IDENTIFY_EXCLUSION_LIST, + ); + } + + return { + traits: traitsCopy, + contextTraits: contextTraitsCopy, + setOnce: sentOnceTransformedPayload || {}, + }; +} + module.exports = { createIdentifyResponse, isImportAuthCredentialsAvailable, @@ -330,4 +399,5 @@ module.exports = { generateBatchedPayloadForArray, batchEvents, combineBatchRequestsWithSameJobIds, + trimTraits, }; diff --git a/src/v0/destinations/mp/util.test.js b/src/v0/destinations/mp/util.test.js index 6d5b24766d..fbaa6f9b9f 100644 --- a/src/v0/destinations/mp/util.test.js +++ b/src/v0/destinations/mp/util.test.js @@ -4,6 +4,7 @@ const { batchEvents, generateBatchedPayloadForArray, buildUtmParams, + trimTraits, } = require('./util'); const { FEATURE_GZIP_SUPPORT } = require('../../util/constant'); @@ -602,4 +603,97 @@ describe('Mixpanel utils test', () => { }); }); }); + describe('Unit test cases for trimTraits', () => { + // Given a valid traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing traits, contextTraits, and setOnce properties. + it('should return an object containing traits, contextTraits, and setOnce properties when given valid inputs', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + console.log(result); + + expect(result).toEqual({ + traits: { + age: 30, + }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, + }); + }); + + // Given an empty traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing empty traits and contextTraits, and an empty setOnce property. + it('should return an object containing empty traits and contextTraits, and an empty setOnce property when given empty traits and contextTraits objects', () => { + const traits = {}; + const contextTraits = {}; + const setOnceProperties = ['name', 'email']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: {}, + contextTraits: {}, + setOnce: {}, + }); + }); + + // Given an empty setOnceProperties array, the function should return an object containing the original traits and contextTraits objects, and an empty setOnce property. + it('should return an object containing the original traits and contextTraits objects, and an empty setOnce property when given an empty setOnceProperties array', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = []; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: { name: 'John', age: 30 }, + contextTraits: { email: 'john@example.com' }, + setOnce: {}, + }); + }); + + // Given a setOnceProperties array containing properties that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. + it('should not add properties to the setOnce property when given setOnceProperties array with non-existent properties', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: { age: 30 }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, + }); + }); + + // Given a setOnceProperties array containing properties with nested paths that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. + it('should not add properties to the setOnce property when given setOnceProperties array with non-existent nested properties', () => { + const traits = { name: 'John', age: 30, address: 'kolkata' }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address.city']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: { age: 30, address: 'kolkata' }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, + }); + }); + + it('should add properties to the setOnce property when given setOnceProperties array with existent nested properties', () => { + const traits = { name: 'John', age: 30, address: { city: 'kolkata' }, isAdult: false }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address.city']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: { age: 30, address: {}, isAdult: false }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com', $city: 'kolkata' }, + }); + }); + }); }); diff --git a/src/v0/destinations/ometria/networkResponseHandler.js b/src/v0/destinations/ometria/networkResponseHandler.js index 2020ab0343..501b67f176 100644 --- a/src/v0/destinations/ometria/networkResponseHandler.js +++ b/src/v0/destinations/ometria/networkResponseHandler.js @@ -1,8 +1,8 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { getDynamicErrorType, trimResponse } = require('../../../adapters/utils/networkUtils'); const { isDefinedAndNotNull } = require('../../util'); const { isEmpty } = require('../../util/index'); const tags = require('../../util/tags'); -const { NetworkError } = require('../../util/errorTypes'); const responseTransform = (destResponse) => { let respBody; diff --git a/src/v0/destinations/ometria/transform.js b/src/v0/destinations/ometria/transform.js index 6d3c2ab174..55038e10b8 100644 --- a/src/v0/destinations/ometria/transform.js +++ b/src/v0/destinations/ometria/transform.js @@ -1,7 +1,7 @@ /* eslint-disable one-var, @typescript-eslint/naming-convention */ /* eslint-disable camelcase */ +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { constructPayload, extractCustomFields, diff --git a/src/v0/destinations/one_signal/transform.js b/src/v0/destinations/one_signal/transform.js index db699935f4..a072aef0e4 100644 --- a/src/v0/destinations/one_signal/transform.js +++ b/src/v0/destinations/one_signal/transform.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ConfigCategory, mappingConfig, BASE_URL, ENDPOINTS } = require('./config'); const { @@ -13,11 +18,6 @@ const { defaultPutRequestConfig, } = require('../../util'); const { populateDeviceType, populateTags } = require('./util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, eventType) => { diff --git a/src/v0/destinations/one_signal/util.js b/src/v0/destinations/one_signal/util.js index 4b53949e55..2de57de1b4 100644 --- a/src/v0/destinations/one_signal/util.js +++ b/src/v0/destinations/one_signal/util.js @@ -1,5 +1,5 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getIntegrationsObj, getFieldValueFromMessage, getBrowserInfo } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); // For mapping device_type value const deviceTypeMapping = { diff --git a/src/v0/destinations/pagerduty/transform.js b/src/v0/destinations/pagerduty/transform.js index d7a8848ace..fb862d2553 100644 --- a/src/v0/destinations/pagerduty/transform.js +++ b/src/v0/destinations/pagerduty/transform.js @@ -1,3 +1,8 @@ +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -6,11 +11,6 @@ const { removeUndefinedAndNullValues, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { trackEventPayloadBuilder } = require('./util'); const responseBuilder = (payload, endpoint) => { diff --git a/src/v0/destinations/pagerduty/util.js b/src/v0/destinations/pagerduty/util.js index 42030aa2e7..5b768704ed 100644 --- a/src/v0/destinations/pagerduty/util.js +++ b/src/v0/destinations/pagerduty/util.js @@ -1,5 +1,6 @@ const get = require('get-value'); const moment = require('moment'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { SEVERITIES, EVENT_ACTIONS, @@ -9,7 +10,6 @@ const { DEFAULT_EVENT_ACTION, } = require('./config'); const { constructPayload, getIntegrationsObj } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); /** * Validates the timestamp diff --git a/src/v0/destinations/pardot/networkHandler.js b/src/v0/destinations/pardot/networkHandler.js index 4cec03ebf8..12b4abbc53 100644 --- a/src/v0/destinations/pardot/networkHandler.js +++ b/src/v0/destinations/pardot/networkHandler.js @@ -1,3 +1,4 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); const { removeUndefinedValues } = require('../../util'); const { prepareProxyRequest, getPayloadData, httpSend } = require('../../../adapters/network'); const { @@ -7,7 +8,6 @@ const { const { isHttpStatusSuccess } = require('../../util/index'); const { REFRESH_TOKEN } = require('../../../adapters/networkhandler/authConstants'); const tags = require('../../util/tags'); -const { NetworkError } = require('../../util/errorTypes'); /** * Example Response from pardot diff --git a/src/v0/destinations/pardot/transform.js b/src/v0/destinations/pardot/transform.js index bfc7386ef9..b32b8967bd 100644 --- a/src/v0/destinations/pardot/transform.js +++ b/src/v0/destinations/pardot/transform.js @@ -34,6 +34,7 @@ */ const get = require('get-value'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { identifyConfig, DESTINATION } = require('./config'); const logger = require('../../../logger'); const { @@ -48,7 +49,6 @@ const { getAccessToken, } = require('../../util'); const { CONFIG_CATEGORIES } = require('./config'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const buildResponse = (payload, url, destination, token) => { const responseBody = removeUndefinedValues(payload); diff --git a/src/v0/destinations/persistiq/transform.js b/src/v0/destinations/persistiq/transform.js index 195f8d6567..3b4fd6cadc 100644 --- a/src/v0/destinations/persistiq/transform.js +++ b/src/v0/destinations/persistiq/transform.js @@ -1,4 +1,5 @@ const { set } = require('lodash'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, removeUndefinedAndNullValues, @@ -8,7 +9,6 @@ const { const { configCategories } = require('./config'); const { buildLeadPayload, getIdentifyTraits } = require('./util'); const { EventType } = require('../../../constants'); -const { InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = (payload, endpoint, method, Config) => { const { apiKey } = Config; diff --git a/src/v0/destinations/persistiq/util.js b/src/v0/destinations/persistiq/util.js index 7e1986e9b3..f37a9d1886 100644 --- a/src/v0/destinations/persistiq/util.js +++ b/src/v0/destinations/persistiq/util.js @@ -1,4 +1,5 @@ const { get } = require('lodash'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getFieldValueFromMessage, getHashFromArray, @@ -6,7 +7,6 @@ const { flattenMultilevelPayload, } = require('../../util'); const { identifySourceKeys, fileConfigCategories, mappingConfig } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); /** * Returns the remaining keys from traits diff --git a/src/v0/destinations/personalize/transform.js b/src/v0/destinations/personalize/transform.js index 3523987a89..dcfaae755c 100644 --- a/src/v0/destinations/personalize/transform.js +++ b/src/v0/destinations/personalize/transform.js @@ -1,4 +1,5 @@ const lodash = require('lodash'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { KEY_CHECK_LIST, MANDATORY_PROPERTIES } = require('./config'); const { EventType } = require('../../../constants'); const { @@ -9,7 +10,6 @@ const { isDefined, simpleProcessRouterDest, } = require('../../util'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const putEventsHandler = (message, destination) => { const { properties, anonymousId, event, messageId, context } = message; diff --git a/src/v0/destinations/pinterest_tag/transform.js b/src/v0/destinations/pinterest_tag/transform.js index 15efd63436..ee7e2e5b19 100644 --- a/src/v0/destinations/pinterest_tag/transform.js +++ b/src/v0/destinations/pinterest_tag/transform.js @@ -1,4 +1,5 @@ const { get } = require('lodash'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -28,7 +29,6 @@ const { getV5EventsEndpoint, API_VERSION, } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const responseBuilderSimple = (finalPayload, { Config }) => { const { apiVersion = API_VERSION.v3, adAccountId, conversionToken, sendAsTestEvent } = Config; diff --git a/src/v0/destinations/pinterest_tag/utils.js b/src/v0/destinations/pinterest_tag/utils.js index c8ca8dabad..c1493e9dbd 100644 --- a/src/v0/destinations/pinterest_tag/utils.js +++ b/src/v0/destinations/pinterest_tag/utils.js @@ -1,5 +1,6 @@ /* eslint-disable no-param-reassign */ const sha256 = require('sha256'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { constructPayload, @@ -8,7 +9,6 @@ const { getHashFromArrayWithDuplicate, removeUndefinedAndNullValues, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { COMMON_CONFIGS, CUSTOM_CONFIGS, API_VERSION } = require('./config'); const VALID_ACTION_SOURCES = ['app_android', 'app_ios', 'web', 'offline']; @@ -165,7 +165,7 @@ const convertToSnakeCase = (eventName) => const deduceTrackScreenEventName = (message, Config) => { let eventName; const { event, name } = message; - const { apiVersion = API_VERSION.v3, eventsMapping, sendAsCustomEvent } = Config; + const { eventsMapping, sendAsCustomEvent } = Config; const trackEventOrScreenName = event || name; if (!trackEventOrScreenName) { throw new InstrumentationError('event_name could not be mapped. Aborting'); @@ -209,17 +209,11 @@ const deduceTrackScreenEventName = (message, Config) => { return ['custom']; } - if (apiVersion === API_VERSION.v3) { - /* - Step 4: In case both of the above stated cases fail, will send the event name as it is. - This is going to be reflected as "unknown" event in conversion API dashboard. - */ - return [trackEventOrScreenName]; - } - - throw new ConfigurationError( - `${event} is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting`, - ); + /* + Step 4: In case all of the above stated cases failed, will send the event name as it is. + This is going to be reflected as "unknown" event in conversion API dashboard. + */ + return [trackEventOrScreenName]; }; /** diff --git a/src/v0/destinations/posthog/transform.js b/src/v0/destinations/posthog/transform.js index 9f639b59de..62a2f26783 100644 --- a/src/v0/destinations/posthog/transform.js +++ b/src/v0/destinations/posthog/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { DEFAULT_BASE_ENDPOINT, CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const { @@ -14,7 +15,6 @@ const { removeUndefinedAndNullValues, simpleProcessRouterDest, } = require('../../util'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); // Logic To match destination Property key that is in Rudder Stack Properties Object. diff --git a/src/v0/destinations/profitwell/transform.js b/src/v0/destinations/profitwell/transform.js index 70de193fbd..58449fd9c1 100644 --- a/src/v0/destinations/profitwell/transform.js +++ b/src/v0/destinations/profitwell/transform.js @@ -1,3 +1,8 @@ +const { + NetworkError, + ConfigurationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { getSubscriptionHistory, @@ -15,7 +20,6 @@ const { simpleProcessRouterDest, } = require('../../util'); const { BASE_ENDPOINT, createPayloadMapping } = require('./config'); -const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/profitwell/utils.js b/src/v0/destinations/profitwell/utils.js index d7a3562126..acc4db2035 100644 --- a/src/v0/destinations/profitwell/utils.js +++ b/src/v0/destinations/profitwell/utils.js @@ -1,4 +1,8 @@ const get = require('get-value'); +const { + InstrumentationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { httpGET } = require('../../../adapters/network'); const { toUnixTimestamp, @@ -11,7 +15,6 @@ const { constructPayload, } = require('../../util'); const { BASE_ENDPOINT, createPayloadMapping, updatePayloadMapping } = require('./config'); -const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); const CURRENCY_CODES = [ 'aed', diff --git a/src/v0/destinations/reddit/networkHandler.js b/src/v0/destinations/reddit/networkHandler.js new file mode 100644 index 0000000000..836c015859 --- /dev/null +++ b/src/v0/destinations/reddit/networkHandler.js @@ -0,0 +1,50 @@ +const { RetryableError } = require('@rudderstack/integrations-lib'); +const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); +const { isHttpStatusSuccess } = require('../../util/index'); +const { REFRESH_TOKEN } = require('../../../adapters/networkhandler/authConstants'); + +const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); + +const redditRespHandler = (destResponse) => { + const { status, response } = destResponse; + + // to handle the case when authorization-token is invalid + if (status === 401 && response.includes('Authorization Required')) { + throw new RetryableError( + `Request failed due to ${response} 'during reddit response transformation'`, + 500, + destResponse, + REFRESH_TOKEN, + ); + } +}; +const responseHandler = (destinationResponse) => { + const message = `Request Processed Successfully`; + const { status } = destinationResponse; + if (!isHttpStatusSuccess(status)) { + // if error, successfully return status, message and original destination response + redditRespHandler(destinationResponse); + } + const { response } = destinationResponse; + const errorMessage = + response.invalid_events && Array.isArray(response.invalid_events) + ? response?.invalid_events[0]?.error_message + : null; + const destResp = errorMessage || destinationResponse; + // Mostly any error will not have a status of 2xx + return { + status, + message, + destResp, + }; +}; +// eslint-disable-next-line @typescript-eslint/naming-convention +class networkHandler { + constructor() { + this.responseHandler = responseHandler; + this.proxy = proxyRequest; + this.prepareProxy = prepareProxyRequest; + this.processAxiosResponse = processAxiosResponse; + } +} +module.exports = { networkHandler }; diff --git a/src/v0/destinations/redis/transform.js b/src/v0/destinations/redis/transform.js index ffc4a33c43..23c73f0ba4 100644 --- a/src/v0/destinations/redis/transform.js +++ b/src/v0/destinations/redis/transform.js @@ -1,9 +1,9 @@ const lodash = require('lodash'); const flatten = require('flat'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { isEmpty, isObject } = require('../../util'); const { EventType } = require('../../../constants'); -const { InstrumentationError } = require('../../util/errorTypes'); // processValues: // 1. removes keys with empty values or still an object(empty) after flattening diff --git a/src/v0/destinations/refiner/transform.js b/src/v0/destinations/refiner/transform.js index def685b597..b891945f7f 100644 --- a/src/v0/destinations/refiner/transform.js +++ b/src/v0/destinations/refiner/transform.js @@ -1,3 +1,4 @@ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { ErrorMessage, defaultRequestConfig, @@ -13,7 +14,6 @@ const { identifyUserPayloadBuilder, } = require('./utils'); const { EventType } = require('../../../constants'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = (payload, endpoint, destination) => { if (payload) { diff --git a/src/v0/destinations/refiner/utils.js b/src/v0/destinations/refiner/utils.js index 109f6ff656..5e788352ca 100644 --- a/src/v0/destinations/refiner/utils.js +++ b/src/v0/destinations/refiner/utils.js @@ -1,7 +1,7 @@ const get = require('get-value'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES } = require('./config'); const { getHashFromArray, getFieldValueFromMessage } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); /** * Validation for userId and an email diff --git a/src/v0/destinations/revenue_cat/transform.js b/src/v0/destinations/revenue_cat/transform.js index 5f165a9278..407cb91608 100644 --- a/src/v0/destinations/revenue_cat/transform.js +++ b/src/v0/destinations/revenue_cat/transform.js @@ -1,5 +1,10 @@ const set = require('set-value'); const { defaultRequestConfig } = require('rudder-transformer-cdk/build/utils'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { constructPayload, @@ -15,11 +20,6 @@ const { REVENUE_CAT_IDENTIFY_EXCLUSION, BASE_URL, } = require('./config'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const trackResponseBuilder = async (message, category, { Config }) => { diff --git a/src/v0/destinations/rockerbox/transform.js b/src/v0/destinations/rockerbox/transform.js index 5369afa7e5..3ac806e5ee 100644 --- a/src/v0/destinations/rockerbox/transform.js +++ b/src/v0/destinations/rockerbox/transform.js @@ -1,4 +1,5 @@ const get = require('get-value'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, removeUndefinedAndNullValues, @@ -9,7 +10,6 @@ const { } = require('../../util'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, ROCKERBOX_DEFINED_PROPERTIES } = require('./config'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilderSimple = (message, category, destination) => { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); diff --git a/src/v0/destinations/salesforce/config.js b/src/v0/destinations/salesforce/config.js index 6c0ccde80f..1425bad51b 100644 --- a/src/v0/destinations/salesforce/config.js +++ b/src/v0/destinations/salesforce/config.js @@ -24,6 +24,8 @@ const SF_TOKEN_REQUEST_URL = 'https://login.salesforce.com/services/oauth2/token const SF_TOKEN_REQUEST_URL_SANDBOX = 'https://test.salesforce.com/services/oauth2/token'; const DESTINATION = 'Salesforce'; +const OAUTH = 'oauth'; +const LEGACY = 'legacy'; const mappingConfig = getMappingConfig(ConfigCategory, __dirname); @@ -37,4 +39,6 @@ module.exports = { ignoredContactTraits: mappingConfig[ConfigCategory.IGNORE_CONTACT.name], ACCESS_TOKEN_CACHE_TTL, DESTINATION, + OAUTH, + LEGACY, }; diff --git a/src/v0/destinations/salesforce/networkHandler.js b/src/v0/destinations/salesforce/networkHandler.js index 622d2ae731..918084cc89 100644 --- a/src/v0/destinations/salesforce/networkHandler.js +++ b/src/v0/destinations/salesforce/networkHandler.js @@ -1,5 +1,6 @@ const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); +const { LEGACY } = require('./config'); const { salesforceResponseHandler } = require('./utils'); const responseHandler = (destinationResponse, destType) => { @@ -9,6 +10,7 @@ const responseHandler = (destinationResponse, destType) => { destinationResponse, 'during Salesforce Response Handling', destinationResponse?.rudderJobMetadata?.destInfo?.authKey, + LEGACY, ); // else successfully return status as 200, message and original destination response diff --git a/src/v0/destinations/salesforce/transform.js b/src/v0/destinations/salesforce/transform.js index 95e41ccd98..5ada9dfaa0 100644 --- a/src/v0/destinations/salesforce/transform.js +++ b/src/v0/destinations/salesforce/transform.js @@ -1,5 +1,9 @@ const get = require('get-value'); const cloneDeep = require('lodash/cloneDeep'); +const { + InstrumentationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { SF_API_VERSION, @@ -22,10 +26,10 @@ const { checkInvalidRtTfEvents, handleRtTfSingleEventError, generateErrorObject, + isHttpStatusSuccess, } = require('../../util'); -const { getAccessToken, salesforceResponseHandler } = require('./utils'); +const { salesforceResponseHandler, collectAuthorizationInfo, getAuthHeader } = require('./utils'); const { handleHttpRequest } = require('../../../adapters/network'); -const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); // Basic response builder @@ -38,6 +42,7 @@ function responseBuilderSimple( authorizationData, mapProperty, mappedToDestination, + authorizationFlow, ) { const { salesforceType, salesforceId } = salesforceMap; @@ -84,12 +89,12 @@ function responseBuilderSimple( } const response = defaultRequestConfig(); - const header = { + + response.method = defaultPostRequestConfig.requestMethod; + response.headers = { 'Content-Type': JSON_MIME_TYPE, - Authorization: authorizationData.token, + ...getAuthHeader({ authorizationFlow, authorizationData }), }; - response.method = defaultPostRequestConfig.requestMethod; - response.headers = header; response.body.JSON = removeUndefinedValues(rawPayload); response.endpoint = targetEndpoint; @@ -103,24 +108,26 @@ async function getSaleforceIdForRecord( identifierType, identifierValue, destination, + authorizationFlow, ) { const objSearchUrl = `${authorizationData.instanceUrl}/services/data/v${SF_API_VERSION}/parameterizedSearch/?q=${identifierValue}&sobject=${objectType}&in=${identifierType}&${objectType}.fields=id,${identifierType}`; const { processedResponse: processedsfSearchResponse } = await handleHttpRequest( 'get', objSearchUrl, { - headers: { Authorization: authorizationData.token }, + headers: getAuthHeader({ authorizationFlow, authorizationData }), }, { destType: 'salesforce', feature: 'transformation', }, ); - if (processedsfSearchResponse.status !== 200) { + if (!isHttpStatusSuccess(processedsfSearchResponse.status)) { salesforceResponseHandler( processedsfSearchResponse, `:- SALESFORCE SEARCH BY ID`, destination.ID, + authorizationFlow, ); } const searchRecord = processedsfSearchResponse.response?.searchRecords?.find( @@ -146,7 +153,12 @@ async function getSaleforceIdForRecord( // We'll use the Salesforce Object names by removing "Salesforce-" string from the type field // // Default Object type will be "Lead" for backward compatibility -async function getSalesforceIdFromPayload(message, authorizationData, destination) { +async function getSalesforceIdFromPayload( + message, + authorizationData, + destination, + authorizationFlow, +) { // define default map const salesforceMaps = []; @@ -188,6 +200,7 @@ async function getSalesforceIdFromPayload(message, authorizationData, destinatio identifierType, id, destination, + authorizationFlow, ); } @@ -209,12 +222,13 @@ async function getSalesforceIdFromPayload(message, authorizationData, destinatio throw new InstrumentationError('Invalid Email address for Lead Objet'); } const leadQueryUrl = `${authorizationData.instanceUrl}/services/data/v${SF_API_VERSION}/parameterizedSearch/?q=${email}&sobject=Lead&Lead.fields=id,IsConverted,ConvertedContactId,IsDeleted`; + // request configuration will be conditional const { processedResponse: processedLeadQueryResponse } = await handleHttpRequest( 'get', leadQueryUrl, { - headers: { Authorization: authorizationData.token }, + headers: getAuthHeader({ authorizationFlow, authorizationData }), }, { destType: 'salesforce', @@ -222,8 +236,13 @@ async function getSalesforceIdFromPayload(message, authorizationData, destinatio }, ); - if (processedLeadQueryResponse.status !== 200) { - salesforceResponseHandler(processedLeadQueryResponse, `:- during Lead Query`, destination.ID); + if (!isHttpStatusSuccess(processedLeadQueryResponse.status)) { + salesforceResponseHandler( + processedLeadQueryResponse, + `:- during Lead Query`, + destination.ID, + authorizationFlow, + ); } if (processedLeadQueryResponse.response.searchRecords.length > 0) { @@ -259,7 +278,7 @@ async function getSalesforceIdFromPayload(message, authorizationData, destinatio } // Function for handling identify events -async function processIdentify(message, authorizationData, destination) { +async function processIdentify(message, authorizationData, destination, authorizationFlow) { const mapProperty = destination.Config.mapProperty === undefined ? true : destination.Config.mapProperty; // check the traits before hand @@ -280,7 +299,12 @@ async function processIdentify(message, authorizationData, destination) { const responseData = []; // get salesforce object map - const salesforceMaps = await getSalesforceIdFromPayload(message, authorizationData, destination); + const salesforceMaps = await getSalesforceIdFromPayload( + message, + authorizationData, + destination, + authorizationFlow, + ); // iterate over the object types found salesforceMaps.forEach((salesforceMap) => { @@ -292,6 +316,7 @@ async function processIdentify(message, authorizationData, destination) { authorizationData, mapProperty, mappedToDestination, + authorizationFlow, ), ); }); @@ -301,10 +326,10 @@ async function processIdentify(message, authorizationData, destination) { // Generic process function which invokes specific handler functions depending on message type // and event type where applicable -async function processSingleMessage(message, authorizationData, destination) { +async function processSingleMessage(message, authorizationData, destination, authorizationFlow) { let response; if (message.type === EventType.IDENTIFY) { - response = await processIdentify(message, authorizationData, destination); + response = await processIdentify(message, authorizationData, destination, authorizationFlow); } else { throw new InstrumentationError(`message type ${message.type} is not supported`); } @@ -312,9 +337,13 @@ async function processSingleMessage(message, authorizationData, destination) { } async function process(event) { - // Get the authorization header if not available - const authorizationData = await getAccessToken(event.destination); - const response = await processSingleMessage(event.message, authorizationData, event.destination); + const authInfo = await collectAuthorizationInfo(event); + const response = await processSingleMessage( + event.message, + authInfo.authorizationData, + event.destination, + authInfo.authorizationFlow, + ); return response; } @@ -323,10 +352,9 @@ const processRouterDest = async (inputs, reqMetadata) => { if (errorRespEvents.length > 0) { return errorRespEvents; } - - let authorizationData; + let authInfo; try { - authorizationData = await getAccessToken(inputs[0].destination); + authInfo = await collectAuthorizationInfo(inputs[0]); } catch (error) { const errObj = generateErrorObject(error); const respEvents = getErrorRespEvents( @@ -348,7 +376,12 @@ const processRouterDest = async (inputs, reqMetadata) => { // unprocessed payload return getSuccessRespEvents( - await processSingleMessage(input.message, authorizationData, input.destination), + await processSingleMessage( + input.message, + authInfo.authorizationData, + input.destination, + authInfo.authorizationFlow, + ), [input.metadata], input.destination, ); diff --git a/src/v0/destinations/salesforce/utils.js b/src/v0/destinations/salesforce/utils.js index 3ffa4e56d8..96735ecc17 100644 --- a/src/v0/destinations/salesforce/utils.js +++ b/src/v0/destinations/salesforce/utils.js @@ -1,12 +1,18 @@ +const { RetryableError, ThrottledError, AbortedError } = require('@rudderstack/integrations-lib'); const { handleHttpRequest } = require('../../../adapters/network'); -const { isHttpStatusSuccess } = require('../../util'); +const { + isHttpStatusSuccess, + getAuthErrCategoryFromStCode, + isDefinedAndNotNull, +} = require('../../util'); const Cache = require('../../util/cache'); -const { RetryableError, ThrottledError, AbortedError } = require('../../util/errorTypes'); const { ACCESS_TOKEN_CACHE_TTL, SF_TOKEN_REQUEST_URL_SANDBOX, SF_TOKEN_REQUEST_URL, DESTINATION, + LEGACY, + OAUTH, } = require('./config'); const ACCESS_TOKEN_CACHE = new Cache(ACCESS_TOKEN_CACHE_TTL); @@ -19,7 +25,7 @@ const ACCESS_TOKEN_CACHE = new Cache(ACCESS_TOKEN_CACHE_TTL); * @param {*} stage * @param {String} authKey */ -const salesforceResponseHandler = (destResponse, sourceMessage, authKey) => { +const salesforceResponseHandler = (destResponse, sourceMessage, authKey, authorizationFlow) => { const { status, response } = destResponse; // if the response from destination is not a success case build an explicit error @@ -27,6 +33,14 @@ const salesforceResponseHandler = (destResponse, sourceMessage, authKey) => { const matchErrorCode = (errorCode) => response && Array.isArray(response) && response.some((resp) => resp?.errorCode === errorCode); if (status === 401 && authKey && matchErrorCode('INVALID_SESSION_ID')) { + if (authorizationFlow === OAUTH) { + throw new RetryableError( + `${DESTINATION} Request Failed - due to "INVALID_SESSION_ID", (Retryable) ${sourceMessage}`, + 500, + destResponse, + getAuthErrCategoryFromStCode(status), + ); + } // checking for invalid/expired token errors and evicting cache in that case // rudderJobMetadata contains some destination info which is being used to evict the cache ACCESS_TOKEN_CACHE.del(authKey); @@ -89,6 +103,11 @@ const salesforceResponseHandler = (destResponse, sourceMessage, authKey) => { * @param {*} destination * @returns */ +const getAccessTokenOauth = (metadata) => ({ + token: metadata.secret?.access_token, + instanceUrl: metadata.secret?.instance_url, +}); + const getAccessToken = async (destination) => { const accessTokenKey = destination.ID; @@ -122,6 +141,7 @@ const getAccessToken = async (destination) => { processedResponse, `:- authentication failed during fetching access token.`, accessTokenKey, + LEGACY, ); } const token = httpResponse.response.data; @@ -131,6 +151,7 @@ const getAccessToken = async (destination) => { processedResponse, `:- authentication failed could not retrieve authorization token.`, accessTokenKey, + LEGACY, ); } return { @@ -140,4 +161,30 @@ const getAccessToken = async (destination) => { }); }; -module.exports = { getAccessToken, salesforceResponseHandler }; +const collectAuthorizationInfo = async (event) => { + let authorizationFlow; + let authorizationData; + if (isDefinedAndNotNull(event.metadata?.secret)) { + authorizationFlow = OAUTH; + authorizationData = getAccessTokenOauth(event.metadata); + } else { + authorizationFlow = LEGACY; + authorizationData = await getAccessToken(event.destination); + } + return { authorizationFlow, authorizationData }; +}; + +const getAuthHeader = (authInfo) => { + const { authorizationFlow, authorizationData } = authInfo; + return authorizationFlow === OAUTH + ? { Authorization: `Bearer ${authorizationData.token}` } + : { Authorization: authorizationData.token }; +}; + +module.exports = { + getAccessTokenOauth, + salesforceResponseHandler, + getAccessToken, + collectAuthorizationInfo, + getAuthHeader, +}; diff --git a/src/v0/destinations/salesforce_oauth/networkHandler.js b/src/v0/destinations/salesforce_oauth/networkHandler.js new file mode 100644 index 0000000000..2bcace31c9 --- /dev/null +++ b/src/v0/destinations/salesforce_oauth/networkHandler.js @@ -0,0 +1,33 @@ +const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); +const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); +const { OAUTH } = require('../salesforce/config'); +const { salesforceResponseHandler } = require('../salesforce/utils'); + +const responseHandler = (destinationResponse, destType) => { + const message = `Request for destination: ${destType} Processed Successfully`; + + salesforceResponseHandler( + destinationResponse, + 'during Salesforce Response Handling', + destinationResponse?.rudderJobMetadata?.destInfo?.authKey, + OAUTH, + ); + + // else successfully return status as 200, message and original destination response + return { + status: 200, + message, + destinationResponse, + }; +}; + +function networkHandler() { + this.responseHandler = responseHandler; + this.proxy = proxyRequest; + this.prepareProxy = prepareProxyRequest; + this.processAxiosResponse = processAxiosResponse; +} + +module.exports = { + networkHandler, +}; diff --git a/src/v0/destinations/sendgrid/deleteUsers.js b/src/v0/destinations/sendgrid/deleteUsers.js index e93fefa59e..8410f41296 100644 --- a/src/v0/destinations/sendgrid/deleteUsers.js +++ b/src/v0/destinations/sendgrid/deleteUsers.js @@ -1,3 +1,4 @@ +const { NetworkError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { httpDELETE } = require('../../../adapters/network'); const { delIdUrlLimit, DELETE_CONTACTS_ENDPOINT } = require('./config'); const { @@ -5,7 +6,6 @@ const { getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { isHttpStatusSuccess } = require('../../util'); -const { NetworkError, ConfigurationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { executeCommonValidations } = require('../../util/regulation-api'); diff --git a/src/v0/destinations/sendgrid/transform.js b/src/v0/destinations/sendgrid/transform.js index d2f5b38b70..5038fedf7b 100644 --- a/src/v0/destinations/sendgrid/transform.js +++ b/src/v0/destinations/sendgrid/transform.js @@ -1,4 +1,9 @@ const lodash = require('lodash'); +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ErrorMessage, @@ -34,11 +39,6 @@ const { generatePayloadFromConfig, createOrUpdateContactPayloadBuilder, } = require('./util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, method, endpoint, apiKey) => { diff --git a/src/v0/destinations/sendgrid/util.js b/src/v0/destinations/sendgrid/util.js index fad227a65b..1df34bfe69 100644 --- a/src/v0/destinations/sendgrid/util.js +++ b/src/v0/destinations/sendgrid/util.js @@ -1,4 +1,9 @@ const get = require('get-value'); +const { + NetworkError, + ConfigurationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const logger = require('../../../logger'); const { isEmpty, @@ -21,7 +26,6 @@ const { processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); const { httpGET } = require('../../../adapters/network'); -const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { AUTH_CACHE_TTL, JSON_MIME_TYPE } = require('../../util/constant'); const { MAPPING_CONFIG, CONFIG_CATEGORIES } = require('./config'); diff --git a/src/v0/destinations/sendinblue/transform.js b/src/v0/destinations/sendinblue/transform.js index 151304db22..7663672f12 100644 --- a/src/v0/destinations/sendinblue/transform.js +++ b/src/v0/destinations/sendinblue/transform.js @@ -1,5 +1,6 @@ /* eslint-disable camelcase */ /* eslint-disable @typescript-eslint/naming-convention */ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -25,7 +26,6 @@ const { prepareTrackEventData, getListIds, } = require('./util'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = ( payload, diff --git a/src/v0/destinations/sendinblue/util.js b/src/v0/destinations/sendinblue/util.js index f184ee1ac1..9ad37fc9b7 100644 --- a/src/v0/destinations/sendinblue/util.js +++ b/src/v0/destinations/sendinblue/util.js @@ -1,3 +1,4 @@ +const { NetworkError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EMAIL_SUFFIX, getContactDetailsEndpoint } = require('./config'); const { getHashFromArray, @@ -12,7 +13,6 @@ const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/serenytics/transform.js b/src/v0/destinations/serenytics/transform.js index ee7279e288..ee38f7d1a1 100644 --- a/src/v0/destinations/serenytics/transform.js +++ b/src/v0/destinations/serenytics/transform.js @@ -1,14 +1,14 @@ +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { ErrorMessage, simpleProcessRouterDest, getHashFromArrayWithDuplicate, } = require('../../util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { CONFIG_CATEGORIES, diff --git a/src/v0/destinations/serenytics/utils.js b/src/v0/destinations/serenytics/utils.js index bccce2585d..90ce374d5a 100644 --- a/src/v0/destinations/serenytics/utils.js +++ b/src/v0/destinations/serenytics/utils.js @@ -1,10 +1,10 @@ +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { constructPayload, extractCustomFields, defaultRequestConfig, defaultPostRequestConfig, } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); const { MAPPING_CONFIG } = require('./config'); const checkStorageUrl = (STORAGE_URL, messageType) => { diff --git a/src/v0/destinations/sfmc/transform.js b/src/v0/destinations/sfmc/transform.js index 161720b2cc..7623d751f1 100644 --- a/src/v0/destinations/sfmc/transform.js +++ b/src/v0/destinations/sfmc/transform.js @@ -1,4 +1,11 @@ /* eslint-disable no-nested-ternary */ +const { + NetworkError, + ConfigurationError, + InstrumentationError, + isDefinedAndNotNull, + isEmpty, +} = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, ENDPOINTS } = require('./config'); @@ -12,14 +19,12 @@ const { flattenJson, toTitleCase, getHashFromArray, - isEmpty, simpleProcessRouterDest, } = require('../../util'); const { getDynamicErrorType, nodeSysErrorToStatus, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); @@ -217,10 +222,22 @@ const responseBuilderSimple = async (message, category, destination) => { } if (category.type === 'identify' && createOrUpdateContacts) { - throw new ConfigurationError('Creating or updating contacts is disabled'); + throw new ConfigurationError( + 'Creating or updating contacts is disabled. To enable this feature set "Do Not Create or Update Contacts" to false', + ); } - if (category.type === 'track' && hashMapExternalKey[message.event.toLowerCase()]) { + if (category.type === 'track') { + if (isEmpty(message.event)) { + throw new ConfigurationError('Event name is required for track events'); + } + if (typeof message.event !== 'string') { + throw new ConfigurationError('Event name must be a string'); + } + if (!isDefinedAndNotNull(hashMapExternalKey[message.event.toLowerCase()])) { + throw new ConfigurationError('Event not mapped for this track call'); + } + return responseBuilderForInsertData( message, hashMapExternalKey[message.event.toLowerCase()], @@ -233,7 +250,7 @@ const responseBuilderSimple = async (message, category, destination) => { ); } - throw new ConfigurationError('Event not mapped for this track call'); + throw new ConfigurationError(`Event type '${category.type}' not supported`); }; const processEvent = async (message, destination) => { @@ -270,4 +287,4 @@ const processRouterDest = async (inputs, reqMetadata) => { return respList; }; -module.exports = { process, processRouterDest }; +module.exports = { process, processRouterDest, responseBuilderSimple }; diff --git a/src/v0/destinations/sfmc/transform.test.js b/src/v0/destinations/sfmc/transform.test.js new file mode 100644 index 0000000000..c49c49017c --- /dev/null +++ b/src/v0/destinations/sfmc/transform.test.js @@ -0,0 +1,125 @@ +const { ConfigurationError } = require('@rudderstack/integrations-lib'); +const axios = require('axios'); +const MockAxiosAdapter = require('axios-mock-adapter'); +const { responseBuilderSimple } = require('./transform'); +beforeAll(() => { + const mock = new MockAxiosAdapter(axios); + mock + .onPost('https://yourSubDomain.auth.marketingcloudapis.com/v2/token') + .reply(200, '{"access_token":"yourAuthToken"}'); +}); + +describe('responseBuilderSimple', () => { + const destination = { + Config: { + clientId: 'yourClientId', + clientSecret: 'yourClientSecret', + subDomain: 'yourSubDomain', + createOrUpdateContacts: false, + externalKey: 'yourExternalKey', + eventToExternalKey: [{ from: 'purchase', to: 'purchaseKey' }], + eventToPrimaryKey: [{ from: 'purchase', to: 'primaryKey' }], + eventToUUID: [{ event: 'purchase', uuid: true }], + }, + }; + it('should return an array of two payloads for identify calls when createOrUpdateContacts is false', async () => { + const message = { + type: 'identify', + userId: '12345', + }; + + const category = { + type: 'identify', + name: 'Identify', + }; + + const response = await responseBuilderSimple(message, category, destination); + + expect(response).toHaveLength(2); + expect(response[0]).toHaveProperty('endpoint'); + expect(response[0]).toHaveProperty('method'); + expect(response[0]).toHaveProperty('body.JSON'); + expect(response[0]).toHaveProperty('headers'); + expect(response[1]).toHaveProperty('endpoint'); + expect(response[1]).toHaveProperty('method'); + expect(response[1]).toHaveProperty('body.JSON'); + expect(response[1]).toHaveProperty('headers'); + }); + + // Throws an error when event name is not provided for track calls + it('should throw an error when event name is not provided for track calls', async () => { + const message = { + type: 'track', + }; + + const category = { + type: 'track', + name: 'Track', + }; + + try { + await responseBuilderSimple(message, category, destination); + } catch (e) { + expect(e).toBeInstanceOf(ConfigurationError); + expect(e.message).toBe('Event name is required for track events'); + } + }); + + // Throws an error when event is not mapped for track calls + it('should throw an error when event is not mapped for track calls', async () => { + const message = { + type: 'track', + event: 'unmappedEvent', + }; + + const category = { + type: 'track', + name: 'Track', + }; + try { + await responseBuilderSimple(message, category, destination); + } catch (e) { + expect(e).toBeInstanceOf(ConfigurationError); + expect(e.message).toBe('Event not mapped for this track call'); + } + }); + + // Throws an error when event type is not supported + it('should throw an error when event type is not supported', async () => { + const message = { + type: 'unsupported', + }; + + const category = { + type: 'unsupported', + name: 'Unsupported', + }; + + try { + await responseBuilderSimple(message, category, destination); + } catch (e) { + expect(e).toBeInstanceOf(ConfigurationError); + expect(e.message).toBe("Event type 'unsupported' not supported"); + } + }); + + // Returns a payload for track calls when event is mapped and event name is a string + it('should return a payload for track calls when event is mapped and event name is a string', async () => { + const message = { + type: 'track', + event: 'purchase', + userId: '12345', + }; + + const category = { + type: 'track', + name: 'Track', + }; + + const response = await responseBuilderSimple(message, category, destination); + expect(response).toHaveProperty('endpoint'); + expect(response).toHaveProperty('method'); + expect(response).toHaveProperty('body.JSON'); + expect(response).toHaveProperty('headers'); + }); +}); diff --git a/src/v0/destinations/shynet/transform.js b/src/v0/destinations/shynet/transform.js index 833616a11f..565c0790d5 100644 --- a/src/v0/destinations/shynet/transform.js +++ b/src/v0/destinations/shynet/transform.js @@ -1,4 +1,5 @@ /* eslint-disable no-underscore-dangle */ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -9,7 +10,6 @@ const { generateUUID, } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); -const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig } = require('./config'); diff --git a/src/v0/destinations/signl4/transform.js b/src/v0/destinations/signl4/transform.js index 63dc10d73c..3a8b23b630 100644 --- a/src/v0/destinations/signl4/transform.js +++ b/src/v0/destinations/signl4/transform.js @@ -1,3 +1,8 @@ +const { + ConfigurationError, + TransformationError, + InstrumentationError, +} = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { BASE_URL } = require('./config'); const { populatePayload } = require('./utils'); @@ -7,11 +12,6 @@ const { simpleProcessRouterDest, removeUndefinedAndNullAndEmptyValues, } = require('../../util'); -const { - ConfigurationError, - TransformationError, - InstrumentationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint) => { diff --git a/src/v0/destinations/singular/transform.js b/src/v0/destinations/singular/transform.js index 749debb0b0..ff5d18db9a 100644 --- a/src/v0/destinations/singular/transform.js +++ b/src/v0/destinations/singular/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { BASE_URL } = require('./config'); const { defaultRequestConfig, @@ -10,7 +11,6 @@ const { generateRevenuePayloadArray, isSessionEvent, } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const responseBuilderSimple = (message, { Config }) => { const eventName = message.event; diff --git a/src/v0/destinations/singular/util.js b/src/v0/destinations/singular/util.js index 542b049a2e..4c5aeb8964 100644 --- a/src/v0/destinations/singular/util.js +++ b/src/v0/destinations/singular/util.js @@ -1,4 +1,5 @@ const lodash = require('lodash'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, @@ -20,7 +21,6 @@ const { isDefinedAndNotNull, isAppleFamily, } = require('../../util'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); /* All the fields listed inside properties which are not directly mapped, will be sent to 'e' as custom event attributes diff --git a/src/v0/destinations/slack/transform.js b/src/v0/destinations/slack/transform.js index 8db934d71f..41282c6887 100644 --- a/src/v0/destinations/slack/transform.js +++ b/src/v0/destinations/slack/transform.js @@ -1,5 +1,6 @@ /* eslint-disable no-nested-ternary, no-restricted-syntax, no-prototype-builtins */ const Handlebars = require('handlebars'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { stringifyJSON, @@ -17,7 +18,6 @@ const { simpleProcessRouterDest, isDefinedAndNotNull, } = require('../../util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); // build the response to be sent to backend, url encoded header is required as slack accepts payload in this format // add the username and image for Rudder diff --git a/src/v0/destinations/snapchat_conversion/data/OrderCompletedConfig.json b/src/v0/destinations/snapchat_conversion/data/OrderCompletedConfig.json index dc5696e9a4..38e85ca2d8 100644 --- a/src/v0/destinations/snapchat_conversion/data/OrderCompletedConfig.json +++ b/src/v0/destinations/snapchat_conversion/data/OrderCompletedConfig.json @@ -6,7 +6,7 @@ }, { "destKey": "item_category", - "sourceKeys": "properties.item_category", + "sourceKeys": ["properties.item_category", "properties.category"], "required": false }, { diff --git a/src/v0/destinations/snapchat_conversion/transform.js b/src/v0/destinations/snapchat_conversion/transform.js index 49776935de..37d321a468 100644 --- a/src/v0/destinations/snapchat_conversion/transform.js +++ b/src/v0/destinations/snapchat_conversion/transform.js @@ -1,5 +1,6 @@ const get = require('get-value'); const moment = require('moment'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { @@ -33,7 +34,6 @@ const { channelMapping, generateBatchedPayloadForArray, } = require('./util'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function buildResponse(apiKey, payload) { diff --git a/src/v0/destinations/snapchat_custom_audience/networkHandler.js b/src/v0/destinations/snapchat_custom_audience/networkHandler.js index 196f9a87fb..db36f6f518 100644 --- a/src/v0/destinations/snapchat_custom_audience/networkHandler.js +++ b/src/v0/destinations/snapchat_custom_audience/networkHandler.js @@ -1,3 +1,4 @@ +const { NetworkError, RetryableError, AbortedError } = require('@rudderstack/integrations-lib'); const { removeUndefinedValues, getAuthErrCategoryFromErrDetailsAndStCode } = require('../../util'); const { prepareProxyRequest, getPayloadData, httpSend } = require('../../../adapters/network'); const { isHttpStatusSuccess } = require('../../util/index'); @@ -7,7 +8,6 @@ const { getDynamicErrorType, processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); -const { NetworkError, RetryableError, AbortedError } = require('../../util/errorTypes'); const { HTTP_STATUS_CODES } = require('../../util/constant'); const prepareProxyReq = (request) => { diff --git a/src/v0/destinations/snapchat_custom_audience/transform.js b/src/v0/destinations/snapchat_custom_audience/transform.js index 7938236594..f4cbeafb56 100644 --- a/src/v0/destinations/snapchat_custom_audience/transform.js +++ b/src/v0/destinations/snapchat_custom_audience/transform.js @@ -1,4 +1,5 @@ const sha256 = require('sha256'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, removeUndefinedAndNullValues, @@ -6,7 +7,6 @@ const { isDefinedAndNotNullAndNotEmpty, getAccessToken, } = require('../../util'); -const { ConfigurationError } = require('../../util/errorTypes'); const { BASE_URL, schemaType } = require('./config'); const { validatePayload, validateFields } = require('./utils'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/snapchat_custom_audience/utils.js b/src/v0/destinations/snapchat_custom_audience/utils.js index 4d20b27a09..bc4a2292da 100644 --- a/src/v0/destinations/snapchat_custom_audience/utils.js +++ b/src/v0/destinations/snapchat_custom_audience/utils.js @@ -1,4 +1,4 @@ -const { InstrumentationError } = require('../../util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); /** * Verifies whether the input payload is in right format or not diff --git a/src/v0/destinations/splitio/transform.js b/src/v0/destinations/splitio/transform.js index 012c73a8b6..6641a62fe8 100644 --- a/src/v0/destinations/splitio/transform.js +++ b/src/v0/destinations/splitio/transform.js @@ -1,3 +1,4 @@ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, @@ -18,7 +19,6 @@ const { simpleProcessRouterDest, ErrorMessage, } = require('../../util'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, category, destination) { diff --git a/src/v0/destinations/statsig/transform.js b/src/v0/destinations/statsig/transform.js index 1be72d4095..81658a255a 100644 --- a/src/v0/destinations/statsig/transform.js +++ b/src/v0/destinations/statsig/transform.js @@ -1,7 +1,7 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultPostRequestConfig, defaultRequestConfig } = require('../../util'); const { ENDPOINT } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); function process(event) { diff --git a/src/v0/destinations/stormly/transform.js b/src/v0/destinations/stormly/transform.js index 756bfb8024..dc7a256583 100644 --- a/src/v0/destinations/stormly/transform.js +++ b/src/v0/destinations/stormly/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-nested-ternary */ const get = require('get-value'); const set = require('set-value'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -12,7 +13,6 @@ const { getDestinationExternalID, } = require('../../util'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, destination) => { @@ -40,7 +40,8 @@ const identifyResponseBuilder = (message, destination) => { const trackResponseBuilder = (message, destination) => { const { endpoint, name } = CONFIG_CATEGORIES.TRACK; - const groupId = getDestinationExternalID(message, 'stormlyGroupId') || message.properties?.groupId; + const groupId = + getDestinationExternalID(message, 'stormlyGroupId') || message.properties?.groupId; let payload = constructPayload(message, MAPPING_CONFIG[name]); if (groupId) { diff --git a/src/v0/destinations/tiktok_ads/data/TikTokTrack.json b/src/v0/destinations/tiktok_ads/data/TikTokTrack.json index b15223b999..cc5f4886e0 100644 --- a/src/v0/destinations/tiktok_ads/data/TikTokTrack.json +++ b/src/v0/destinations/tiktok_ads/data/TikTokTrack.json @@ -72,6 +72,11 @@ "sourceKeys": ["properties.context.ad", "context.ad"], "required": false }, + { + "destKey": "context.ad.callback", + "sourceKeys": "properties.clickId", + "required": false + }, { "destKey": "context.page", "sourceKeys": ["properties.context.page", "context.page"], diff --git a/src/v0/destinations/tiktok_ads/networkHandler.js b/src/v0/destinations/tiktok_ads/networkHandler.js index 1ec31e982a..ae93b1ec15 100644 --- a/src/v0/destinations/tiktok_ads/networkHandler.js +++ b/src/v0/destinations/tiktok_ads/networkHandler.js @@ -1,10 +1,10 @@ +const { NetworkError, ThrottledError, AbortedError } = require('@rudderstack/integrations-lib'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { DESTINATION } = require('./config'); -const { NetworkError, ThrottledError, AbortedError } = require('../../util/errorTypes'); const { TAG_NAMES } = require('../../util/tags'); const { HTTP_STATUS_CODES } = require('../../util/constant'); diff --git a/src/v0/destinations/tiktok_ads/transform.js b/src/v0/destinations/tiktok_ads/transform.js index 4e99d83575..09f0d95dcc 100644 --- a/src/v0/destinations/tiktok_ads/transform.js +++ b/src/v0/destinations/tiktok_ads/transform.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const { SHA256 } = require('crypto-js'); const get = require('get-value'); const set = require('set-value'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { constructPayload, @@ -29,7 +30,6 @@ const { MAX_BATCH_SIZE, PARTNER_NAME, } = require('./config'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const USER_EMAIL_KEY_PATH = 'context.user.email'; @@ -128,7 +128,7 @@ const getTrackResponse = (message, Config, event) => { }; const trackResponseBuilder = async (message, { Config }) => { - const { eventsToStandard } = Config; + const { eventsToStandard, sendCustomEvents } = Config; let event = message.event?.toLowerCase().trim(); if (!event) { @@ -137,7 +137,7 @@ const trackResponseBuilder = async (message, { Config }) => { const standardEventsMap = getHashFromArrayWithDuplicate(eventsToStandard); - if (eventNameMapping[event] === undefined && !standardEventsMap[event]) { + if (!sendCustomEvents && eventNameMapping[event] === undefined && !standardEventsMap[event]) { throw new InstrumentationError( `Event name (${event}) is not valid, must be mapped to one of standard events`, ); @@ -152,10 +152,12 @@ const trackResponseBuilder = async (message, { Config }) => { }); } }); - } else { - event = eventNameMapping[event]; - responseList.push(getTrackResponse(message, Config, event)); + return responseList; } + // Doc https://ads.tiktok.com/help/article/standard-events-parameters?lang=en + event = eventNameMapping[event] || event; + // if there exists no event mapping we will build payload with custom event recieved + responseList.push(getTrackResponse(message, Config, event)); return responseList; }; diff --git a/src/v0/destinations/tiktok_ads_offline_events/transform.js b/src/v0/destinations/tiktok_ads_offline_events/transform.js index 3539c856a3..945c31ea63 100644 --- a/src/v0/destinations/tiktok_ads_offline_events/transform.js +++ b/src/v0/destinations/tiktok_ads_offline_events/transform.js @@ -1,6 +1,7 @@ const { SHA256 } = require('crypto-js'); const set = require('set-value'); const lodash = require('lodash'); +const { ConfigurationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { constructPayload, @@ -21,7 +22,6 @@ const { EVENT_NAME_MAPPING, PARTNER_NAME, } = require('./config'); -const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const getContents = (message) => { diff --git a/src/v0/destinations/trengo/transform.js b/src/v0/destinations/trengo/transform.js index 14d1d8c84c..06e5496a1e 100644 --- a/src/v0/destinations/trengo/transform.js +++ b/src/v0/destinations/trengo/transform.js @@ -2,6 +2,13 @@ /* eslint-disable no-prototype-builtins */ const Handlebars = require('handlebars'); const get = require('get-value'); +const { + NetworkError, + ConfigurationError, + TransformationError, + InstrumentationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { EventType } = require('../../../constants'); const { EndPoints, BASE_URL } = require('./config'); @@ -17,13 +24,6 @@ const { getStringValueOfJSON, ErrorMessage, } = require('../../util'); -const { - NetworkError, - ConfigurationError, - TransformationError, - InstrumentationError, - NetworkInstrumentationError, -} = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/twitter_ads/transform.js b/src/v0/destinations/twitter_ads/transform.js index 363e61072e..268dca3636 100644 --- a/src/v0/destinations/twitter_ads/transform.js +++ b/src/v0/destinations/twitter_ads/transform.js @@ -1,5 +1,10 @@ const sha256 = require('sha256'); +const { + InstrumentationError, + OAuthSecretError, + ConfigurationError, +} = require('@rudderstack/integrations-lib'); const { constructPayload, defaultRequestConfig, @@ -11,11 +16,6 @@ const { const { EventType } = require('../../../constants'); const { ConfigCategories, mappingConfig, BASE_URL } = require('./config'); -const { - InstrumentationError, - OAuthSecretError, - ConfigurationError, -} = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const { getAuthHeaderForRequest } = require('./util'); diff --git a/src/v0/destinations/user/transform.js b/src/v0/destinations/user/transform.js index 6cde9c9b80..ed04f5ccd4 100644 --- a/src/v0/destinations/user/transform.js +++ b/src/v0/destinations/user/transform.js @@ -1,3 +1,8 @@ +const { + TransformationError, + InstrumentationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, simpleProcessRouterDest, @@ -17,11 +22,6 @@ const { createOrUpdateUserPayloadBuilder, createEventOccurrencePayloadBuilder, } = require('./utils'); -const { - TransformationError, - InstrumentationError, - NetworkInstrumentationError, -} = require('../../util/errorTypes'); const { EventType } = require('../../../constants'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/user/utils.js b/src/v0/destinations/user/utils.js index 23dd74a30f..41ad173583 100644 --- a/src/v0/destinations/user/utils.js +++ b/src/v0/destinations/user/utils.js @@ -1,4 +1,8 @@ const get = require('get-value'); +const { + InstrumentationError, + NetworkInstrumentationError, +} = require('@rudderstack/integrations-lib'); const { getHashFromArray, constructPayload, @@ -19,7 +23,6 @@ const { groupSourceKeys, identifySourceKeys, } = require('./config'); -const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const ACCEPT_HEADER_VAL = '*/*;version=2'; diff --git a/src/v0/destinations/userlist/transform.js b/src/v0/destinations/userlist/transform.js index 20b47c6a35..45d58edbbf 100644 --- a/src/v0/destinations/userlist/transform.js +++ b/src/v0/destinations/userlist/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -9,7 +10,6 @@ const { const { endpoint } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); // ------------------------------------------------ diff --git a/src/v0/destinations/vero/transform.js b/src/v0/destinations/vero/transform.js index 7115ea425d..f489056681 100644 --- a/src/v0/destinations/vero/transform.js +++ b/src/v0/destinations/vero/transform.js @@ -1,5 +1,6 @@ const set = require('set-value'); const get = require('get-value'); +const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, constructPayload, @@ -11,7 +12,6 @@ const { } = require('../../util'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); // This function handles the common response payload for the supported calls const responseBuilderSimple = (message, category, destination) => { diff --git a/src/v0/destinations/webengage/transform.js b/src/v0/destinations/webengage/transform.js index 835a486eff..f18a7399ff 100644 --- a/src/v0/destinations/webengage/transform.js +++ b/src/v0/destinations/webengage/transform.js @@ -1,4 +1,5 @@ /* eslint-disable no-param-reassign */ +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { CONFIG_CATEGORIES, @@ -15,7 +16,6 @@ const { simpleProcessRouterDest, extractCustomFields, } = require('../../util'); -const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (message, category, { Config }) => { diff --git a/src/v0/destinations/webhook/transform.js b/src/v0/destinations/webhook/transform.js index a4a7617f68..6a115f1c63 100644 --- a/src/v0/destinations/webhook/transform.js +++ b/src/v0/destinations/webhook/transform.js @@ -1,6 +1,7 @@ /* eslint-disable no-nested-ternary */ const get = require('get-value'); const set = require('set-value'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); const { defaultPostRequestConfig, defaultPutRequestConfig, @@ -17,7 +18,6 @@ const { } = require('../../util'); const { EventType } = require('../../../constants'); -const { ConfigurationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const getPropertyParams = (message) => { diff --git a/src/v0/destinations/woopra/transform.js b/src/v0/destinations/woopra/transform.js index 1414cbac23..9104884416 100644 --- a/src/v0/destinations/woopra/transform.js +++ b/src/v0/destinations/woopra/transform.js @@ -1,5 +1,6 @@ /* eslint-disable no-param-reassign */ const { set, get } = require('lodash'); +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { defaultRequestConfig, constructPayload, @@ -12,7 +13,6 @@ const { const { EventType } = require('../../../constants'); const { BASE_URL, mappingConfig, ConfigCategories } = require('./config'); const { refinePayload, getEvent } = require('./utils'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = (payload, endpoint, method, projectName) => { if (!payload) { diff --git a/src/v0/destinations/wootric/transform.js b/src/v0/destinations/wootric/transform.js index f89e63a5ed..f8b4274af7 100644 --- a/src/v0/destinations/wootric/transform.js +++ b/src/v0/destinations/wootric/transform.js @@ -1,3 +1,4 @@ +const { TransformationError, InstrumentationError } = require('@rudderstack/integrations-lib'); const { EventType } = require('../../../constants'); const { defaultRequestConfig, @@ -19,7 +20,6 @@ const { createDeclinePayloadBuilder, } = require('./util'); const { PROPERTIES, END_USER_PROPERTIES } = require('./config'); -const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); const responseBuilder = async (payload, endpoint, method, accessToken) => { if (payload) { diff --git a/src/v0/destinations/wootric/util.js b/src/v0/destinations/wootric/util.js index 207a0994bb..fce8a66586 100644 --- a/src/v0/destinations/wootric/util.js +++ b/src/v0/destinations/wootric/util.js @@ -1,4 +1,5 @@ const qs = require('qs'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); const { httpGET, httpPOST } = require('../../../adapters/network'); const { getDynamicErrorType, @@ -8,7 +9,6 @@ const { BASE_ENDPOINT, VERSION, ACCESS_TOKEN_CACHE_TTL_SECONDS } = require('./co const { constructPayload, isDefinedAndNotNullAndNotEmpty } = require('../../util'); const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); const Cache = require('../../util/cache'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/yahoo_dsp/transform.js b/src/v0/destinations/yahoo_dsp/transform.js index 8b0875f1a0..4cd1eee73d 100644 --- a/src/v0/destinations/yahoo_dsp/transform.js +++ b/src/v0/destinations/yahoo_dsp/transform.js @@ -1,3 +1,4 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { BASE_ENDPOINT, ENDPOINTS, @@ -12,7 +13,6 @@ const { } = require('../../util'); const { getAccessToken, createPayload } = require('./util'); -const { InstrumentationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); /** diff --git a/src/v0/destinations/yahoo_dsp/util.js b/src/v0/destinations/yahoo_dsp/util.js index a069660bde..d41716935f 100644 --- a/src/v0/destinations/yahoo_dsp/util.js +++ b/src/v0/destinations/yahoo_dsp/util.js @@ -1,12 +1,12 @@ const qs = require('qs'); const sha256 = require('sha256'); +const { InstrumentationError, NetworkError } = require('@rudderstack/integrations-lib'); const { generateJWTToken } = require('../../../util/jwtTokenGenerator'); const { httpSend } = require('../../../adapters/network'); const { isDefinedAndNotNullAndNotEmpty } = require('../../util'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const { ACCESS_TOKEN_CACHE_TTL, AUDIENCE_ATTRIBUTE, DSP_SUPPORTED_OPERATION } = require('./config'); const Cache = require('../../util/cache'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/zendesk/transform.js b/src/v0/destinations/zendesk/transform.js index 869e54c220..bf2bc01ed2 100644 --- a/src/v0/destinations/zendesk/transform.js +++ b/src/v0/destinations/zendesk/transform.js @@ -1,5 +1,10 @@ const get = require('get-value'); const set = require('set-value'); +const { + NetworkInstrumentationError, + InstrumentationError, + NetworkError, +} = require('@rudderstack/integrations-lib'); const myAxios = require('../../../util/myAxios'); const { EventType } = require('../../../constants'); @@ -26,11 +31,6 @@ const { const { getSourceName } = require('./util'); const logger = require('../../../logger'); const { httpGET } = require('../../../adapters/network'); -const { - NetworkInstrumentationError, - InstrumentationError, - NetworkError, -} = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/destinations/zendesk/util.js b/src/v0/destinations/zendesk/util.js index 0d03f73c19..29f3fc0602 100644 --- a/src/v0/destinations/zendesk/util.js +++ b/src/v0/destinations/zendesk/util.js @@ -1,4 +1,4 @@ -const { ConfigurationError } = require('../../util/errorTypes'); +const { ConfigurationError } = require('@rudderstack/integrations-lib'); /** * Get source name from config or return 'Rudder' as default source name diff --git a/src/v0/sources/appcenter/transform.js b/src/v0/sources/appcenter/transform.js index 3a98a6db3e..40399d92e2 100644 --- a/src/v0/sources/appcenter/transform.js +++ b/src/v0/sources/appcenter/transform.js @@ -1,5 +1,6 @@ const path = require('path'); const fs = require('fs'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const { generateUUID } = require('../../util'); const Message = require('../message'); @@ -7,7 +8,6 @@ const mappingJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mappin const { removeUndefinedAndNullValues } = require('../../util'); -const { TransformationError } = require('../../util/errorTypes'); const { JSON_MIME_TYPE } = require('../../util/constant'); const processNormalEvent = (event) => { diff --git a/src/v0/sources/appsflyer/transform.js b/src/v0/sources/appsflyer/transform.js index 862e19acd0..1f21392b67 100644 --- a/src/v0/sources/appsflyer/transform.js +++ b/src/v0/sources/appsflyer/transform.js @@ -1,8 +1,8 @@ const path = require('path'); const fs = require('fs'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const Message = require('../message'); const { generateUUID } = require('../../util'); -const { TransformationError } = require('../../util/errorTypes'); const mappingJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); diff --git a/src/v0/sources/braze/transform.js b/src/v0/sources/braze/transform.js index 34158c8e68..e3d7200023 100644 --- a/src/v0/sources/braze/transform.js +++ b/src/v0/sources/braze/transform.js @@ -2,9 +2,9 @@ const set = require('set-value'); const get = require('get-value'); const path = require('path'); const fs = require('fs'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const { formatTimeStamp, removeUndefinedAndNullValues } = require('../../util'); const Message = require('../message'); -const { TransformationError } = require('../../util/errorTypes'); // import mapping json using JSON.parse to preserve object key order const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); diff --git a/src/v0/sources/canny/transform.js b/src/v0/sources/canny/transform.js index abc6f491b8..9188f5ac34 100644 --- a/src/v0/sources/canny/transform.js +++ b/src/v0/sources/canny/transform.js @@ -1,8 +1,8 @@ const sha256 = require('sha256'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const Message = require('../message'); const { voterMapping, authorMapping, checkForRequiredFields } = require('./util'); const { logger } = require('../../../logger'); -const { TransformationError } = require('../../util/errorTypes'); const CannyOperation = { VOTE_CREATED: 'vote.created', diff --git a/src/v0/sources/canny/util.js b/src/v0/sources/canny/util.js index cd92c0c2af..549b7dcbbc 100644 --- a/src/v0/sources/canny/util.js +++ b/src/v0/sources/canny/util.js @@ -1,6 +1,6 @@ const path = require('path'); const fs = require('fs'); -const { TransformationError } = require('../../util/errorTypes'); +const { TransformationError } = require('@rudderstack/integrations-lib'); // import mapping json using JSON.parse to preserve object key order const voterMapping = JSON.parse( diff --git a/src/v0/sources/customerio/transform.js b/src/v0/sources/customerio/transform.js index 51c353dd3b..a2e69388b9 100644 --- a/src/v0/sources/customerio/transform.js +++ b/src/v0/sources/customerio/transform.js @@ -8,7 +8,6 @@ const Message = require('../message'); const { mappingConfig } = require('./config'); const { isDefinedAndNotNull } = require('../../util'); -// const { TransformationError } = require("../../util/errorTypes"); function process(event) { const message = new Message(`Customer.io`); @@ -35,7 +34,6 @@ function process(event) { message.setProperty('sentAt', validTimestamp); } - // when customer.io does not pass an associated userId, set the email address as anonymousId if ( (message.userId === null || message.userId === undefined) && diff --git a/src/v0/sources/gainsightpx/transform.js b/src/v0/sources/gainsightpx/transform.js index ca91765fa6..92f0a07456 100644 --- a/src/v0/sources/gainsightpx/transform.js +++ b/src/v0/sources/gainsightpx/transform.js @@ -1,4 +1,5 @@ const md5 = require('md5'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const Message = require('../message'); const customMapping = require('./data/customMapping.json'); const identifyMapping = require('./data/identifyMapping.json'); @@ -9,7 +10,6 @@ const surveyMapping = require('./data/surveyMapping.json'); const featureMatchMapping = require('./data/featureMatchMapping.json'); const segmentIoMapping = require('./data/segmentIOMapping.json'); const { refinePayload, refineTraitPayload } = require('./utils'); -const { TransformationError } = require('../../util/errorTypes'); const buildIdentifyPayload = (event) => { let message = new Message(`GAINSIGHTPX`); diff --git a/src/v0/sources/iterable/transform.js b/src/v0/sources/iterable/transform.js index 275051815b..dc3fc72c3c 100644 --- a/src/v0/sources/iterable/transform.js +++ b/src/v0/sources/iterable/transform.js @@ -1,8 +1,8 @@ const path = require('path'); const fs = require('fs'); const md5 = require('md5'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const Message = require('../message'); -const { TransformationError } = require('../../util/errorTypes'); // import mapping json using JSON.parse to preserve object key order const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); diff --git a/src/v0/sources/mailjet/transform.js b/src/v0/sources/mailjet/transform.js index fcc27611bb..d2719cc0ba 100644 --- a/src/v0/sources/mailjet/transform.js +++ b/src/v0/sources/mailjet/transform.js @@ -40,7 +40,7 @@ function process(event) { } message.context.externalId = externalId; - if (message.userId === null || message.userId === undefined) { + if (!message.userId && event.email) { // Treating userId as unique identifier // If userId is not present, then generating it from email using md5 hash function message.userId = md5(event.email); diff --git a/src/v0/sources/mailmodo/transform.js b/src/v0/sources/mailmodo/transform.js index 8b36eafa1a..a4383fb440 100644 --- a/src/v0/sources/mailmodo/transform.js +++ b/src/v0/sources/mailmodo/transform.js @@ -1,9 +1,9 @@ const path = require('path'); const fs = require('fs'); const sha256 = require('sha256'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const { flattenJson, removeUndefinedAndNullAndEmptyValues } = require('../../util'); const Message = require('../message'); -const { TransformationError } = require('../../util/errorTypes'); // import mapping json using JSON.parse to preserve object key order const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); diff --git a/src/v0/sources/monday/transform.js b/src/v0/sources/monday/transform.js index 48cddec301..d63323605b 100644 --- a/src/v0/sources/monday/transform.js +++ b/src/v0/sources/monday/transform.js @@ -1,7 +1,7 @@ const sha256 = require('sha256'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const Message = require('../message'); const { mapping, formEventName } = require('./util'); -const { TransformationError } = require('../../util/errorTypes'); const { generateUUID, removeUndefinedAndNullValues } = require('../../util'); const { JSON_MIME_TYPE } = require('../../util/constant'); diff --git a/src/v0/sources/revenuecat/mapping.json b/src/v0/sources/revenuecat/mapping.json new file mode 100644 index 0000000000..541568b71b --- /dev/null +++ b/src/v0/sources/revenuecat/mapping.json @@ -0,0 +1,10 @@ +[ + { + "sourceKeys": "event.type", + "destKeys": "event" + }, + { + "sourceKeys": "event.id", + "destKeys": "messageId" + } +] diff --git a/src/v0/sources/revenuecat/transform.js b/src/v0/sources/revenuecat/transform.js new file mode 100644 index 0000000000..36944e10fa --- /dev/null +++ b/src/v0/sources/revenuecat/transform.js @@ -0,0 +1,47 @@ +const { camelCase } = require('lodash'); +const moment = require('moment'); +const { removeUndefinedAndNullValues, isDefinedAndNotNull } = require('../../util'); +const Message = require('../message'); + +function process(event) { + const message = new Message(`RevenueCat`); + + // we are setting event type as track always + message.setEventType('track'); + + const properties = {}; + // dump all event properties to message.properties after converting them to camelCase + if (event.event) { + Object.keys(event.event).forEach((key) => { + properties[camelCase(key)] = event.event[key]; + }); + message.setProperty('properties', properties); + } + + // setting up app_user_id to externalId : revenuecatAppUserId + if (event?.event?.app_user_id) { + message.context.externalId = [ + { + type: 'revenuecatAppUserId', + id: event?.event?.app_user_id, + }, + ]; + } + + if ( + isDefinedAndNotNull(event?.event?.event_timestamp_ms) && + moment(event?.event?.event_timestamp_ms).isValid() + ) { + const validTimestamp = new Date(event.event.event_timestamp_ms).toISOString(); + message.setProperty('originalTimestamp', validTimestamp); + message.setProperty('sentAt', validTimestamp); + } + message.event = event?.event?.type; + message.messageId = event?.event?.id; + + // removing undefined and null values from message + removeUndefinedAndNullValues(message); + return message; +} + +module.exports = { process }; diff --git a/src/v0/sources/shopify/transform.js b/src/v0/sources/shopify/transform.js index fd763eeb46..013580d7a3 100644 --- a/src/v0/sources/shopify/transform.js +++ b/src/v0/sources/shopify/transform.js @@ -175,7 +175,7 @@ const processEvent = async (inputEvent, metricMetadata) => { if (message.type !== EventType.IDENTIFY) { const { anonymousId, sessionId } = await getAnonymousIdAndSessionId( message, - metricMetadata, + { shopifyTopic, ...metricMetadata }, redisData, ); if (isDefinedAndNotNull(anonymousId)) { diff --git a/src/v0/sources/shopify/util.js b/src/v0/sources/shopify/util.js index 0d81ddc185..6f31ade4a7 100644 --- a/src/v0/sources/shopify/util.js +++ b/src/v0/sources/shopify/util.js @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ const { v5 } = require('uuid'); const sha256 = require('sha256'); +const { TransformationError } = require('@rudderstack/integrations-lib'); const stats = require('../../../util/stats'); const { constructPayload, @@ -22,7 +23,6 @@ const { useRedisDatabase, maxTimeToIdentifyRSGeneratedCall, } = require('./config'); -const { TransformationError } = require('../../util/errorTypes'); const getDataFromRedis = async (key, metricMetadata) => { try { @@ -32,7 +32,10 @@ const getDataFromRedis = async (key, metricMetadata) => { ...metricMetadata, }); const redisData = await RedisDB.getVal(key); - if (redisData === null) { + if ( + redisData === null || + (typeof redisData === 'object' && Object.keys(redisData).length === 0) + ) { stats.increment('shopify_redis_no_val', { ...metricMetadata, }); @@ -161,6 +164,10 @@ const getAnonymousIdAndSessionId = async (message, metricMetadata, redisData = n } // falling back to cartToken mapping or its hash in case no rudderAnonymousId or rudderSessionId is found if (isDefinedAndNotNull(anonymousId) && isDefinedAndNotNull(sessionId)) { + stats.increment('shopify_anon_id_resolve', { + method: 'note_attributes', + ...metricMetadata, + }); return { anonymousId, sessionId }; } const cartToken = getCartToken(message); @@ -186,6 +193,13 @@ const getAnonymousIdAndSessionId = async (message, metricMetadata, redisData = n Hash the id and use it as anonymousId (limiting 256 -> 36 chars) and sessionId is not sent as its not required field */ anonymousId = v5(cartToken, v5.URL); + } else { + // This metric let us know how many events based on event name used redis for anonId resolution + // and for how many + stats.increment('shopify_anon_id_resolve', { + method: 'database', + ...metricMetadata, + }); } return { anonymousId, sessionId }; }; diff --git a/src/v0/util/errorTypes/abortedError.js b/src/v0/util/errorTypes/abortedError.js deleted file mode 100644 index bf5896c8be..0000000000 --- a/src/v0/util/errorTypes/abortedError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class AbortedError extends BaseError { - constructor(message, statusCode, destResponse, authErrorCategory) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.ABORTED, - }; - - super(message, statusCode || 400, finalStatTags, destResponse, authErrorCategory); - } -} - -module.exports = AbortedError; diff --git a/src/v0/util/errorTypes/configurationError.js b/src/v0/util/errorTypes/configurationError.js deleted file mode 100644 index 59df3718e7..0000000000 --- a/src/v0/util/errorTypes/configurationError.js +++ /dev/null @@ -1,16 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class ConfigurationError extends BaseError { - constructor(message) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.DATA_VALIDATION, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.CONFIGURATION, - }; - - // TODO: Change this to a retryable error - super(message, 400, finalStatTags); - } -} - -module.exports = ConfigurationError; diff --git a/src/v0/util/errorTypes/filteredEventsError.js b/src/v0/util/errorTypes/filteredEventsError.js index 35a384f4e3..990ca76670 100644 --- a/src/v0/util/errorTypes/filteredEventsError.js +++ b/src/v0/util/errorTypes/filteredEventsError.js @@ -1,13 +1,9 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); +const { BaseError } = require('@rudderstack/integrations-lib'); const { HTTP_STATUS_CODES } = require('../constant'); class FilteredEventsError extends BaseError { constructor(message, statusCode = HTTP_STATUS_CODES.FILTER_EVENTS) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.TRANSFORMATION, - }; - super(message, statusCode, finalStatTags); + super(message, statusCode); } } diff --git a/src/v0/util/errorTypes/index.js b/src/v0/util/errorTypes/index.js index 2926306dcd..f3cef657ca 100644 --- a/src/v0/util/errorTypes/index.js +++ b/src/v0/util/errorTypes/index.js @@ -1,37 +1,7 @@ -const { BaseError } = require('./base'); -const TransformationError = require('./transformationError'); -const ConfigurationError = require('./configurationError'); -const InstrumentationError = require('./instrumentationError'); -const PlatformError = require('./platformError'); -const OAuthSecretError = require('./oAuthSecretError'); -const NetworkError = require('./networkError'); -const ThrottledError = require('./throttledError'); -const RedisError = require('./redisError'); -const RetryableError = require('./retryableError'); -const InvalidAuthTokenError = require('./invalidAuthTokenError'); -const AbortedError = require('./abortedError'); -const UnhandledStatusCodeError = require('./unhandledStatusCodeError'); -const UnauthorizedError = require('./unauthorizedError'); -const NetworkInstrumentationError = require('./networkInstrumentationError'); -const UnsupportedEventError = require('./unsupportedEventError'); const FilteredEventsError = require('./filteredEventsError'); +const TransformerProxyError = require('./transformerProxyError'); module.exports = { - BaseError, - TransformationError, - ConfigurationError, - InstrumentationError, - PlatformError, - OAuthSecretError, - NetworkError, - ThrottledError, - RetryableError, - InvalidAuthTokenError, - AbortedError, - UnhandledStatusCodeError, - UnauthorizedError, - NetworkInstrumentationError, - UnsupportedEventError, - RedisError, FilteredEventsError, + TransformerProxyError, }; diff --git a/src/v0/util/errorTypes/instrumentationError.js b/src/v0/util/errorTypes/instrumentationError.js deleted file mode 100644 index 74df966260..0000000000 --- a/src/v0/util/errorTypes/instrumentationError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class InstrumentationError extends BaseError { - constructor(message) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.DATA_VALIDATION, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.INSTRUMENTATION, - }; - - super(message, 400, finalStatTags); - } -} - -module.exports = InstrumentationError; diff --git a/src/v0/util/errorTypes/invalidAuthTokenError.js b/src/v0/util/errorTypes/invalidAuthTokenError.js deleted file mode 100644 index 6a78996c6e..0000000000 --- a/src/v0/util/errorTypes/invalidAuthTokenError.js +++ /dev/null @@ -1,16 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class InvalidAuthTokenError extends BaseError { - constructor(message, statusCode, destResponse, authErrorCategory) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.RETRYABLE, - [tags.TAG_NAMES.META]: tags.METADATA.INVALID_AUTH_TOKEN, - }; - - super(message, statusCode || 500, finalStatTags, destResponse, authErrorCategory); - } -} - -module.exports = InvalidAuthTokenError; diff --git a/src/v0/util/errorTypes/networkInstrumentationError.js b/src/v0/util/errorTypes/networkInstrumentationError.js deleted file mode 100644 index fb9acdfeb4..0000000000 --- a/src/v0/util/errorTypes/networkInstrumentationError.js +++ /dev/null @@ -1,16 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class NetworkInstrumentationError extends BaseError { - constructor(message, destResponse) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.ABORTED, - [tags.TAG_NAMES.META]: tags.METADATA.INSTRUMENTATION, - }; - - super(message, 400, finalStatTags, destResponse); - } -} - -module.exports = NetworkInstrumentationError; diff --git a/src/v0/util/errorTypes/oAuthSecretError.js b/src/v0/util/errorTypes/oAuthSecretError.js deleted file mode 100644 index dd8c51eaac..0000000000 --- a/src/v0/util/errorTypes/oAuthSecretError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class OAuthSecretError extends BaseError { - constructor(message) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.PLATFORM, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.OAUTH_SECRET, - }; - - super(message, 500, finalStatTags); - } -} - -module.exports = OAuthSecretError; diff --git a/src/v0/util/errorTypes/platformError.js b/src/v0/util/errorTypes/platformError.js deleted file mode 100644 index b04ef50c16..0000000000 --- a/src/v0/util/errorTypes/platformError.js +++ /dev/null @@ -1,14 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class PlatformError extends BaseError { - constructor(message) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.PLATFORM, - }; - - super(message, 400, finalStatTags); - } -} - -module.exports = PlatformError; diff --git a/src/v0/util/errorTypes/redisError.js b/src/v0/util/errorTypes/redisError.js deleted file mode 100644 index ec3d49ff2b..0000000000 --- a/src/v0/util/errorTypes/redisError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class RedisError extends BaseError { - constructor(message, statusCode) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.TRANSFORMATION, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.REDIS, - }; - - super(message, statusCode || 500, finalStatTags); - } -} - -module.exports = RedisError; diff --git a/src/v0/util/errorTypes/retryableError.js b/src/v0/util/errorTypes/retryableError.js deleted file mode 100644 index ba18424c76..0000000000 --- a/src/v0/util/errorTypes/retryableError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class RetryableError extends BaseError { - constructor(message, statusCode, destResponse, authErrorCategory) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.RETRYABLE, - }; - - super(message, statusCode || 500, finalStatTags, destResponse, authErrorCategory); - } -} - -module.exports = RetryableError; diff --git a/src/v0/util/errorTypes/throttledError.js b/src/v0/util/errorTypes/throttledError.js deleted file mode 100644 index 0e873c7892..0000000000 --- a/src/v0/util/errorTypes/throttledError.js +++ /dev/null @@ -1,15 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class ThrottledError extends BaseError { - constructor(message, destResponse) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.THROTTLED, - }; - - super(message, 429, finalStatTags, destResponse); - } -} - -module.exports = ThrottledError; diff --git a/src/v0/util/errorTypes/transformationError.js b/src/v0/util/errorTypes/transformationError.js deleted file mode 100644 index 0b28b61984..0000000000 --- a/src/v0/util/errorTypes/transformationError.js +++ /dev/null @@ -1,14 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class TransformationError extends BaseError { - constructor(message, statusCode, destResponse, authErrorCategory) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.TRANSFORMATION, - }; - - super(message, statusCode || 400, finalStatTags, destResponse, authErrorCategory); - } -} - -module.exports = TransformationError; diff --git a/src/v0/util/errorTypes/networkError.js b/src/v0/util/errorTypes/transformerProxyError.js similarity index 72% rename from src/v0/util/errorTypes/networkError.js rename to src/v0/util/errorTypes/transformerProxyError.js index 3461efbbdd..2fefb6fb92 100644 --- a/src/v0/util/errorTypes/networkError.js +++ b/src/v0/util/errorTypes/transformerProxyError.js @@ -1,11 +1,10 @@ +const { BaseError } = require('@rudderstack/integrations-lib'); const tags = require('../tags'); -const { BaseError } = require('./base'); const errorTypes = Object.values(tags.ERROR_TYPES); const metaTypes = Object.values(tags.METADATA); -// To throw error when error type (abort, retry or throttle) has to be dynamically deduced -class NetworkError extends BaseError { - constructor(message, statusCode, statTags, destResponse, authErrorCategory) { +class TransformerProxyError extends BaseError { + constructor(message, statusCode, statTags, destResponse, authErrorCategory, response) { const finalStatTags = { [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.ABORTED, @@ -21,9 +20,9 @@ class NetworkError extends BaseError { finalStatTags[tags.TAG_NAMES.META] = statTags[tags.TAG_NAMES.META]; } } - - super(message, statusCode || 400, finalStatTags, destResponse, authErrorCategory); + super(message, statusCode, finalStatTags, destResponse, authErrorCategory); + this.response = response; } } -module.exports = NetworkError; +module.exports = TransformerProxyError; diff --git a/src/v0/util/errorTypes/unauthorizedError.js b/src/v0/util/errorTypes/unauthorizedError.js deleted file mode 100644 index c9c35795b8..0000000000 --- a/src/v0/util/errorTypes/unauthorizedError.js +++ /dev/null @@ -1,16 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class UnauthorizedError extends BaseError { - constructor(message, statusCode, destResponse, authErrorCategory) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.ABORTED, - [tags.TAG_NAMES.META]: tags.METADATA.UNAUTHORIZED, - }; - - super(message, statusCode || 400, finalStatTags, destResponse, authErrorCategory); - } -} - -module.exports = UnauthorizedError; diff --git a/src/v0/util/errorTypes/unhandledStatusCodeError.js b/src/v0/util/errorTypes/unhandledStatusCodeError.js deleted file mode 100644 index fe35c01c1a..0000000000 --- a/src/v0/util/errorTypes/unhandledStatusCodeError.js +++ /dev/null @@ -1,16 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class UnhandledStatusCodeError extends BaseError { - constructor(message, destResponse) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.NETWORK, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.ABORTED, - [tags.TAG_NAMES.META]: tags.METADATA.UNHANDLED_STATUS_CODE, - }; - - super(message, 400, finalStatTags, destResponse); - } -} - -module.exports = UnhandledStatusCodeError; diff --git a/src/v0/util/errorTypes/unsupportedEventError.js b/src/v0/util/errorTypes/unsupportedEventError.js deleted file mode 100644 index c2e965b620..0000000000 --- a/src/v0/util/errorTypes/unsupportedEventError.js +++ /dev/null @@ -1,14 +0,0 @@ -const tags = require('../tags'); -const { BaseError } = require('./base'); - -class UnsupportedEventError extends BaseError { - constructor(message) { - const finalStatTags = { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.PLATFORM, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.UNSUPPORTED, - }; - super(message, 400, finalStatTags); - } -} - -module.exports = UnsupportedEventError; diff --git a/src/v0/util/facebookUtils/index.js b/src/v0/util/facebookUtils/index.js index d39d1c4ce9..4c09518559 100644 --- a/src/v0/util/facebookUtils/index.js +++ b/src/v0/util/facebookUtils/index.js @@ -1,4 +1,5 @@ const sha256 = require('sha256'); +const { InstrumentationError, TransformationError } = require('@rudderstack/integrations-lib'); const { isObject, getIntegrationsObj, @@ -9,7 +10,6 @@ const { getFieldValueFromMessage, formatTimeStamp, } = require('../index'); -const { InstrumentationError, TransformationError } = require('../errorTypes'); /** This function transforms the payloads according to the config settings and adds, removes or hashes pii data. @param message --> the rudder payload diff --git a/src/v0/util/facebookUtils/networkHandler.js b/src/v0/util/facebookUtils/networkHandler.js index d53d0f76f9..e0d69fa5c8 100644 --- a/src/v0/util/facebookUtils/networkHandler.js +++ b/src/v0/util/facebookUtils/networkHandler.js @@ -1,11 +1,11 @@ const { isEmpty } = require('lodash'); const get = require('get-value'); +const { NetworkError } = require('@rudderstack/integrations-lib'); const { processAxiosResponse, getDynamicErrorType, } = require('../../../adapters/utils/networkUtils'); const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); -const { NetworkError } = require('../errorTypes'); const tags = require('../tags'); const { ErrorDetailsExtractorBuilder } = require('../../../util/error-extractor'); @@ -75,7 +75,7 @@ const errorDetailsMap = { 33: new ErrorDetailsExtractorBuilder() .setStatus(400) .setMessage( - "Object with ID 'PIXEL_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", + "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", ) .build(), default: new ErrorDetailsExtractorBuilder() @@ -151,6 +151,53 @@ const errorDetailsMap = { .setMessage('API User Too Many Calls') .build(), }, + // facebook custom audience related error codes + // ref: + // https://developers.facebook.com/docs/marketing-api/reference/custom-audience/#error-codes-4 + // https://developers.facebook.com/docs/marketing-api/error-reference/ + 294: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessage( + 'Missing permission. Please make sure you have ads_management permission and the application is included in the allowlist', + ) + .build(), + }, + 1487301: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessage( + 'Custom Audience Unavailable: The custom audience you are trying to use has not been shared with your ad account', + ) + .build(), + }, + 1487366: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessage('Custom Audience Has Been Deleted') + .build(), + }, + 2650: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessage('Failed to update the custom audience') + .build(), + }, + 105: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessage('The number of parameters exceeded the maximum for this operation') + .build(), + }, + 80003: { + default: new ErrorDetailsExtractorBuilder() + .setStatus(429) + .setMessage('There have been too many calls to this ad-account.') + .build(), + }, + 200: { + default: new ErrorDetailsExtractorBuilder().setStatus(403).setMessageField('message').build(), + }, }; const getErrorDetailsFromErrorMap = (error) => { diff --git a/src/v0/util/index.js b/src/v0/util/index.js index 4ea3d3783d..34182a7685 100644 --- a/src/v0/util/index.js +++ b/src/v0/util/index.js @@ -16,16 +16,16 @@ const uaParser = require('ua-parser-js'); const moment = require('moment-timezone'); const sha256 = require('sha256'); const crypto = require('crypto'); -const logger = require('../../logger'); -const stats = require('../../util/stats'); -const { DestCanonicalNames, DestHandlerMap } = require('../../constants/destinationCanonicalNames'); const { InstrumentationError, BaseError, PlatformError, TransformationError, OAuthSecretError, -} = require('./errorTypes'); +} = require('@rudderstack/integrations-lib'); +const logger = require('../../logger'); +const stats = require('../../util/stats'); +const { DestCanonicalNames, DestHandlerMap } = require('../../constants/destinationCanonicalNames'); const { client: errNotificationClient } = require('../../util/errorNotifier'); const { HTTP_STATUS_CODES } = require('./constant'); const { @@ -83,7 +83,7 @@ const isPrimitive = (arg) => { const isNewStatusCodesAccepted = (reqMetadata = {}) => { if (reqMetadata && typeof reqMetadata === 'object' && !Array.isArray(reqMetadata)) { const { features } = reqMetadata; - return !!(features && features[FEATURE_FILTER_CODE]); + return !!features?.[FEATURE_FILTER_CODE]; } return false; }; @@ -1403,6 +1403,12 @@ const getMetadata = (metadata) => ({ destinationType: metadata.destinationType, k8_namespace: metadata.namespace, }); + +const getTransformationMetadata = (metadata) => ({ + transformationId: metadata.transformationId, + workspaceId: metadata.workspaceId, +}); + // checks if array 2 is a subset of array 1 function checkSubsetOfArray(array1, array2) { const result = array2.every((val) => array1.includes(val)); @@ -2053,7 +2059,17 @@ const getAuthErrCategoryFromStCode = (status) => { return ''; }; -const validateEventType = (event) => { +const isValidInteger = (value) => { + if (Number.isNaN(value) || !isDefinedAndNotNull(value)) { + return false; + } + if (typeof value === 'number' && value % 1 === 0) { + return true; + } + // Use a regular expression to check if the string is a valid integer or a valid floating-point number + return typeof value === 'string' ? /^-?\d+$/.test(value) : false; +}; +const validateEventName = (event) => { if (!event || typeof event !== 'string') { throw new InstrumentationError('Event is a required field and should be a string'); } @@ -2067,6 +2083,31 @@ const IsGzipSupported = (reqMetadata = {}) => { return false; }; +/** + * Returns an array containing the values of the specified key from each object in the input array. + * If the input array is falsy (null, undefined, empty array), an empty array is returned. + * + * @param {Array} arr - The input array from which values will be extracted. + * @param {string} key - The key of the property whose values will be extracted from each object in the input array. + * @returns {Array} - A new array containing the values of the specified key from each object in the input array. + * + * @example + * const configArray = [ + * { name: 'John', age: 25 }, + * { name: 'Jane', age: 30 }, + * { name: 'Bob', age: 35 } + * ]; + * + * const result = parseConfigArray(configArray, 'name'); + * Output: ['John', 'Jane', 'Bob'] + */ +const parseConfigArray = (arr, key) => { + if (!arr) { + return []; + } + return arr.map((item) => item[key]); +}; + // ======================================================================== // EXPORTS // ======================================================================== @@ -2113,6 +2154,7 @@ module.exports = { getIntegrationsObj, getMappingConfig, getMetadata, + getTransformationMetadata, getParsedIP, getStringValueOfJSON, getSuccessRespEvents, @@ -2160,7 +2202,7 @@ module.exports = { getDestAuthCacheInstance, refinePayload, validateEmail, - validateEventType, + validateEventName, validatePhoneWithCountryCode, getEventReqMetadata, isHybridModeEnabled, @@ -2172,6 +2214,8 @@ module.exports = { hasCircularReference, getAuthErrCategoryFromErrDetailsAndStCode, getAuthErrCategoryFromStCode, + isValidInteger, isNewStatusCodesAccepted, IsGzipSupported, + parseConfigArray, }; diff --git a/src/v0/util/index.test.js b/src/v0/util/index.test.js index ce341e8187..65d6313e30 100644 --- a/src/v0/util/index.test.js +++ b/src/v0/util/index.test.js @@ -1,5 +1,7 @@ +const { TAG_NAMES } = require('@rudderstack/integrations-lib'); const utilities = require('.'); const { getFuncTestData } = require('../../../test/testHelper'); +const { FilteredEventsError } = require('./errorTypes'); const { hasCircularReference, flattenJson } = require('./index'); // Names of the utility functions to test @@ -13,6 +15,7 @@ const functionNames = [ 'batchMultiplexedEvents', 'removeUndefinedNullValuesAndEmptyObjectArray', 'groupEventsByType', + 'isValidInteger', ]; // Names of the utility functions to test which expects multiple arguments as values and not objects @@ -115,3 +118,11 @@ describe('flattenJson', () => { ); }); }); + +describe('tests for generateErrorObject', () => { + test('test-0', () => { + const myErr = new FilteredEventsError('error-1'); + const outputErrObj = utilities.generateErrorObject(myErr); + expect(outputErrObj.statTags).toEqual({}); + }); +}); diff --git a/src/v0/util/regulation-api.js b/src/v0/util/regulation-api.js index 8a557858e0..238993ee81 100644 --- a/src/v0/util/regulation-api.js +++ b/src/v0/util/regulation-api.js @@ -1,4 +1,4 @@ -const { PlatformError } = require('./errorTypes'); +const { PlatformError } = require('@rudderstack/integrations-lib'); const RegulationApiUtils = { /** diff --git a/src/v0/util/testdata/isValidInteger.json b/src/v0/util/testdata/isValidInteger.json new file mode 100644 index 0000000000..be7be936a6 --- /dev/null +++ b/src/v0/util/testdata/isValidInteger.json @@ -0,0 +1,31 @@ +[ + { + "description": "Number is undefined", + "output": false + }, + { + "description": "Number in string format", + "input": "123", + "output": true + }, + { + "description": "Normal Integer", + "input": 123, + "output": true + }, + { + "description": "Float", + "input": 123.91, + "output": false + }, + { + "description": "Float string", + "input": "123.00", + "output": false + }, + { + "description": "Alphanumeric String", + "input": "abcd1234", + "output": false + } +] diff --git a/src/v1/destinations/campaign_manager/networkHandler.js b/src/v1/destinations/campaign_manager/networkHandler.js new file mode 100644 index 0000000000..431cbd6966 --- /dev/null +++ b/src/v1/destinations/campaign_manager/networkHandler.js @@ -0,0 +1,96 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable no-restricted-syntax */ +const { TransformerProxyError } = require('../../../v0/util/errorTypes'); +const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); +const { isHttpStatusSuccess, getAuthErrCategoryFromStCode } = require('../../../v0/util/index'); + +const { + processAxiosResponse, + getDynamicErrorType, +} = require('../../../adapters/utils/networkUtils'); +const tags = require('../../../v0/util/tags'); + +function isEventAbortableAndExtractErrMsg(element, proxyOutputObj) { + let isAbortable = false; + let errorMsg = ''; + // success event + if (!element.errors) { + return isAbortable; + } + for (const err of element.errors) { + errorMsg += `${err.message}, `; + // if code is any of these, event is not retryable + if ( + err.code === 'PERMISSION_DENIED' || + err.code === 'INVALID_ARGUMENT' || + err.code === 'NOT_FOUND' + ) { + isAbortable = true; + } + } + if (errorMsg) { + proxyOutputObj.error = errorMsg; + } + return isAbortable; +} + +const responseHandler = (destinationResponse) => { + const message = `[CAMPAIGN_MANAGER Response V1 Handler] - Request Processed Successfully`; + const responseWithIndividualEvents = []; + const { response, status, rudderJobMetadata } = destinationResponse; + + if (isHttpStatusSuccess(status)) { + // check for Partial Event failures and Successes + const destPartialStatus = response.status; + + for (const [idx, element] of destPartialStatus.entries()) { + const proxyOutputObj = { + statusCode: 200, + metadata: rudderJobMetadata[idx], + error: 'success', + }; + // update status of partial event if abortable + if (isEventAbortableAndExtractErrMsg(element, proxyOutputObj)) { + proxyOutputObj.statusCode = 400; + } + responseWithIndividualEvents.push(proxyOutputObj); + } + + return { + status, + message, + destinationResponse, + response: responseWithIndividualEvents, + }; + } + + // in case of failure status, populate response to maintain len(metadata)=len(response) + const errorMessage = response.error?.message || 'unknown error format'; + for (const metadata of rudderJobMetadata) { + responseWithIndividualEvents.push({ + statusCode: 500, + metadata, + error: errorMessage, + }); + } + + throw new TransformerProxyError( + `Campaign Manager: Error transformer proxy v1 during CAMPAIGN_MANAGER response transformation`, + 500, + { + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), + }, + destinationResponse, + getAuthErrCategoryFromStCode(status), + responseWithIndividualEvents, + ); +}; + +function networkHandler() { + this.prepareProxy = prepareProxyRequest; + this.proxy = proxyRequest; + this.processAxiosResponse = processAxiosResponse; + this.responseHandler = responseHandler; +} + +module.exports = { networkHandler }; diff --git a/src/v0/sources/webhook/transform.js b/src/v1/sources/webhook/transform.js similarity index 81% rename from src/v0/sources/webhook/transform.js rename to src/v1/sources/webhook/transform.js index 3a756ef63b..fc13424b8a 100644 --- a/src/v0/sources/webhook/transform.js +++ b/src/v1/sources/webhook/transform.js @@ -1,4 +1,4 @@ -const { removeUndefinedAndNullValues, generateUUID } = require('../../util'); +const { removeUndefinedAndNullValues, generateUUID } = require('../../../v0/util'); function processEvent(event) { const payload = { @@ -10,7 +10,8 @@ function processEvent(event) { return payload; } -function process(event) { +function process(inputEvent) { + const { event } = inputEvent; const response = processEvent(event); return removeUndefinedAndNullValues(response); } diff --git a/src/warehouse/identity.js b/src/warehouse/identity.js index 4326dddfc6..c34a66a481 100644 --- a/src/warehouse/identity.js +++ b/src/warehouse/identity.js @@ -1,5 +1,5 @@ const _ = require('lodash'); -const { InstrumentationError } = require('../v0/util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { getVersionedUtils } = require('./util'); const identityEnabledWarehouses = ['snowflake', 'bq']; diff --git a/src/warehouse/index.js b/src/warehouse/index.js index c12239c440..d88904b4a8 100644 --- a/src/warehouse/index.js +++ b/src/warehouse/index.js @@ -25,7 +25,7 @@ const whScreenColumnMappingRules = require('./config/WHScreenConfig.js'); const whGroupColumnMappingRules = require('./config/WHGroupConfig.js'); const whAliasColumnMappingRules = require('./config/WHAliasConfig.js'); const { isDataLakeProvider } = require('./config/helpers'); -const { InstrumentationError } = require('../v0/util/errorTypes'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const whExtractEventTableColumnMappingRules = require('./config/WHExtractEventTableConfig.js'); const maxColumnsInEvent = parseInt(process.env.WH_MAX_COLUMNS_IN_EVENT || '200', 10); diff --git a/src/warehouse/util.js b/src/warehouse/util.js index 91b49039f1..79981249e7 100644 --- a/src/warehouse/util.js +++ b/src/warehouse/util.js @@ -3,7 +3,7 @@ const get = require('get-value'); const v0 = require('./v0/util'); const v1 = require('./v1/util'); -const { PlatformError, InstrumentationError } = require('../v0/util/errorTypes'); +const { PlatformError, InstrumentationError } = require('@rudderstack/integrations-lib'); const minTimeInMs = Date.parse('0001-01-01T00:00:00Z'); const maxTimeInMs = Date.parse('9999-12-31T23:59:59.999Z'); diff --git a/src/warehouse/v1/util.js b/src/warehouse/v1/util.js index 8f44a17b8e..1c44a2385e 100644 --- a/src/warehouse/v1/util.js +++ b/src/warehouse/v1/util.js @@ -2,7 +2,7 @@ const _ = require('lodash'); const reservedANSIKeywordsMap = require('../config/ReservedKeywords.json'); const { isDataLakeProvider } = require('../config/helpers'); -const { TransformationError } = require('../../v0/util/errorTypes'); +const { TransformationError } = require('@rudderstack/integrations-lib'); function safeTableName(options, name = '') { const { provider } = options; diff --git a/test/__tests__/data/adobe_analytics.json b/test/__tests__/data/adobe_analytics.json index cfffccb8da..6361f92640 100644 --- a/test/__tests__/data/adobe_analytics.json +++ b/test/__tests__/data/adobe_analytics.json @@ -1010,7 +1010,6 @@ }, "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383", "properties": { - "order_id": "1234", "affiliation": "Apple Store", "value": 20, "revenue": 15.0, @@ -1019,6 +1018,7 @@ "discount": 1.5, "coupon": "ImagePro", "currency": "USD", + "purchaseId": "p101", "products": [ { "product_id": "123", @@ -1205,7 +1205,7 @@ "JSON": {}, "JSON_ARRAY": {}, "XML": { - "payload": "17941080sales campaignwebUSD127.0.0.1en-US12341234Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerroottval001RudderLabs JavaScript SDKocheckout startedhttps://www.estore.com/best-seller/12020-01-09T10:01:53.558Zmktcloudid001scCheckoutGames;Monopoly;1;14.00,Games;UNO;2;6.90footlockerrudderstackpoc" + "payload": "17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerroottval001RudderLabs JavaScript SDKocheckout startedhttps://www.estore.com/best-seller/12020-01-09T10:01:53.558Zmktcloudid001p101scCheckoutGames;Monopoly;1;14.00,Games;UNO;2;6.90footlockerrudderstackpoc" }, "FORM": {} }, diff --git a/test/__tests__/data/am_batch_input.json b/test/__tests__/data/am_batch_input.json index 64fe0b4ec7..5b0440babf 100644 --- a/test/__tests__/data/am_batch_input.json +++ b/test/__tests__/data/am_batch_input.json @@ -1,4 +1,67 @@ [ + [ + { + "message": { + "body": { + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {}, + "JSON": { + "events": [ + { + "ip": "0.0.0.0", + "time": 1603132665557, + "os_name": "", + "app_name": "RudderLabs JavaScript SDK", + "language": "en-US", + "library": "rudderstack", + "event_type": "$identify", + "os_version": "", + "session_id": -1, + "app_version": "1.1.5", + "user_properties": { + "name": "some campaign", + "plan": "Open source", + "term": "keyword", + "test": "other value", + "email": "test@rudderstack.com", + "logins": 5, + "medium": "medium", + "source": "google", + "content": "some content", + "category": "SampleIdentify", + "createdAt": 1599264000 + } + } + ], + "api_key": "4c7ed7573eb73517ee4c26ed4bde9a85", + "options": { + "min_id_length": 1 + } + } + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "headers": { + "Content-Type": "application/json" + }, + "version": "1", + "endpoint": "https://api.eu.amplitude.com/2/httpapi" + }, + "metadata": { + "job_id": 1 + }, + "destination": { + "ID": "a", + "url": "a", + "Config": { + "residencyServer": "EU" + } + } + } + ], [ { "message": { diff --git a/test/__tests__/data/am_batch_output.json b/test/__tests__/data/am_batch_output.json index dac6400585..32735b000f 100644 --- a/test/__tests__/data/am_batch_output.json +++ b/test/__tests__/data/am_batch_output.json @@ -1,4 +1,18 @@ [ + [ + { + "batched": false, + "error": "Both userId and deviceId cannot be undefined", + "metadata": { + "job_id": 1 + }, + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "statusCode": 400 + } + ], [ { "batchedRequest": { @@ -108,7 +122,9 @@ "JSON_ARRAY": {}, "FORM": { "api_key": "4c7ed7573eb73517ee4c26ed4bde9a85", - "mapping": ["{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}"] + "mapping": [ + "{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}" + ] }, "JSON": {} }, @@ -361,7 +377,9 @@ "JSON_ARRAY": {}, "FORM": { "api_key": "4c7ed7573eb73517ee4c26ed4bde9a85", - "mapping": ["{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}"] + "mapping": [ + "{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}" + ] }, "JSON": {} }, @@ -687,14 +705,29 @@ "DisplayName": "Braze", "Config": { "destConfig": { - "android": ["useNativeSDK"], - "defaultConfig": ["appKey", "dataCenter", "restApiKey"], - "ios": ["useNativeSDK"], - "web": ["useNativeSDK"] + "android": [ + "useNativeSDK" + ], + "defaultConfig": [ + "appKey", + "dataCenter", + "restApiKey" + ], + "ios": [ + "useNativeSDK" + ], + "web": [ + "useNativeSDK" + ] }, "excludeKeys": [], - "includeKeys": ["appKey", "dataCenter"], - "secretKeys": ["restApiKey"], + "includeKeys": [ + "appKey", + "dataCenter" + ], + "secretKeys": [ + "restApiKey" + ], "supportedSourceTypes": [ "android", "ios", @@ -760,7 +793,9 @@ "JSON_ARRAY": {}, "FORM": { "api_key": "4c7ed7573eb73517ee4c26ed4bde9a85", - "mapping": ["{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}"] + "mapping": [ + "{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}" + ] }, "JSON": {} }, @@ -1043,7 +1078,9 @@ "JSON_ARRAY": {}, "FORM": { "api_key": "4c7ed7573eb73517ee4c26ed4bde9a85", - "mapping": ["{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}"] + "mapping": [ + "{\"global_user_id\":\"newUserIdAlias\",\"user_id\":\"sampleusrRudder3\"}" + ] }, "JSON": {} }, @@ -1189,4 +1226,4 @@ } } ] -] +] \ No newline at end of file diff --git a/test/__tests__/data/am_input.json b/test/__tests__/data/am_input.json index 664894f7f5..2eecfb1d2c 100644 --- a/test/__tests__/data/am_input.json +++ b/test/__tests__/data/am_input.json @@ -1,4 +1,214 @@ [ + { + "message": { + "type": "track", + "sentAt": "2020-08-14T05:30:30.118Z", + "context": { + "source": "test", + "traits": { + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + "library": { + "name": "rudder-sdk-ruby-sync", + "version": "1.0.6" + } + }, + "messageId": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "timestamp": "2020-08-14T05:30:30.118Z", + "properties": { + "tax": 2, + "total": 27.5, + "coupon": "hasbros", + "revenue": 48, + "revenue_type": "Purchased", + "quantity": 2, + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "shipping": 3, + "subtotal": 22.5, + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f" + }, + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "integrations": { + "S3": false, + "All": true + } + }, + "destination": { + "Config": { + "apiKey": "abcde", + "groupTypeTrait": "email", + "groupValueTrait": "age", + "trackProductsOnce": true, + "trackRevenuePerProduct": false + } + } + }, + { + "message": { + "type": "UNSUPPORTED-TYPE", + "event": "Order Completed", + "sentAt": "2020-08-14T05:30:30.118Z", + "context": {}, + "messageId": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "timestamp": "2020-08-14T05:30:30.118Z", + "properties": {}, + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "integrations": { + "S3": false, + "All": true + } + }, + "destination": { + "Config": { + "groupTypeTrait": "email", + "apiKey": "abcde", + "groupValueTrait": "age", + "trackProductsOnce": true, + "trackRevenuePerProduct": false + } + } + }, + { + "message": { + "event": "Order Completed", + "sentAt": "2020-08-14T05:30:30.118Z", + "context": {}, + "messageId": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "timestamp": "2020-08-14T05:30:30.118Z", + "properties": {}, + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "integrations": { + "S3": false, + "All": true + } + }, + "destination": { + "Config": { + "groupTypeTrait": "email", + "groupValueTrait": "age", + "trackProductsOnce": true, + "trackRevenuePerProduct": false + } + } + }, + { + "message": { + "type": "track", + "event": "Order Completed", + "sentAt": "2020-08-14T05:30:30.118Z", + "context": { + "source": "test", + "traits": { + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + "library": { + "name": "rudder-sdk-ruby-sync", + "version": "1.0.6" + } + }, + "messageId": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "timestamp": "2020-08-14T05:30:30.118Z", + "properties": { + "tax": 2, + "total": 27.5, + "coupon": "hasbros", + "revenue": 48, + "revenue_type": "Purchased", + "quantity": 2, + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "shipping": 3, + "subtotal": 22.5, + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f" + }, + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "integrations": { + "S3": false, + "All": true + } + }, + "destination": { + "Config": { + "apiKey": "abcde", + "groupTypeTrait": "email", + "groupValueTrait": "age", + "trackProductsOnce": true, + "trackRevenuePerProduct": false + } + } + }, + { + "message": { + "type": "track", + "event": "Order Completed", + "sentAt": "2020-08-14T05:30:30.118Z", + "context": { + "source": "test", + "traits": { + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + "library": { + "name": "rudder-sdk-ruby-sync", + "version": "1.0.6" + } + }, + "messageId": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "timestamp": "2020-08-14T05:30:30.118Z", + "properties": { + "tax": 2, + "total": 27.5, + "coupon": "hasbros", + "revenue": 48, + "quantity": 2, + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "products": [ + { + "sku": "45790-32", + "url": "https://www.example.com/product/path", + "name": "Monopoly: 3rd Edition", + "price": 19, + "category": "Games", + "quantity": 1, + "image_url": "https:///www.example.com/product/path.jpg", + "product_id": "507f1f77bcf86cd799439011" + }, + { + "sku": "46493-32", + "name": "Uno Card Game", + "price": 3, + "category": "Games", + "quantity": 2, + "product_id": "505bd76785ebb509fc183733" + } + ], + "shipping": 3, + "subtotal": 22.5, + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f" + }, + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "integrations": { + "S3": false, + "All": true + } + }, + "destination": { + "Config": { + "apiKey": "abcde", + "groupTypeTrait": "email", + "groupValueTrait": "age", + "trackProductsOnce": true, + "trackRevenuePerProduct": false + } + } + }, { "message": { "channel": "web", @@ -629,6 +839,91 @@ } } }, + { + "message": { + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.1.5" + }, + "traits": { + "name": "Shehan Study", + "category": "SampleIdentify", + "email": "test@rudderstack.com", + "plan": "Open source", + "logins": 5, + "createdAt": 1599264000 + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.1.5" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", + "locale": "en-US", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 0.8999999761581421 + }, + "campaign": { + "source": "google", + "medium": "medium", + "term": "keyword", + "content": "some content", + "name": "some campaign", + "test": "other value" + }, + "page": { + "path": "/destinations/amplitude", + "referrer": "", + "search": "", + "title": "", + "url": "https://docs.rudderstack.com/destinations/amplitude", + "category": "destination", + "initial_referrer": "https://docs.rudderstack.com", + "initial_referring_domain": "docs.rudderstack.com" + } + }, + "type": "group", + "messageId": "e5034df0-a404-47b4-a463-76df99934fea", + "originalTimestamp": "2020-10-20T07:54:58.983Z", + "anonymousId": "my-anonymous-id-new", + "userId": "sampleusrRudder3", + "integrations": { + "All": true, + "Amplitude": { + "groups": { + "group_type": "Company", + "group_value": "ABC" + } + } + }, + "groupId": "Sample_groupId23", + "traits": { + "KEY_3": { + "CHILD_KEY_92": "value_95", + "CHILD_KEY_102": "value_103" + }, + "KEY_2": { + "CHILD_KEY_92": "value_95", + "CHILD_KEY_102": "value_103" + }, + "name_trait": "Company", + "value_trait": "ABC" + }, + "sentAt": "2020-10-20T07:54:58.983Z" + }, + "destination": { + "Config": { + "apiKey": "abcde" + } + } + }, { "message": { "channel": "web", @@ -698,7 +993,7 @@ "CHILD_KEY_102": "value_103" }, "name_trait": "Company", - "value_trait": "Comapny-ABC" + "value_trait": "ABC" }, "sentAt": "2020-10-20T07:54:58.983Z" }, @@ -779,7 +1074,7 @@ "CHILD_KEY_102": "value_103" }, "name_trait": "Company", - "value_trait": ["Comapny-ABC"] + "value_trait": ["ABC"] }, "sentAt": "2020-10-20T07:54:58.983Z" }, @@ -3173,7 +3468,7 @@ "CHILD_KEY_102": "value_103" }, "name_trait": "Company", - "value_trait": "Comapny-ABC" + "value_trait": "ABC" }, "sentAt": "2020-10-20T07:54:58.983Z" }, @@ -3718,7 +4013,7 @@ "CHILD_KEY_102": "value_103" }, "name_trait": "Company", - "value_trait": "Comapny-ABC" + "value_trait": "ABC" }, "sentAt": "2020-10-20T07:54:58.983Z" }, @@ -3965,6 +4260,68 @@ } } }, + { + "message": { + "anonymousId": "5d205961641ee6c5", + "channel": "mobile", + "context": { + "app": { + "build": "6", + "name": "Sample Kotlin", + "namespace": "com.example.testapp1mg", + "version": "1.2" + }, + "device": { + "id": "5d205961641ee6c5", + "manufacturer": "Google", + "model": "Android SDK built for x86", + "name": "generic_x86", + "type": "Android" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.7.0" + }, + "locale": "en-US", + "network": { + "carrier": "Android", + "bluetooth": false, + "cellular": true, + "wifi": true + }, + "os": { + "name": "Android", + "version": "7.1.1" + }, + "screen": { + "density": 440, + "height": 2148, + "width": 1080 + }, + "sessionId": "1662393792", + "timezone": "Asia/Kolkata", + "traits": { + "anonymousId": "5d205961641ee6c5", + "id": "User Android", + "userId": "User Android" + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 7.1.1; Android SDK built for x86 Build/NYC)" + }, + "integrations": { + "All": true + }, + "messageId": "1662393883248-509420bf-b812-4f8d-bdb2-8c811bfde87f", + "properties": {}, + "originalTimestamp": "2022-09-05T16:04:43.250Z", + "type": "screen", + "userId": "User Android" + }, + "destination": { + "Config": { + "apiKey": "abcde" + } + } + }, { "message": { "channel": "web", @@ -4185,7 +4542,7 @@ "CHILD_KEY_102": "value_103" }, "name_trait": "Company", - "value_trait": "Comapny-ABC" + "value_trait": "ABC" }, "sentAt": "2020-10-20T07:54:58.983Z" }, @@ -4464,7 +4821,6 @@ "search": "", "title": "", "url": "https://docs.rudderstack.com/destinations/amplitude", - "category": "destination", "initial_referrer": "https://docs.rudderstack.com", "initial_referring_domain": "docs.rudderstack.com" }, @@ -4474,15 +4830,114 @@ "event_id": 2 } }, - "name": "ApplicationLoaded", "sentAt": "2019-10-14T11:15:53.296Z" }, "destination": { "Config": { "apiKey": "abcde", - "useUserDefinedPageEventName": true, + "useUserDefinedPageEventName": false, "userProvidedPageEventString": "Viewed {{context.page.title}} event." } } + }, + { + "message": { + "type": "screen", + "userId": "identified user id", + "anonymousId": "anon-id-new", + "event": "Screen View", + "properties": { + "prop1": "5" + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "destination": { + "Config": { + "apiKey": "abcde", + "useUserDefinedScreenEventName": true, + "userProvidedScreenEventString": "My {{ event }} event." + } + } + }, + { + "message": { + "type": "screen", + "userId": "identified user id", + "anonymousId": "anon-id-new", + "event": "Screen View", + "properties": { + "prop1": "5" + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "destination": { + "Config": { + "apiKey": "abcde", + "useUserDefinedScreenEventName": false, + "userProvidedScreenEventString": "My {{ event }} event." + } + } + }, + { + "message": { + "type": "screen", + "userId": "identified user id", + "anonymousId": "anon-id-new", + "event": "Screen same as event", + "properties": { + "prop1": "5" + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "destination": { + "Config": { + "apiKey": "abcde", + "useUserDefinedScreenEventName": true, + "userProvidedScreenEventString": "{{ event }}" + } + } + }, + { + "message": { + "type": "screen", + "userId": "identified user id", + "anonymousId": "anon-id-new", + "name": "Screen", + "properties": { + "prop1": "5" + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "destination": { + "Config": { + "apiKey": "abcde", + "useUserDefinedScreenEventName": true, + "userProvidedScreenEventString": "" + } + } } ] diff --git a/test/__tests__/data/am_output.json b/test/__tests__/data/am_output.json index b82df8ae0d..6744a9dcef 100644 --- a/test/__tests__/data/am_output.json +++ b/test/__tests__/data/am_output.json @@ -1,4 +1,138 @@ [ + { + "error": "Event not present. Please send event field" + }, + { + "error": "message type not supported" + }, + { + "error": "No API Key is Found. Please Configure API key from dashbaord" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "library": "rudderstack", + "event_type": "Order Completed", + "insert_id": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "event_properties": { + "tax": 2, + "total": 27.5, + "coupon": "hasbros", + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "revenue_type": "Purchased", + "shipping": 3, + "subtotal": 22.5, + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f" + }, + "revenueType": "Purchased", + "price": 48, + "quantity": 1, + "revenue": 48, + "time": 1597383030118, + "user_properties": { + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + "session_id": -1 + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "50be5c78-6c3f-4b60-be84-97805a316fb1", + "library": "rudderstack", + "event_type": "Order Completed", + "insert_id": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "event_properties": { + "tax": 2, + "total": 27.5, + "coupon": "hasbros", + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "products": [ + { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "price": 19, + "product_id": "507f1f77bcf86cd799439011", + "quantity": 1, + "sku": "45790-32", + "url": "https://www.example.com/product/path" + }, + { + "category": "Games", + "name": "Uno Card Game", + "price": 3, + "product_id": "505bd76785ebb509fc183733", + "quantity": 2, + "sku": "46493-32" + } + ], + "shipping": 3, + "subtotal": 22.5, + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f" + }, + "revenueType": "Purchased", + "price": 48, + "quantity": 1, + "revenue": 48, + "time": 1597383030118, + "user_properties": { + "anonymousId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, + "session_id": -1 + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "50be5c78-6c3f-4b60-be84-97805a316fb1" + }, { "version": "1", "type": "REST", @@ -21,7 +155,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "84e26acc-56a5-4835-8233-591137fca468", "ip": "0.0.0.0", "user_properties": { @@ -77,7 +211,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "84e26acc-56a5-4835-8233-591137fca468", "ip": "0.0.0.0", "user_properties": { @@ -137,7 +271,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "event_type": "$identify", "user_properties": { "anonymousId": "123456", @@ -202,7 +336,7 @@ "initial_referring_domain": "docs.rudderstack.com", "initial_referrer": "https://docs.rudderstack.com" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "ip": "1.1.1.1", "time": 1571051718299, "user_id": "12345", @@ -261,7 +395,7 @@ "initial_referring_domain": "docs.rudderstack.com", "initial_referrer": "https://docs.rudderstack.com" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "ip": "1.1.1.1", "groups": { "Company": "ABC" @@ -312,7 +446,7 @@ "app_version": "1.0.0", "language": "en-US", "event_type": "test track event", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "event_properties": { "user_actual_role": "system_admin", "user_actual_id": 12345, @@ -366,7 +500,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "event_type": "$identify", "user_properties": { "anonymousId": "123456", @@ -419,7 +553,7 @@ "timestamp": "2020-08-28 09:00:00" }, "event_type": "$identify", - "session_id": "1598597129", + "session_id": 1598597129, "time": 0, "user_id": "ubcdfghi0001" } @@ -450,7 +584,7 @@ "events": [ { "device_id": "123456", - "session_id": "1598597129", + "session_id": 1598597129, "event_type": "$identify", "library": "rudderstack", "user_properties": { @@ -555,6 +689,81 @@ "files": {}, "userId": "123456" }, + [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "os_name": "Chrome", + "os_version": "85.0.4183.121", + "platform": "Web", + "library": "rudderstack", + "device_model": "Mac", + "device_id": "my-anonymous-id-new", + "app_name": "RudderLabs JavaScript SDK", + "app_version": "1.1.5", + "language": "en-US", + "event_type": "$identify", + "groups": { + "Company": "ABC" + }, + "user_properties": { + "Company": "ABC", + "utm_content": "some content", + "utm_medium": "medium", + "utm_name": "some campaign", + "utm_source": "google", + "utm_term": "keyword", + "utm_test": "other value", + "initial_referring_domain": "docs.rudderstack.com", + "initial_referrer": "https://docs.rudderstack.com" + }, + "time": 1603180498983, + "user_id": "sampleusrRudder3", + "session_id": -1 + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "my-anonymous-id-new" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/groupidentify", + "headers": {}, + "params": {}, + "body": { + "JSON": {}, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": { + "api_key": "abcde", + "identification": ["{\"group_type\":\"Company\",\"group_value\":\"ABC\"}"] + } + }, + "files": {}, + "userId": "my-anonymous-id-new" + } + ], [ { "version": "1", @@ -581,7 +790,7 @@ "language": "en-US", "event_type": "$identify", "user_properties": { - "Company": "Comapny-ABC", + "Company": "ABC", "utm_content": "some content", "utm_medium": "medium", "utm_name": "some campaign", @@ -592,7 +801,7 @@ "initial_referrer": "https://docs.rudderstack.com" }, "groups": { - "Company": "Comapny-ABC" + "Company": "ABC" }, "time": 1603180498983, "user_id": "sampleusrRudder3", @@ -624,7 +833,7 @@ "FORM": { "api_key": "abcde", "identification": [ - "{\"group_type\":\"Company\",\"group_value\":\"Comapny-ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"Comapny-ABC\"}}" + "{\"group_type\":\"Company\",\"group_value\":\"ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"ABC\"}}" ] } }, @@ -2244,7 +2453,7 @@ "event_type": "Order Completed", "user_id": "userID123", "revenueType": "Purchased", - "price": 25, + "price": 25.0, "quantity": 2, "revenue": 48, "time": 1597383030118, @@ -2886,7 +3095,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "event_type": "$identify", "device_brand": "testBrand", "device_manufacturer": "testManufacturer", @@ -3031,7 +3240,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "84e26acc-56a5-4835-8233-591137fca468", "ip": "0.0.0.0", "user_properties": { @@ -3091,7 +3300,7 @@ "language": "en-US", "event_type": "$identify", "user_properties": { - "Company": "Comapny-ABC", + "Company": "ABC", "utm_content": "some content", "utm_medium": "medium", "utm_name": "some campaign", @@ -3102,7 +3311,7 @@ "initial_referrer": "https://docs.rudderstack.com" }, "groups": { - "Company": "Comapny-ABC" + "Company": "ABC" }, "time": 1603180498983, "user_id": "sampleusrRudder3", @@ -3134,7 +3343,7 @@ "FORM": { "api_key": "abcde", "identification": [ - "{\"group_type\":\"Company\",\"group_value\":\"Comapny-ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"Comapny-ABC\"}}" + "{\"group_type\":\"Company\",\"group_value\":\"ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"ABC\"}}" ] } }, @@ -3483,11 +3692,11 @@ "utm_content": "some content", "utm_name": "some campaign", "utm_test": "other value", - "Company": "Comapny-ABC" + "Company": "ABC" }, "event_type": "$identify", "groups": { - "Company": "Comapny-ABC" + "Company": "ABC" }, "time": 1603180498983, "user_id": "sampleusrRudder3", @@ -3520,7 +3729,7 @@ "FORM": { "api_key": "abcde", "identification": [ - "{\"group_type\":\"Company\",\"group_value\":\"Comapny-ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"Comapny-ABC\"}}" + "{\"group_type\":\"Company\",\"group_value\":\"ABC\",\"group_properties\":{\"KEY_3\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"KEY_2\":{\"CHILD_KEY_92\":\"value_95\",\"CHILD_KEY_102\":\"value_103\"},\"name_trait\":\"Company\",\"value_trait\":\"ABC\"}}" ] } }, @@ -3603,7 +3812,7 @@ "initial_referring_domain": "docs.rudderstack.com", "name": "ApplicationLoaded" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "event_id": 2, @@ -3702,6 +3911,56 @@ "files": {}, "userId": "5d205961641ee6c5" }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "os_name": "Android", + "os_version": "7.1.1", + "device_model": "Android SDK built for x86", + "device_manufacturer": "Google", + "device_id": "5d205961641ee6c5", + "carrier": "Android", + "app_name": "Sample Kotlin", + "app_version": "1.2", + "platform": "Android", + "language": "en-US", + "event_properties": {}, + "insert_id": "1662393883248-509420bf-b812-4f8d-bdb2-8c811bfde87f", + "user_properties": { + "anonymousId": "5d205961641ee6c5", + "id": "User Android", + "userId": "User Android" + }, + "event_type": "Viewed Screen", + "user_id": "User Android", + "device_brand": "Google", + "time": 1662393883250, + "session_id": 1662393792, + "library": "rudderstack" + } + ], + "options": { + "min_id_length": 1 + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "5d205961641ee6c5" + }, { "version": "1", "type": "REST", @@ -3741,7 +4000,7 @@ "event_type": "$identify", "time": 1571043797562, "user_id": "123456", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": 1662393792, "country": "India", "city": "kolkata", "library": "rudderstack" @@ -3847,7 +4106,7 @@ "initial_referring_domain": "docs.rudderstack.com", "name": "ApplicationLoaded" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "event_id": 2, @@ -3907,7 +4166,7 @@ "initial_referring_domain": "docs.rudderstack.com", "name": "ApplicationLoaded" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "event_id": 2, @@ -3967,7 +4226,7 @@ "initial_referring_domain": "docs.rudderstack.com", "name": "ApplicationLoaded" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "event_id": 2, @@ -4015,19 +4274,17 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "event_type": "Viewed Home Page event.", + "event_type": "Viewed Page", "event_properties": { "path": "/destinations/amplitude", "referrer": "", "search": "", "title": "", "url": "https://docs.rudderstack.com/destinations/amplitude", - "category": "destination", "initial_referrer": "https://docs.rudderstack.com", - "initial_referring_domain": "docs.rudderstack.com", - "name": "ApplicationLoaded" + "initial_referring_domain": "docs.rudderstack.com" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "event_id": 2, @@ -4052,5 +4309,161 @@ }, "files": {}, "userId": "00000000000000000000000000" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "anon-id-new", + "library": "rudderstack", + "event_properties": { + "prop1": "5", + "name": "Screen View" + }, + "event_type": "My Screen View event.", + "time": 1580602989544, + "user_id": "identified user id", + "user_properties": {}, + "session_id": -1, + "ip": "14.5.67.21" + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "anon-id-new", + "library": "rudderstack", + "event_properties": { + "prop1": "5", + "name": "Screen View" + }, + "event_type": "Viewed Screen View Screen", + "time": 1580602989544, + "user_id": "identified user id", + "user_properties": {}, + "session_id": -1, + "ip": "14.5.67.21" + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "anon-id-new", + "library": "rudderstack", + "event_properties": { + "prop1": "5", + "name": "Screen same as event" + }, + "event_type": "Screen same as event", + "time": 1580602989544, + "user_id": "identified user id", + "user_properties": {}, + "session_id": -1, + "ip": "14.5.67.21" + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api2.amplitude.com/2/httpapi", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "api_key": "abcde", + "events": [ + { + "device_id": "anon-id-new", + "library": "rudderstack", + "event_properties": { + "prop1": "5", + "name": "Screen" + }, + "event_type": "Screen", + "time": 1580602989544, + "user_id": "identified user id", + "user_properties": {}, + "session_id": -1, + "ip": "14.5.67.21" + } + ], + "options": { + "min_id_length": 1 + } + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" } ] diff --git a/test/__tests__/data/am_router_output.json b/test/__tests__/data/am_router_output.json index 5c9e23840a..bfccb478b3 100644 --- a/test/__tests__/data/am_router_output.json +++ b/test/__tests__/data/am_router_output.json @@ -24,7 +24,7 @@ "app_name": "RudderLabs JavaScript SDK", "app_version": "1.0.0", "language": "en-US", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "84e26acc-56a5-4835-8233-591137fca468", "city": "kolkata", "country": "India", @@ -109,7 +109,7 @@ "initial_referring_domain": "docs.rudderstack.com", "name": "ApplicationLoaded" }, - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", + "session_id": -1, "insert_id": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "ip": "1.1.1.1", "user_properties": { diff --git a/test/__tests__/data/braze_input.json b/test/__tests__/data/braze_input.json index e799cf2e82..fb4e41b189 100644 --- a/test/__tests__/data/braze_input.json +++ b/test/__tests__/data/braze_input.json @@ -1814,5 +1814,146 @@ "type": "track", "userId": "mickeyMouse" } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "sendPurchaseEventWithExtraProperties": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.0.5" + }, + "ip": "0.0.0.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.0.5" + }, + "locale": "en-GB", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 2 + }, + "traits": { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "firstname": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "event": "Order Completed", + "integrations": { + "All": true + }, + "messageId": "aa5f5e44-8756-40ad-ad1e-b0d3b9fa710a", + "originalTimestamp": "2020-01-24T06:29:02.367Z", + "properties": { + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f", + "coupon": "hasbros", + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "products": [ + { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "quantity": 1, + "sku": "45790-32", + "url": "https://www.example.com/product/path" + }, + { + "category": "Games", + "name": "Uno Card Game", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "quantity": 2, + "sku": "46493-32" + } + ], + "revenue": 25, + "shipping": 3, + "subtotal": 22.5, + "tax": 2, + "total": 27.5 + }, + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53712", + "sentAt": "2020-01-24T06:29:02.368Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "track", + "userId": "" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "traits": { + "city": "Disney", + "country": "USA", + "email": 123, + "firstname": "Mickey", + "closed_at": null, + "orderTotal": 0 + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "integrations": { + "All": true + }, + "messageId": "2536eda4-d638-4c93-8014-8ffe3f083214", + "originalTimestamp": "2020-01-24T06:29:02.362Z", + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53709", + "sentAt": "2020-01-24T06:29:02.363Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "identify", + "userId": "" + } } ] diff --git a/test/__tests__/data/braze_output.json b/test/__tests__/data/braze_output.json index 10c42b1064..ed39930569 100644 --- a/test/__tests__/data/braze_output.json +++ b/test/__tests__/data/braze_output.json @@ -963,5 +963,80 @@ }, "files": {}, "userId": "mickeyMouse" + }, + { + "body": { + "FORM": {}, + "JSON": { + "attributes": [ + { + "_update_existing_only": false, + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "firstname": "Mickey", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ], + "partner": "RudderStack", + "purchases": [ + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "properties": { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "url": "https://www.example.com/product/path" + }, + "quantity": 1, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + }, + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "properties": { + "category": "Games", + "name": "Uno Card Game" + }, + "quantity": 2, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ] + }, + "JSON_ARRAY": {}, + "XML": {} + }, + "endpoint": "https://rest.fra-01.braze.eu/users/track", + "files": {}, + "headers": { + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey", + "Content-Type": "application/json" + }, + "method": "POST", + "params": {}, + "type": "REST", + "userId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "version": "1" + }, + { + "statusCode": 400, + "message": "Invalid email, email must be a valid string" } ] diff --git a/test/__tests__/data/braze_router.json b/test/__tests__/data/braze_router.json index 8bfd7c7d42..33c66bca6d 100644 --- a/test/__tests__/data/braze_router.json +++ b/test/__tests__/data/braze_router.json @@ -841,9 +841,7 @@ }, { "error": "[Braze Deduplication]: Duplicate user detected, the user is dropped", - "statTags": { - "errorCategory": "transformation" - }, + "statTags": {}, "statusCode": 298, "batched": false, "metadata": [ diff --git a/test/__tests__/data/campaign_manager_proxy_input.json b/test/__tests__/data/campaign_manager_proxy_input.json deleted file mode 100644 index e7bf369d0c..0000000000 --- a/test/__tests__/data/campaign_manager_proxy_input.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchupdate", - "headers": { - "Authorization": "Bearer dummyApiKey", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "kind": "dfareporting#conversionsBatchInsertRequest", - "encryptionInfo": { - "kind": "dfareporting#encryptionInfo", - "encryptionSource": "AD_SERVING", - "encryptionEntityId": "3564523", - "encryptionEntityType": "DCM_ACCOUNT" - }, - "conversions": [ - { - "timestampMicros": "1668624722000000", - "floodlightConfigurationId": "213123123", - "ordinal": "string", - "floodlightActivityId": "456543345245", - "mobileDeviceId": "string", - "value": 7, - "encryptedUserIdCandidates": ["dfghjbnm"], - "gclid": "string", - "matchId": "string", - "dclid": "string", - "impressionId": "string", - "limitAdTracking": true, - "childDirectedTreatment": true - } - ] - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchupdate", - "headers": { - "Authorization": "Bearer dummyApiKey", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "kind": "dfareporting#conversionsBatchUpdateRequest", - "encryptionInfo": { - "kind": "dfareporting#encryptionInfo", - "encryptionSource": "AD_SERVING", - "encryptionEntityId": "3564523", - "encryptionEntityType": "DCM_ACCOUNT" - }, - "conversions": [ - { - "timestampMicros": "1668624722000000", - "floodlightConfigurationId": "213123123", - "ordinal": "string", - "floodlightActivityId": "456543345245", - "mobileDeviceId": "string", - "value": 7, - "encryptedUserIdCandidates": ["dfghjbnm"], - "gclid": "string", - "matchId": "string", - "dclid": "string", - "impressionId": "string", - "limitAdTracking": true, - "childDirectedTreatment": true - } - ] - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - } - } -] diff --git a/test/__tests__/data/campaign_manager_proxy_output.json b/test/__tests__/data/campaign_manager_proxy_output.json deleted file mode 100644 index c5dcc4559f..0000000000 --- a/test/__tests__/data/campaign_manager_proxy_output.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "output": { - "destinationResponse": { - "error": { - "code": 403, - "message": "The caller does not have permission", - "errors": [ - { - "message": "Invalid Credentials", - "domain": "global", - "reason": "authError", - "location": "Authorization", - "locationType": "header" - } - ], - "status": "PERMISSION_DENIED" - } - }, - "message": "Campaign Manager: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. during CAMPAIGN_MANAGER response transformation", - "statTags": { - "destType": "CAMPAIGN_MANAGER", - "errorAt": "proxy", - "scope": "exception", - "stage": "responseTransform" - }, - "status": 403 - } - }, - { - "output": { - "status": 200, - "message": "[CAMPAIGN_MANAGER Response Handler] - Request Processed Successfully", - "destinationResponse": { - "response": [ - { - "adjustmentType": "ENHANCEMENT", - "conversionAction": "customers/7693729833/conversionActions/874224905", - "adjustmentDateTime": "2021-01-01 12:32:45-08:00", - "gclidDateTimePair": { - "gclid": "1234", - "conversionDateTime": "2021-01-01 12:32:45-08:00" - }, - "orderId": "12345" - } - ], - "status": 200 - } - } - } -] diff --git a/test/__tests__/data/facebook_conversions.json b/test/__tests__/data/facebook_conversions.json index 62d0a49c0f..cc4d9a1421 100644 --- a/test/__tests__/data/facebook_conversions.json +++ b/test/__tests__/data/facebook_conversions.json @@ -120,7 +120,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -201,7 +201,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -241,7 +241,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -250,7 +250,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"spin_result\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"value\":400,\"currency\":\"USD\"}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"spin_result\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"value\":400,\"currency\":\"USD\"}}" ] } }, @@ -298,7 +298,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -338,7 +338,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -347,7 +347,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Search\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Search\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -395,7 +395,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -435,7 +435,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -444,7 +444,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddToCart\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddToCart\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -492,7 +492,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -532,7 +532,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -541,7 +541,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -596,7 +596,7 @@ } ] }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -636,7 +636,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -645,7 +645,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"products[0].product_id\":1234,\"products[0].quantity\":5,\"products[0].price\":55,\"content_ids\":[1234],\"contents\":[{\"id\":1234,\"quantity\":5,\"item_price\":55}],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"products\":[{\"product_id\":1234,\"quantity\":5,\"price\":55}],\"content_ids\":[1234],\"contents\":[{\"id\":1234,\"quantity\":5,\"item_price\":55}],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -694,7 +694,7 @@ "additional_bet_index": 0, "category": "randomCategory" }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -734,7 +734,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -743,7 +743,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"category\":\"randomCategory\",\"content_ids\":[\"randomCategory\"],\"contents\":[{\"id\":\"randomCategory\",\"quantity\":1}],\"content_type\":\"product_group\",\"content_category\":\"randomCategory\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"ViewContent\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"category\":\"randomCategory\",\"content_ids\":[\"randomCategory\"],\"contents\":[{\"id\":\"randomCategory\",\"quantity\":1}],\"content_type\":\"product_group\",\"content_category\":\"randomCategory\",\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -791,7 +791,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -831,7 +831,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -840,7 +840,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddToWishlist\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddToWishlist\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"currency\":\"USD\",\"value\":400}}" ] } }, @@ -888,7 +888,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -928,7 +928,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -937,7 +937,217 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddPaymentInfo\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"AddPaymentInfo\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"currency\":\"USD\",\"value\":400}}" + ] + } + }, + "files": {} + } + }, + { + "description": "Track event with standard event order completed with delivery_category in products array", + "input": { + "message": { + "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", + "channel": "web", + "context": { + "device": { + "id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", + "manufacturer": "Xiaomi", + "model": "Redmi 6", + "name": "xiaomi" + }, + "network": { + "carrier": "Banglalink" + }, + "os": { + "name": "android", + "version": "8.1.0" + }, + "screen": { + "height": "100", + "density": 50 + }, + "traits": { + "email": " aBc@gmail.com ", + "address": { + "zip": 1234 + }, + "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" + } + }, + "event": "order completed", + "integrations": { + "All": true + }, + "message_id": "a80f82be-9bdc-4a9f-b2a5-15621ee41df8", + "properties": { + "revenue": 400, + "additional_bet_index": 0, + "products": [ + { + "product_id": 1234, + "quantity": 5, + "price": 55, + "delivery_category": "home_delivery" + } + ] + }, + "timestamp": "2023-11-12T15:46:51.693229+05:30", + "type": "track" + }, + "destination": { + "Config": { + "limitedDataUsage": true, + "blacklistPiiProperties": [ + { + "blacklistPiiProperties": "", + "blacklistPiiHash": false + } + ], + "accessToken": "09876", + "datasetId": "dummyID", + "eventsToEvents": [ + { + "from": "", + "to": "" + } + ], + "eventCustomProperties": [ + { + "eventCustomProperties": "" + } + ], + "removeExternalId": true, + "whitelistPiiProperties": [ + { + "whitelistPiiProperties": "" + } + ], + "actionSource": "website" + }, + "Enabled": true + } + }, + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", + "headers": {}, + "params": {}, + "body": { + "JSON": {}, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": { + "data": [ + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Purchase\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"products\":[{\"product_id\":1234,\"quantity\":5,\"price\":55,\"delivery_category\":\"home_delivery\"}],\"content_ids\":[1234],\"contents\":[{\"id\":1234,\"quantity\":5,\"item_price\":55,\"delivery_category\":\"home_delivery\"}],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400,\"num_items\":1}}" + ] + } + }, + "files": {} + } + }, + { + "description": "Track event with standard event order completed with delivery_category in properties", + "input": { + "message": { + "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", + "channel": "web", + "context": { + "device": { + "id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", + "manufacturer": "Xiaomi", + "model": "Redmi 6", + "name": "xiaomi" + }, + "network": { + "carrier": "Banglalink" + }, + "os": { + "name": "android", + "version": "8.1.0" + }, + "screen": { + "height": "100", + "density": 50 + }, + "traits": { + "email": " aBc@gmail.com ", + "address": { + "zip": 1234 + }, + "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" + } + }, + "event": "order completed", + "integrations": { + "All": true + }, + "message_id": "a80f82be-9bdc-4a9f-b2a5-15621ee41df8", + "properties": { + "revenue": 400, + "additional_bet_index": 0, + "delivery_category": "home_delivery", + "products": [ + { + "product_id": 1234, + "quantity": 5, + "price": 55 + } + ] + }, + "timestamp": "2023-11-12T15:46:51.693229+05:30", + "type": "track" + }, + "destination": { + "Config": { + "limitedDataUsage": true, + "blacklistPiiProperties": [ + { + "blacklistPiiProperties": "", + "blacklistPiiHash": false + } + ], + "accessToken": "09876", + "datasetId": "dummyID", + "eventsToEvents": [ + { + "from": "", + "to": "" + } + ], + "eventCustomProperties": [ + { + "eventCustomProperties": "" + } + ], + "removeExternalId": true, + "whitelistPiiProperties": [ + { + "whitelistPiiProperties": "" + } + ], + "actionSource": "website" + }, + "Enabled": true + } + }, + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", + "headers": {}, + "params": {}, + "body": { + "JSON": {}, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": { + "data": [ + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Purchase\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"delivery_category\":\"home_delivery\",\"products\":[{\"product_id\":1234,\"quantity\":5,\"price\":55}],\"content_ids\":[1234],\"contents\":[{\"id\":1234,\"quantity\":5,\"item_price\":55,\"delivery_category\":\"home_delivery\"}],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400,\"num_items\":1}}" ] } }, diff --git a/test/__tests__/data/facebook_conversions_router_input.json b/test/__tests__/data/facebook_conversions_router_input.json index 4abe66d3c4..b8865d124e 100644 --- a/test/__tests__/data/facebook_conversions_router_input.json +++ b/test/__tests__/data/facebook_conversions_router_input.json @@ -41,7 +41,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { @@ -119,7 +119,7 @@ "revenue": 400, "additional_bet_index": 0 }, - "timestamp": "2023-10-15T15:46:51.693229+05:30", + "timestamp": "2023-11-12T15:46:51.693229+05:30", "type": "track" }, "destination": { diff --git a/test/__tests__/data/facebook_conversions_router_output.json b/test/__tests__/data/facebook_conversions_router_output.json index d376a91027..542c173090 100644 --- a/test/__tests__/data/facebook_conversions_router_output.json +++ b/test/__tests__/data/facebook_conversions_router_output.json @@ -4,7 +4,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -13,7 +13,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"spin_result\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"value\":400,\"currency\":\"USD\"}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"spin_result\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"value\":400,\"currency\":\"USD\"}}" ] } }, @@ -64,7 +64,7 @@ "version": "1", "type": "REST", "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/dummyID/events?access_token=09876", + "endpoint": "https://graph.facebook.com/v18.0/dummyID/events?access_token=09876", "headers": {}, "params": {}, "body": { @@ -73,7 +73,7 @@ "JSON_ARRAY": {}, "FORM": { "data": [ - "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Search\",\"event_time\":1697365011,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" + "{\"user_data\":{\"em\":\"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08\",\"zp\":\"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4\"},\"event_name\":\"Search\",\"event_time\":1699784211,\"action_source\":\"website\",\"custom_data\":{\"revenue\":400,\"additional_bet_index\":0,\"content_ids\":[],\"contents\":[],\"content_type\":\"product\",\"currency\":\"USD\",\"value\":400}}" ] } }, diff --git a/test/__tests__/data/facebook_pixel_proxy_output.json b/test/__tests__/data/facebook_pixel_proxy_output.json index 607ac7804e..e0afb028d3 100644 --- a/test/__tests__/data/facebook_pixel_proxy_output.json +++ b/test/__tests__/data/facebook_pixel_proxy_output.json @@ -91,7 +91,7 @@ { "output": { "status": 400, - "message": "Object with ID 'PIXEL_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", + "message": "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", "destinationResponse": { "error": { "message": "Unsupported post request. Object with ID '1234567891234569' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api", diff --git a/test/__tests__/data/fb_proxy_output.json b/test/__tests__/data/fb_proxy_output.json index e9dbf0d128..12e06cff2c 100644 --- a/test/__tests__/data/fb_proxy_output.json +++ b/test/__tests__/data/fb_proxy_output.json @@ -91,7 +91,7 @@ { "output": { "status": 400, - "message": "Object with ID 'PIXEL_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", + "message": "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", "destinationResponse": { "error": { "message": "Unsupported post request. Object with ID '1234567891234569' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api", diff --git a/test/__tests__/data/freshmarketer.json b/test/__tests__/data/freshmarketer.json index 3d30841b30..390c0fb44e 100644 --- a/test/__tests__/data/freshmarketer.json +++ b/test/__tests__/data/freshmarketer.json @@ -5,7 +5,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -94,7 +94,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -183,7 +183,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -248,7 +248,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -312,7 +312,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -422,7 +422,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -491,7 +491,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -558,7 +558,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -627,7 +627,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -760,7 +760,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -843,7 +843,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -927,7 +927,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1019,7 +1019,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1127,7 +1127,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1228,7 +1228,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1315,7 +1315,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1406,7 +1406,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1496,7 +1496,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1586,7 +1586,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1696,7 +1696,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1757,7 +1757,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1788,7 +1788,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1825,7 +1825,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1892,7 +1892,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1937,7 +1937,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1976,7 +1976,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2043,7 +2043,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2145,7 +2145,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2232,7 +2232,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2334,7 +2334,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2427,7 +2427,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder", + "domain": "domain-rudder.myfreshworks.com", "rudderEventsToFreshmarketerEvents": [ { "from": "test_activity", diff --git a/test/__tests__/data/freshmarketer_router_input.json b/test/__tests__/data/freshmarketer_router_input.json index 0e05c7f5f8..2cc5ce58de 100644 --- a/test/__tests__/data/freshmarketer_router_input.json +++ b/test/__tests__/data/freshmarketer_router_input.json @@ -3,7 +3,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "metadata": { @@ -59,7 +59,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "metadata": { @@ -115,7 +115,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "metadata": { diff --git a/test/__tests__/data/freshmarketer_router_output.json b/test/__tests__/data/freshmarketer_router_output.json index 01740cb626..3525e4bb16 100644 --- a/test/__tests__/data/freshmarketer_router_output.json +++ b/test/__tests__/data/freshmarketer_router_output.json @@ -43,7 +43,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } } }, @@ -91,7 +91,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } } }, @@ -156,7 +156,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } } diff --git a/test/__tests__/data/freshsales.json b/test/__tests__/data/freshsales.json index 2527e37b90..55193532f4 100644 --- a/test/__tests__/data/freshsales.json +++ b/test/__tests__/data/freshsales.json @@ -69,7 +69,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -90,7 +90,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -179,7 +179,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -268,7 +268,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -356,7 +356,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "rudderstack-476952domain3105" + "domain": "rudderstack-476952domain3105.myfreshworks.com" } }, "message": { @@ -421,7 +421,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -531,7 +531,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -600,7 +600,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -667,7 +667,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -736,7 +736,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } }, "message": { @@ -869,7 +869,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -952,7 +952,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1036,7 +1036,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1128,7 +1128,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder", + "domain": "domain-rudder.myfreshworks.com", "rudderEventsToFreshsalesEvents": [ { "from": "test", @@ -1244,7 +1244,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1345,7 +1345,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1432,7 +1432,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1523,7 +1523,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1613,7 +1613,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1703,7 +1703,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1813,7 +1813,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1874,7 +1874,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -1966,7 +1966,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2053,7 +2053,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, @@ -2155,7 +2155,7 @@ "destination": { "Config": { "apiKey": "dummyApiKey", - "domain": "domain-rudder" + "domain": "domain-rudder.myfreshworks.com" } } }, diff --git a/test/__tests__/data/freshsales_router_input.json b/test/__tests__/data/freshsales_router_input.json index 856a127f51..ea4b9887dd 100644 --- a/test/__tests__/data/freshsales_router_input.json +++ b/test/__tests__/data/freshsales_router_input.json @@ -66,7 +66,7 @@ }, "Config": { "apiKey": "hrkjfergeferf", - "domain": "rudderstack-479541159204968909" + "domain": "rudderstack-479541159204968909.myfreshworks.com" }, "Enabled": true, "Transformations": [], diff --git a/test/__tests__/data/freshsales_router_output.json b/test/__tests__/data/freshsales_router_output.json index 449d6eb45a..69d259ff00 100644 --- a/test/__tests__/data/freshsales_router_output.json +++ b/test/__tests__/data/freshsales_router_output.json @@ -72,7 +72,7 @@ }, "Config": { "apiKey": "hrkjfergeferf", - "domain": "rudderstack-479541159204968909" + "domain": "rudderstack-479541159204968909.myfreshworks.com" }, "Enabled": true, "Transformations": [], diff --git a/test/__tests__/data/klaviyo.json b/test/__tests__/data/klaviyo.json index 796d9ed8e0..623aa78cc4 100644 --- a/test/__tests__/data/klaviyo.json +++ b/test/__tests__/data/klaviyo.json @@ -636,6 +636,150 @@ } ] }, + { + "description": "Identify call without user custom Properties", + "input": { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", + "enforceEmailAsPrimary": false + } + }, + "message": { + "type": "identify", + "sentAt": "2021-01-03T17:02:53.195Z", + "userId": "user@1", + "channel": "web", + "context": { + "os": { + "name": "", + "version": "" + }, + "app": { + "name": "RudderLabs JavaScript SDK", + "build": "1.0.0", + "version": "1.1.11", + "namespace": "com.rudderlabs.javascript" + }, + "traits": { + "firstName": "Test", + "lastName": "Rudderlabs", + "email": "test@rudderstack.com", + "phone": "+12 345 578 900", + "userId": "user@1", + "title": "Developer", + "organization": "Rudder", + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001", + "properties": { + "listId": "XUepkK", + "subscribe": true, + "consent": ["email", "sms"] + } + }, + "locale": "en-US", + "screen": { + "density": 2 + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.1.11" + }, + "campaign": {}, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" + }, + "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", + "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", + "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", + "integrations": { + "All": true + }, + "originalTimestamp": "2021-01-03T17:02:53.193Z" + } + }, + "output": [ + { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile", + "attributes": { + "email": "test@rudderstack.com", + "first_name": "Test", + "last_name": "Rudderlabs", + "phone_number": "+12 345 578 900", + "external_id": "user@1", + "title": "Developer", + "organization": "Rudder", + "location": { + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001" + } + }, + "id": "01GW3PHVY0MTCDGS0A1612HARX" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile-subscription-bulk-create-job", + "attributes": { + "list_id": "XUepkK", + "subscriptions": [ + { + "email": "test@rudderstack.com", + "phone_number": "+12 345 578 900", + "channels": { + "email": ["MARKETING"], + "sms": ["MARKETING"] + } + } + ] + } + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ] + }, { "description": "Identify call without email and phone & enforceEmailAsPrimary enabled from UI", "input": { diff --git a/test/__tests__/data/mailjet_source.json b/test/__tests__/data/mailjet_source.json index ba7f32fb89..d9869585cb 100644 --- a/test/__tests__/data/mailjet_source.json +++ b/test/__tests__/data/mailjet_source.json @@ -200,5 +200,50 @@ "userId": "5b6a3426dba2cb24e4f0aeec43bee9d7" } } + }, + { + "description": "MailJet when no email is present", + "input": { + "event": "bounce", + "time": 1664444170, + "MessageID": 56013522696710744, + "Message_GUID": "dbe4f0a3-4a5a-4784-a724-a9794d3c0444", + "mj_campaign_id": 108892, + "mj_contact_id": 373142182, + "customcampaign": "mj.nl=58486", + "blocked": false, + "hard_bounce": false, + "error_related_to": "system", + "error": "connection issue" + }, + "output": { + "Message": { + "context": { + "library": { + "name": "unknown", + "version": "unknown" + }, + "integration": { + "name": "MailJet" + }, + "externalId": [ + { + "type": "mailjetContactId", + "id": 373142182 + } + ] + }, + "integrations": { + "MailJet": false + }, + "type": "track", + "event": "bounce", + "properties": { + "customcampaign": "mj.nl=58486", + "mj_campaign_id": 108892 + }, + "originalTimestamp": "2022-09-29T09:36:10.000Z" + } + } } ] diff --git a/test/__tests__/data/marketo_input.json b/test/__tests__/data/marketo_input.json index c54005b9f6..122525560e 100644 --- a/test/__tests__/data/marketo_input.json +++ b/test/__tests__/data/marketo_input.json @@ -77,7 +77,8 @@ "Config": { "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success" + "accountId": "marketo_acct_id_success", + "rudderEventsMapping": [] }, "Enabled": true, "Transformations": [], @@ -151,31 +152,31 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], + "leadTraitMapping": [ + { + "from": "leadScore", + "to": "customLeadScore" + } + ], + "createIfNotExist": true, "customActivityPrimaryKeyMap": [ { "from": "Product Clicked", "to": "name" } ], - "leadTraitMapping": [ + "customActivityEventMap": [ { - "from": "leadScore", - "to": "customLeadScore" + "from": "Product Clicked", + "to": "100001" } - ], - "createIfNotExist": true + ] } } }, @@ -243,12 +244,6 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", @@ -259,19 +254,20 @@ "to": "productId" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -339,31 +335,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": false, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -397,31 +388,26 @@ "clientId": "marketo_acct_id_token_failure", "clientSecret": "marketo_acct_id_token_failure", "trackAnonymousEvents": false, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -489,31 +475,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": false, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -558,12 +539,6 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", @@ -574,19 +549,20 @@ "to": "productId" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -653,31 +629,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": false, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -744,31 +715,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -835,31 +801,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -925,31 +886,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -1016,31 +972,26 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } ], - "createIfNotExist": true + "createIfNotExist": true, + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ] } } }, @@ -1088,12 +1039,6 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", @@ -1104,17 +1049,18 @@ "to": "productId" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "score", "to": "customLeadScore" } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } ] } } @@ -1196,7 +1142,8 @@ "Config": { "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success" + "accountId": "marketo_acct_id_success", + "rudderEventsMapping": [] }, "Enabled": true, "Transformations": [], diff --git a/test/__tests__/data/marketo_router_input.json b/test/__tests__/data/marketo_router_input.json index acf59508dd..a7a40a221a 100644 --- a/test/__tests__/data/marketo_router_input.json +++ b/test/__tests__/data/marketo_router_input.json @@ -64,29 +64,24 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } ] }, "secretConfig": {}, @@ -105,9 +100,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -251,29 +245,24 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } ] }, "secretConfig": {}, @@ -292,9 +281,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -450,38 +438,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -493,9 +481,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -662,38 +649,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -705,9 +692,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -874,38 +860,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -917,9 +903,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, diff --git a/test/__tests__/data/marketo_router_metadata_input.json b/test/__tests__/data/marketo_router_metadata_input.json index 1c02a9c6fd..b1e3a26f69 100644 --- a/test/__tests__/data/marketo_router_metadata_input.json +++ b/test/__tests__/data/marketo_router_metadata_input.json @@ -46,10 +46,25 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [{ "from": "Product Clicked", "to": "100001" }], - "customActivityPropertyMap": [{ "from": "name", "to": "productName" }], - "customActivityPrimaryKeyMap": [{ "from": "Product Clicked", "to": "name" }], - "leadTraitMapping": [{ "from": "leadScore", "to": "customLeadScore" }] + "customActivityPropertyMap": [ + { + "from": "name", + "to": "productName" + } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } + ], + "leadTraitMapping": [ + { + "from": "leadScore", + "to": "customLeadScore" + } + ] }, "secretConfig": {}, "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", @@ -67,9 +82,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", + "rudderEventsMapping", "leadTraitMapping" ] }, @@ -83,20 +97,56 @@ "responseType": "JSON", "rules": { "retryable": [ - { "success": "false", "errors.0.code": 600 }, - { "success": "false", "errors.0.code": 601 }, - { "success": "false", "errors.0.code": 602 }, - { "success": "false", "errors.0.code": 604 }, - { "success": "false", "errors.0.code": 606 }, - { "success": "false", "errors.0.code": 607 }, - { "success": "false", "errors.0.code": 608 }, - { "success": "false", "errors.0.code": 611 } + { + "success": "false", + "errors.0.code": 600 + }, + { + "success": "false", + "errors.0.code": 601 + }, + { + "success": "false", + "errors.0.code": 602 + }, + { + "success": "false", + "errors.0.code": 604 + }, + { + "success": "false", + "errors.0.code": 606 + }, + { + "success": "false", + "errors.0.code": 607 + }, + { + "success": "false", + "errors.0.code": 608 + }, + { + "success": "false", + "errors.0.code": 611 + } ], "abortable": [ - { "success": "false", "errors.0.code": 603 }, - { "success": "false", "errors.0.code": 605 }, - { "success": "false", "errors.0.code": 609 }, - { "success": "false", "errors.0.code": 610 } + { + "success": "false", + "errors.0.code": 603 + }, + { + "success": "false", + "errors.0.code": 605 + }, + { + "success": "false", + "errors.0.code": 609 + }, + { + "success": "false", + "errors.0.code": 610 + } ] } }, diff --git a/test/__tests__/data/marketo_router_output.json b/test/__tests__/data/marketo_router_output.json index a8877399e9..c4b59b396d 100644 --- a/test/__tests__/data/marketo_router_output.json +++ b/test/__tests__/data/marketo_router_output.json @@ -41,29 +41,24 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } ] }, "secretConfig": {}, @@ -82,9 +77,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -204,29 +198,24 @@ "clientId": "marketo_client_id_success", "clientSecret": "marketo_client_secret_success", "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], "customActivityPropertyMap": [ { "from": "name", "to": "productName" } ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], "leadTraitMapping": [ { "from": "leadScore", "to": "customLeadScore" } + ], + "rudderEventsMapping": [ + { + "event": "Product Clicked", + "marketoPrimarykey": "name", + "marketoActivityId": "100001" + } ] }, "secretConfig": {}, @@ -245,9 +234,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -345,38 +333,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -388,9 +376,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -492,38 +479,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -535,9 +522,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, @@ -673,38 +659,38 @@ "clientSecret": "3l3gJpzRsZagD6gu7tnTeKXz0bomLGnd", "trackAnonymousEvents": false, "createIfNotExist": true, - "customActivityEventMap": [ + "rudderEventsMapping": [ { - "from": "acq_signup_completed", - "to": "100026" + "event": "acq_signup_completed", + "marketoActivityId": "100026" }, { - "from": "act_createwebinarform_submit", - "to": "100025" + "event": "act_createwebinarform_submit", + "marketoActivityId": "100025" }, { - "from": "act_presentation_style", - "to": "100025" + "event": "act_presentation_style", + "marketoActivityId": "100025" }, { - "from": "act_webinar_view", - "to": "100025" + "event": "act_webinar_view", + "marketoActivityId": "100025" }, { - "from": "act_webinar_join", - "to": "100025" + "event": "act_webinar_join", + "marketoActivityId": "100025" }, { - "from": "act_presentation_addteammember", - "to": "100025" + "event": "act_presentation_addteammember", + "marketoActivityId": "100025" }, { - "from": "act_engagement_discussions_savediscussion", - "to": "100025" + "event": "act_engagement_discussions_savediscussion", + "marketoActivityId": "100025" }, { - "to": "100025", - "from": "act_engagement_networking_savetime" + "event": "act_engagement_networking_savetime", + "marketoActivityId": "100025" } ] }, @@ -716,9 +702,8 @@ "clientId", "clientSecret", "trackAnonymousEvents", - "customActivityEventMap", + "rudderEventsMapping", "customActivityPropertyMap", - "customActivityPrimaryKeyMap", "leadTraitMapping" ] }, diff --git a/test/__tests__/data/marketo_static_list.json b/test/__tests__/data/marketo_static_list.json deleted file mode 100644 index 701868cab0..0000000000 --- a/test/__tests__/data/marketo_static_list.json +++ /dev/null @@ -1,2542 +0,0 @@ -[ - { - "description": "adding and removing users and getting staticListId from externalId", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 3421 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "id": 1 - }, - { - "id": 2 - }, - { - "id": 3 - } - ], - "remove": [ - { - "id": 4 - }, - { - "id": 5 - }, - { - "id": 6 - } - ] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - }, - "externalId": [ - { - "type": "marketoStaticListId", - "id": 1234 - } - ] - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "DELETE", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ] - }, - { - "description": "adding more than max limit users", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "id": 0 - }, - { - "id": 1 - }, - { - "id": 2 - }, - { - "id": 3 - }, - { - "id": 4 - }, - { - "id": 5 - }, - { - "id": 6 - }, - { - "id": 7 - }, - { - "id": 8 - }, - { - "id": 9 - }, - { - "id": 10 - }, - { - "id": 11 - }, - { - "id": 12 - }, - { - "id": 13 - }, - { - "id": 14 - }, - { - "id": 15 - }, - { - "id": 16 - }, - { - "id": 17 - }, - { - "id": 18 - }, - { - "id": 19 - }, - { - "id": 20 - }, - { - "id": 21 - }, - { - "id": 22 - }, - { - "id": 23 - }, - { - "id": 24 - }, - { - "id": 25 - }, - { - "id": 26 - }, - { - "id": 27 - }, - { - "id": 28 - }, - { - "id": 29 - }, - { - "id": 30 - }, - { - "id": 31 - }, - { - "id": 32 - }, - { - "id": 33 - }, - { - "id": 34 - }, - { - "id": 35 - }, - { - "id": 36 - }, - { - "id": 37 - }, - { - "id": 38 - }, - { - "id": 39 - }, - { - "id": 40 - }, - { - "id": 41 - }, - { - "id": 42 - }, - { - "id": 43 - }, - { - "id": 44 - }, - { - "id": 45 - }, - { - "id": 46 - }, - { - "id": 47 - }, - { - "id": 48 - }, - { - "id": 49 - }, - { - "id": 50 - }, - { - "id": 51 - }, - { - "id": 52 - }, - { - "id": 53 - }, - { - "id": 54 - }, - { - "id": 55 - }, - { - "id": 56 - }, - { - "id": 57 - }, - { - "id": 58 - }, - { - "id": 59 - }, - { - "id": 60 - }, - { - "id": 61 - }, - { - "id": 62 - }, - { - "id": 63 - }, - { - "id": 64 - }, - { - "id": 65 - }, - { - "id": 66 - }, - { - "id": 67 - }, - { - "id": 68 - }, - { - "id": 69 - }, - { - "id": 70 - }, - { - "id": 71 - }, - { - "id": 72 - }, - { - "id": 73 - }, - { - "id": 74 - }, - { - "id": 75 - }, - { - "id": 76 - }, - { - "id": 77 - }, - { - "id": 78 - }, - { - "id": 79 - }, - { - "id": 80 - }, - { - "id": 81 - }, - { - "id": 82 - }, - { - "id": 83 - }, - { - "id": 84 - }, - { - "id": 85 - }, - { - "id": 86 - }, - { - "id": 87 - }, - { - "id": 88 - }, - { - "id": 89 - }, - { - "id": 90 - }, - { - "id": 91 - }, - { - "id": 92 - }, - { - "id": 93 - }, - { - "id": 94 - }, - { - "id": 95 - }, - { - "id": 96 - }, - { - "id": 97 - }, - { - "id": 98 - }, - { - "id": 99 - }, - { - "id": 100 - }, - { - "id": 101 - }, - { - "id": 102 - }, - { - "id": 103 - }, - { - "id": 104 - }, - { - "id": 105 - }, - { - "id": 106 - }, - { - "id": 107 - }, - { - "id": 108 - }, - { - "id": 109 - }, - { - "id": 110 - }, - { - "id": 111 - }, - { - "id": 112 - }, - { - "id": 113 - }, - { - "id": 114 - }, - { - "id": 115 - }, - { - "id": 116 - }, - { - "id": 117 - }, - { - "id": 118 - }, - { - "id": 119 - }, - { - "id": 120 - }, - { - "id": 121 - }, - { - "id": 122 - }, - { - "id": 123 - }, - { - "id": 124 - }, - { - "id": 125 - }, - { - "id": 126 - }, - { - "id": 127 - }, - { - "id": 128 - }, - { - "id": 129 - }, - { - "id": 130 - }, - { - "id": 131 - }, - { - "id": 132 - }, - { - "id": 133 - }, - { - "id": 134 - }, - { - "id": 135 - }, - { - "id": 136 - }, - { - "id": 137 - }, - { - "id": 138 - }, - { - "id": 139 - }, - { - "id": 140 - }, - { - "id": 141 - }, - { - "id": 142 - }, - { - "id": 143 - }, - { - "id": 144 - }, - { - "id": 145 - }, - { - "id": 146 - }, - { - "id": 147 - }, - { - "id": 148 - }, - { - "id": 149 - }, - { - "id": 150 - }, - { - "id": 151 - }, - { - "id": 152 - }, - { - "id": 153 - }, - { - "id": 154 - }, - { - "id": 155 - }, - { - "id": 156 - }, - { - "id": 157 - }, - { - "id": 158 - }, - { - "id": 159 - }, - { - "id": 160 - }, - { - "id": 161 - }, - { - "id": 162 - }, - { - "id": 163 - }, - { - "id": 164 - }, - { - "id": 165 - }, - { - "id": 166 - }, - { - "id": 167 - }, - { - "id": 168 - }, - { - "id": 169 - }, - { - "id": 170 - }, - { - "id": 171 - }, - { - "id": 172 - }, - { - "id": 173 - }, - { - "id": 174 - }, - { - "id": 175 - }, - { - "id": 176 - }, - { - "id": 177 - }, - { - "id": 178 - }, - { - "id": 179 - }, - { - "id": 180 - }, - { - "id": 181 - }, - { - "id": 182 - }, - { - "id": 183 - }, - { - "id": 184 - }, - { - "id": 185 - }, - { - "id": 186 - }, - { - "id": 187 - }, - { - "id": 188 - }, - { - "id": 189 - }, - { - "id": 190 - }, - { - "id": 191 - }, - { - "id": 192 - }, - { - "id": 193 - }, - { - "id": 194 - }, - { - "id": 195 - }, - { - "id": 196 - }, - { - "id": 197 - }, - { - "id": 198 - }, - { - "id": 199 - }, - { - "id": 200 - }, - { - "id": 201 - }, - { - "id": 202 - }, - { - "id": 203 - }, - { - "id": 204 - }, - { - "id": 205 - }, - { - "id": 206 - }, - { - "id": 207 - }, - { - "id": 208 - }, - { - "id": 209 - }, - { - "id": 210 - }, - { - "id": 211 - }, - { - "id": 212 - }, - { - "id": 213 - }, - { - "id": 214 - }, - { - "id": 215 - }, - { - "id": 216 - }, - { - "id": 217 - }, - { - "id": 218 - }, - { - "id": 219 - }, - { - "id": 220 - }, - { - "id": 221 - }, - { - "id": 222 - }, - { - "id": 223 - }, - { - "id": 224 - }, - { - "id": 225 - }, - { - "id": 226 - }, - { - "id": 227 - }, - { - "id": 228 - }, - { - "id": 229 - }, - { - "id": 230 - }, - { - "id": 231 - }, - { - "id": 232 - }, - { - "id": 233 - }, - { - "id": 234 - }, - { - "id": 235 - }, - { - "id": 236 - }, - { - "id": 237 - }, - { - "id": 238 - }, - { - "id": 239 - }, - { - "id": 240 - }, - { - "id": 241 - }, - { - "id": 242 - }, - { - "id": 243 - }, - { - "id": 244 - }, - { - "id": 245 - }, - { - "id": 246 - }, - { - "id": 247 - }, - { - "id": 248 - }, - { - "id": 249 - }, - { - "id": 250 - }, - { - "id": 251 - }, - { - "id": 252 - }, - { - "id": 253 - }, - { - "id": 254 - }, - { - "id": 255 - }, - { - "id": 256 - }, - { - "id": 257 - }, - { - "id": 258 - }, - { - "id": 259 - }, - { - "id": 260 - }, - { - "id": 261 - }, - { - "id": 262 - }, - { - "id": 263 - }, - { - "id": 264 - }, - { - "id": 265 - }, - { - "id": 266 - }, - { - "id": 267 - }, - { - "id": 268 - }, - { - "id": 269 - }, - { - "id": 270 - }, - { - "id": 271 - }, - { - "id": 272 - }, - { - "id": 273 - }, - { - "id": 274 - }, - { - "id": 275 - }, - { - "id": 276 - }, - { - "id": 277 - }, - { - "id": 278 - }, - { - "id": 279 - }, - { - "id": 280 - }, - { - "id": 281 - }, - { - "id": 282 - }, - { - "id": 283 - }, - { - "id": 284 - }, - { - "id": 285 - }, - { - "id": 286 - }, - { - "id": 287 - }, - { - "id": 288 - }, - { - "id": 289 - }, - { - "id": 290 - }, - { - "id": 291 - }, - { - "id": 292 - }, - { - "id": 293 - }, - { - "id": 294 - }, - { - "id": 295 - }, - { - "id": 296 - }, - { - "id": 297 - }, - { - "id": 298 - }, - { - "id": 299 - }, - { - "id": 300 - }, - { - "id": 301 - }, - { - "id": 302 - }, - { - "id": 303 - }, - { - "id": 304 - }, - { - "id": 305 - }, - { - "id": 306 - }, - { - "id": 307 - }, - { - "id": 308 - }, - { - "id": 309 - }, - { - "id": 310 - }, - { - "id": 311 - }, - { - "id": 312 - }, - { - "id": 313 - }, - { - "id": 314 - }, - { - "id": 315 - }, - { - "id": 316 - }, - { - "id": 317 - }, - { - "id": 318 - }, - { - "id": 319 - }, - { - "id": 320 - }, - { - "id": 321 - }, - { - "id": 322 - }, - { - "id": 323 - }, - { - "id": 324 - }, - { - "id": 325 - }, - { - "id": 326 - }, - { - "id": 327 - }, - { - "id": 328 - }, - { - "id": 329 - }, - { - "id": 330 - }, - { - "id": 331 - }, - { - "id": 332 - }, - { - "id": 333 - }, - { - "id": 334 - }, - { - "id": 335 - }, - { - "id": 336 - }, - { - "id": 337 - }, - { - "id": 338 - }, - { - "id": 339 - }, - { - "id": 340 - }, - { - "id": 341 - }, - { - "id": 342 - }, - { - "id": 343 - }, - { - "id": 344 - }, - { - "id": 345 - }, - { - "id": 346 - }, - { - "id": 347 - }, - { - "id": 348 - }, - { - "id": 349 - }, - { - "id": 350 - } - ] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=300&id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ] - }, - { - "description": "removing more than max limit users", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "remove": [ - { - "id": 0 - }, - { - "id": 1 - }, - { - "id": 2 - }, - { - "id": 3 - }, - { - "id": 4 - }, - { - "id": 5 - }, - { - "id": 6 - }, - { - "id": 7 - }, - { - "id": 8 - }, - { - "id": 9 - }, - { - "id": 10 - }, - { - "id": 11 - }, - { - "id": 12 - }, - { - "id": 13 - }, - { - "id": 14 - }, - { - "id": 15 - }, - { - "id": 16 - }, - { - "id": 17 - }, - { - "id": 18 - }, - { - "id": 19 - }, - { - "id": 20 - }, - { - "id": 21 - }, - { - "id": 22 - }, - { - "id": 23 - }, - { - "id": 24 - }, - { - "id": 25 - }, - { - "id": 26 - }, - { - "id": 27 - }, - { - "id": 28 - }, - { - "id": 29 - }, - { - "id": 30 - }, - { - "id": 31 - }, - { - "id": 32 - }, - { - "id": 33 - }, - { - "id": 34 - }, - { - "id": 35 - }, - { - "id": 36 - }, - { - "id": 37 - }, - { - "id": 38 - }, - { - "id": 39 - }, - { - "id": 40 - }, - { - "id": 41 - }, - { - "id": 42 - }, - { - "id": 43 - }, - { - "id": 44 - }, - { - "id": 45 - }, - { - "id": 46 - }, - { - "id": 47 - }, - { - "id": 48 - }, - { - "id": 49 - }, - { - "id": 50 - }, - { - "id": 51 - }, - { - "id": 52 - }, - { - "id": 53 - }, - { - "id": 54 - }, - { - "id": 55 - }, - { - "id": 56 - }, - { - "id": 57 - }, - { - "id": 58 - }, - { - "id": 59 - }, - { - "id": 60 - }, - { - "id": 61 - }, - { - "id": 62 - }, - { - "id": 63 - }, - { - "id": 64 - }, - { - "id": 65 - }, - { - "id": 66 - }, - { - "id": 67 - }, - { - "id": 68 - }, - { - "id": 69 - }, - { - "id": 70 - }, - { - "id": 71 - }, - { - "id": 72 - }, - { - "id": 73 - }, - { - "id": 74 - }, - { - "id": 75 - }, - { - "id": 76 - }, - { - "id": 77 - }, - { - "id": 78 - }, - { - "id": 79 - }, - { - "id": 80 - }, - { - "id": 81 - }, - { - "id": 82 - }, - { - "id": 83 - }, - { - "id": 84 - }, - { - "id": 85 - }, - { - "id": 86 - }, - { - "id": 87 - }, - { - "id": 88 - }, - { - "id": 89 - }, - { - "id": 90 - }, - { - "id": 91 - }, - { - "id": 92 - }, - { - "id": 93 - }, - { - "id": 94 - }, - { - "id": 95 - }, - { - "id": 96 - }, - { - "id": 97 - }, - { - "id": 98 - }, - { - "id": 99 - }, - { - "id": 100 - }, - { - "id": 101 - }, - { - "id": 102 - }, - { - "id": 103 - }, - { - "id": 104 - }, - { - "id": 105 - }, - { - "id": 106 - }, - { - "id": 107 - }, - { - "id": 108 - }, - { - "id": 109 - }, - { - "id": 110 - }, - { - "id": 111 - }, - { - "id": 112 - }, - { - "id": 113 - }, - { - "id": 114 - }, - { - "id": 115 - }, - { - "id": 116 - }, - { - "id": 117 - }, - { - "id": 118 - }, - { - "id": 119 - }, - { - "id": 120 - }, - { - "id": 121 - }, - { - "id": 122 - }, - { - "id": 123 - }, - { - "id": 124 - }, - { - "id": 125 - }, - { - "id": 126 - }, - { - "id": 127 - }, - { - "id": 128 - }, - { - "id": 129 - }, - { - "id": 130 - }, - { - "id": 131 - }, - { - "id": 132 - }, - { - "id": 133 - }, - { - "id": 134 - }, - { - "id": 135 - }, - { - "id": 136 - }, - { - "id": 137 - }, - { - "id": 138 - }, - { - "id": 139 - }, - { - "id": 140 - }, - { - "id": 141 - }, - { - "id": 142 - }, - { - "id": 143 - }, - { - "id": 144 - }, - { - "id": 145 - }, - { - "id": 146 - }, - { - "id": 147 - }, - { - "id": 148 - }, - { - "id": 149 - }, - { - "id": 150 - }, - { - "id": 151 - }, - { - "id": 152 - }, - { - "id": 153 - }, - { - "id": 154 - }, - { - "id": 155 - }, - { - "id": 156 - }, - { - "id": 157 - }, - { - "id": 158 - }, - { - "id": 159 - }, - { - "id": 160 - }, - { - "id": 161 - }, - { - "id": 162 - }, - { - "id": 163 - }, - { - "id": 164 - }, - { - "id": 165 - }, - { - "id": 166 - }, - { - "id": 167 - }, - { - "id": 168 - }, - { - "id": 169 - }, - { - "id": 170 - }, - { - "id": 171 - }, - { - "id": 172 - }, - { - "id": 173 - }, - { - "id": 174 - }, - { - "id": 175 - }, - { - "id": 176 - }, - { - "id": 177 - }, - { - "id": 178 - }, - { - "id": 179 - }, - { - "id": 180 - }, - { - "id": 181 - }, - { - "id": 182 - }, - { - "id": 183 - }, - { - "id": 184 - }, - { - "id": 185 - }, - { - "id": 186 - }, - { - "id": 187 - }, - { - "id": 188 - }, - { - "id": 189 - }, - { - "id": 190 - }, - { - "id": 191 - }, - { - "id": 192 - }, - { - "id": 193 - }, - { - "id": 194 - }, - { - "id": 195 - }, - { - "id": 196 - }, - { - "id": 197 - }, - { - "id": 198 - }, - { - "id": 199 - }, - { - "id": 200 - }, - { - "id": 201 - }, - { - "id": 202 - }, - { - "id": 203 - }, - { - "id": 204 - }, - { - "id": 205 - }, - { - "id": 206 - }, - { - "id": 207 - }, - { - "id": 208 - }, - { - "id": 209 - }, - { - "id": 210 - }, - { - "id": 211 - }, - { - "id": 212 - }, - { - "id": 213 - }, - { - "id": 214 - }, - { - "id": 215 - }, - { - "id": 216 - }, - { - "id": 217 - }, - { - "id": 218 - }, - { - "id": 219 - }, - { - "id": 220 - }, - { - "id": 221 - }, - { - "id": 222 - }, - { - "id": 223 - }, - { - "id": 224 - }, - { - "id": 225 - }, - { - "id": 226 - }, - { - "id": 227 - }, - { - "id": 228 - }, - { - "id": 229 - }, - { - "id": 230 - }, - { - "id": 231 - }, - { - "id": 232 - }, - { - "id": 233 - }, - { - "id": 234 - }, - { - "id": 235 - }, - { - "id": 236 - }, - { - "id": 237 - }, - { - "id": 238 - }, - { - "id": 239 - }, - { - "id": 240 - }, - { - "id": 241 - }, - { - "id": 242 - }, - { - "id": 243 - }, - { - "id": 244 - }, - { - "id": 245 - }, - { - "id": 246 - }, - { - "id": 247 - }, - { - "id": 248 - }, - { - "id": 249 - }, - { - "id": 250 - }, - { - "id": 251 - }, - { - "id": 252 - }, - { - "id": 253 - }, - { - "id": 254 - }, - { - "id": 255 - }, - { - "id": 256 - }, - { - "id": 257 - }, - { - "id": 258 - }, - { - "id": 259 - }, - { - "id": 260 - }, - { - "id": 261 - }, - { - "id": 262 - }, - { - "id": 263 - }, - { - "id": 264 - }, - { - "id": 265 - }, - { - "id": 266 - }, - { - "id": 267 - }, - { - "id": 268 - }, - { - "id": 269 - }, - { - "id": 270 - }, - { - "id": 271 - }, - { - "id": 272 - }, - { - "id": 273 - }, - { - "id": 274 - }, - { - "id": 275 - }, - { - "id": 276 - }, - { - "id": 277 - }, - { - "id": 278 - }, - { - "id": 279 - }, - { - "id": 280 - }, - { - "id": 281 - }, - { - "id": 282 - }, - { - "id": 283 - }, - { - "id": 284 - }, - { - "id": 285 - }, - { - "id": 286 - }, - { - "id": 287 - }, - { - "id": 288 - }, - { - "id": 289 - }, - { - "id": 290 - }, - { - "id": 291 - }, - { - "id": 292 - }, - { - "id": 293 - }, - { - "id": 294 - }, - { - "id": 295 - }, - { - "id": 296 - }, - { - "id": 297 - }, - { - "id": 298 - }, - { - "id": 299 - }, - { - "id": 300 - }, - { - "id": 301 - }, - { - "id": 302 - }, - { - "id": 303 - }, - { - "id": 304 - }, - { - "id": 305 - }, - { - "id": 306 - }, - { - "id": 307 - }, - { - "id": 308 - }, - { - "id": 309 - }, - { - "id": 310 - }, - { - "id": 311 - }, - { - "id": 312 - }, - { - "id": 313 - }, - { - "id": 314 - }, - { - "id": 315 - }, - { - "id": 316 - }, - { - "id": 317 - }, - { - "id": 318 - }, - { - "id": 319 - }, - { - "id": 320 - }, - { - "id": 321 - }, - { - "id": 322 - }, - { - "id": 323 - }, - { - "id": 324 - }, - { - "id": 325 - }, - { - "id": 326 - }, - { - "id": 327 - }, - { - "id": 328 - }, - { - "id": 329 - }, - { - "id": 330 - }, - { - "id": 331 - }, - { - "id": 332 - }, - { - "id": 333 - }, - { - "id": 334 - }, - { - "id": 335 - }, - { - "id": 336 - }, - { - "id": 337 - }, - { - "id": 338 - }, - { - "id": 339 - }, - { - "id": 340 - }, - { - "id": 341 - }, - { - "id": 342 - }, - { - "id": 343 - }, - { - "id": 344 - }, - { - "id": 345 - }, - { - "id": 346 - }, - { - "id": 347 - }, - { - "id": 348 - }, - { - "id": 349 - }, - { - "id": 350 - } - ] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": [ - { - "version": "1", - "type": "REST", - "method": "DELETE", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "DELETE", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=300&id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ] - }, - { - "description": "unsupported message Type", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "track", - "properties": { - "listData": { - "remove": [1] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": { - "error": "Event type track is not supported" - } - }, - { - "description": "Invalid leadIds format ", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "remove": 1 - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": { - "error": "Invalid leadIds format or no leadIds found neither to add nor to remove" - } - }, - { - "description": "Only adding with remove not an array", - "input": { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [{ "id": 1 }], - "remove": 2 - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - } - }, - "output": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ] - } -] diff --git a/test/__tests__/data/marketo_static_list_router_input.json b/test/__tests__/data/marketo_static_list_router_input.json deleted file mode 100644 index ed3a7591e6..0000000000 --- a/test/__tests__/data/marketo_static_list_router_input.json +++ /dev/null @@ -1,1209 +0,0 @@ -[ - { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "id": 1 - }, - { - "id": 2 - }, - { - "id": 3 - } - ], - "remove": [ - { - "id": 4 - }, - { - "id": 5 - }, - { - "id": 6 - } - ] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - }, - "metadata": { - "jobId": 1 - } - }, - { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "id": 0 - }, - { - "id": 1 - }, - { - "id": 2 - }, - { - "id": 3 - }, - { - "id": 4 - }, - { - "id": 5 - }, - { - "id": 6 - }, - { - "id": 7 - }, - { - "id": 8 - }, - { - "id": 9 - }, - { - "id": 10 - }, - { - "id": 11 - }, - { - "id": 12 - }, - { - "id": 13 - }, - { - "id": 14 - }, - { - "id": 15 - }, - { - "id": 16 - }, - { - "id": 17 - }, - { - "id": 18 - }, - { - "id": 19 - }, - { - "id": 20 - }, - { - "id": 21 - }, - { - "id": 22 - }, - { - "id": 23 - }, - { - "id": 24 - }, - { - "id": 25 - }, - { - "id": 26 - }, - { - "id": 27 - }, - { - "id": 28 - }, - { - "id": 29 - }, - { - "id": 30 - }, - { - "id": 31 - }, - { - "id": 32 - }, - { - "id": 33 - }, - { - "id": 34 - }, - { - "id": 35 - }, - { - "id": 36 - }, - { - "id": 37 - }, - { - "id": 38 - }, - { - "id": 39 - }, - { - "id": 40 - }, - { - "id": 41 - }, - { - "id": 42 - }, - { - "id": 43 - }, - { - "id": 44 - }, - { - "id": 45 - }, - { - "id": 46 - }, - { - "id": 47 - }, - { - "id": 48 - }, - { - "id": 49 - }, - { - "id": 50 - }, - { - "id": 51 - }, - { - "id": 52 - }, - { - "id": 53 - }, - { - "id": 54 - }, - { - "id": 55 - }, - { - "id": 56 - }, - { - "id": 57 - }, - { - "id": 58 - }, - { - "id": 59 - }, - { - "id": 60 - }, - { - "id": 61 - }, - { - "id": 62 - }, - { - "id": 63 - }, - { - "id": 64 - }, - { - "id": 65 - }, - { - "id": 66 - }, - { - "id": 67 - }, - { - "id": 68 - }, - { - "id": 69 - }, - { - "id": 70 - }, - { - "id": 71 - }, - { - "id": 72 - }, - { - "id": 73 - }, - { - "id": 74 - }, - { - "id": 75 - }, - { - "id": 76 - }, - { - "id": 77 - }, - { - "id": 78 - }, - { - "id": 79 - }, - { - "id": 80 - }, - { - "id": 81 - }, - { - "id": 82 - }, - { - "id": 83 - }, - { - "id": 84 - }, - { - "id": 85 - }, - { - "id": 86 - }, - { - "id": 87 - }, - { - "id": 88 - }, - { - "id": 89 - }, - { - "id": 90 - }, - { - "id": 91 - }, - { - "id": 92 - }, - { - "id": 93 - }, - { - "id": 94 - }, - { - "id": 95 - }, - { - "id": 96 - }, - { - "id": 97 - }, - { - "id": 98 - }, - { - "id": 99 - }, - { - "id": 100 - }, - { - "id": 101 - }, - { - "id": 102 - }, - { - "id": 103 - }, - { - "id": 104 - }, - { - "id": 105 - }, - { - "id": 106 - }, - { - "id": 107 - }, - { - "id": 108 - }, - { - "id": 109 - }, - { - "id": 110 - }, - { - "id": 111 - }, - { - "id": 112 - }, - { - "id": 113 - }, - { - "id": 114 - }, - { - "id": 115 - }, - { - "id": 116 - }, - { - "id": 117 - }, - { - "id": 118 - }, - { - "id": 119 - }, - { - "id": 120 - }, - { - "id": 121 - }, - { - "id": 122 - }, - { - "id": 123 - }, - { - "id": 124 - }, - { - "id": 125 - }, - { - "id": 126 - }, - { - "id": 127 - }, - { - "id": 128 - }, - { - "id": 129 - }, - { - "id": 130 - }, - { - "id": 131 - }, - { - "id": 132 - }, - { - "id": 133 - }, - { - "id": 134 - }, - { - "id": 135 - }, - { - "id": 136 - }, - { - "id": 137 - }, - { - "id": 138 - }, - { - "id": 139 - }, - { - "id": 140 - }, - { - "id": 141 - }, - { - "id": 142 - }, - { - "id": 143 - }, - { - "id": 144 - }, - { - "id": 145 - }, - { - "id": 146 - }, - { - "id": 147 - }, - { - "id": 148 - }, - { - "id": 149 - }, - { - "id": 150 - }, - { - "id": 151 - }, - { - "id": 152 - }, - { - "id": 153 - }, - { - "id": 154 - }, - { - "id": 155 - }, - { - "id": 156 - }, - { - "id": 157 - }, - { - "id": 158 - }, - { - "id": 159 - }, - { - "id": 160 - }, - { - "id": 161 - }, - { - "id": 162 - }, - { - "id": 163 - }, - { - "id": 164 - }, - { - "id": 165 - }, - { - "id": 166 - }, - { - "id": 167 - }, - { - "id": 168 - }, - { - "id": 169 - }, - { - "id": 170 - }, - { - "id": 171 - }, - { - "id": 172 - }, - { - "id": 173 - }, - { - "id": 174 - }, - { - "id": 175 - }, - { - "id": 176 - }, - { - "id": 177 - }, - { - "id": 178 - }, - { - "id": 179 - }, - { - "id": 180 - }, - { - "id": 181 - }, - { - "id": 182 - }, - { - "id": 183 - }, - { - "id": 184 - }, - { - "id": 185 - }, - { - "id": 186 - }, - { - "id": 187 - }, - { - "id": 188 - }, - { - "id": 189 - }, - { - "id": 190 - }, - { - "id": 191 - }, - { - "id": 192 - }, - { - "id": 193 - }, - { - "id": 194 - }, - { - "id": 195 - }, - { - "id": 196 - }, - { - "id": 197 - }, - { - "id": 198 - }, - { - "id": 199 - }, - { - "id": 200 - }, - { - "id": 201 - }, - { - "id": 202 - }, - { - "id": 203 - }, - { - "id": 204 - }, - { - "id": 205 - }, - { - "id": 206 - }, - { - "id": 207 - }, - { - "id": 208 - }, - { - "id": 209 - }, - { - "id": 210 - }, - { - "id": 211 - }, - { - "id": 212 - }, - { - "id": 213 - }, - { - "id": 214 - }, - { - "id": 215 - }, - { - "id": 216 - }, - { - "id": 217 - }, - { - "id": 218 - }, - { - "id": 219 - }, - { - "id": 220 - }, - { - "id": 221 - }, - { - "id": 222 - }, - { - "id": 223 - }, - { - "id": 224 - }, - { - "id": 225 - }, - { - "id": 226 - }, - { - "id": 227 - }, - { - "id": 228 - }, - { - "id": 229 - }, - { - "id": 230 - }, - { - "id": 231 - }, - { - "id": 232 - }, - { - "id": 233 - }, - { - "id": 234 - }, - { - "id": 235 - }, - { - "id": 236 - }, - { - "id": 237 - }, - { - "id": 238 - }, - { - "id": 239 - }, - { - "id": 240 - }, - { - "id": 241 - }, - { - "id": 242 - }, - { - "id": 243 - }, - { - "id": 244 - }, - { - "id": 245 - }, - { - "id": 246 - }, - { - "id": 247 - }, - { - "id": 248 - }, - { - "id": 249 - }, - { - "id": 250 - }, - { - "id": 251 - }, - { - "id": 252 - }, - { - "id": 253 - }, - { - "id": 254 - }, - { - "id": 255 - }, - { - "id": 256 - }, - { - "id": 257 - }, - { - "id": 258 - }, - { - "id": 259 - }, - { - "id": 260 - }, - { - "id": 261 - }, - { - "id": 262 - }, - { - "id": 263 - }, - { - "id": 264 - }, - { - "id": 265 - }, - { - "id": 266 - }, - { - "id": 267 - }, - { - "id": 268 - }, - { - "id": 269 - }, - { - "id": 270 - }, - { - "id": 271 - }, - { - "id": 272 - }, - { - "id": 273 - }, - { - "id": 274 - }, - { - "id": 275 - }, - { - "id": 276 - }, - { - "id": 277 - }, - { - "id": 278 - }, - { - "id": 279 - }, - { - "id": 280 - }, - { - "id": 281 - }, - { - "id": 282 - }, - { - "id": 283 - }, - { - "id": 284 - }, - { - "id": 285 - }, - { - "id": 286 - }, - { - "id": 287 - }, - { - "id": 288 - }, - { - "id": 289 - }, - { - "id": 290 - }, - { - "id": 291 - }, - { - "id": 292 - }, - { - "id": 293 - }, - { - "id": 294 - }, - { - "id": 295 - }, - { - "id": 296 - }, - { - "id": 297 - }, - { - "id": 298 - }, - { - "id": 299 - }, - { - "id": 300 - }, - { - "id": 301 - }, - { - "id": 302 - }, - { - "id": 303 - }, - { - "id": 304 - }, - { - "id": 305 - }, - { - "id": 306 - }, - { - "id": 307 - }, - { - "id": 308 - }, - { - "id": 309 - }, - { - "id": 310 - }, - { - "id": 311 - }, - { - "id": 312 - }, - { - "id": 313 - }, - { - "id": 314 - }, - { - "id": 315 - }, - { - "id": 316 - }, - { - "id": 317 - }, - { - "id": 318 - }, - { - "id": 319 - }, - { - "id": 320 - }, - { - "id": 321 - }, - { - "id": 322 - }, - { - "id": 323 - }, - { - "id": 324 - }, - { - "id": 325 - }, - { - "id": 326 - }, - { - "id": 327 - }, - { - "id": 328 - }, - { - "id": 329 - }, - { - "id": 330 - }, - { - "id": 331 - }, - { - "id": 332 - }, - { - "id": 333 - }, - { - "id": 334 - }, - { - "id": 335 - }, - { - "id": 336 - }, - { - "id": 337 - }, - { - "id": 338 - }, - { - "id": 339 - }, - { - "id": 340 - }, - { - "id": 341 - }, - { - "id": 342 - }, - { - "id": 343 - }, - { - "id": 344 - }, - { - "id": 345 - }, - { - "id": 346 - }, - { - "id": 347 - }, - { - "id": 348 - }, - { - "id": 349 - }, - { - "id": 350 - } - ] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - }, - "metadata": { - "jobId": 2 - } - }, - { - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "message": { - "userId": "user 1", - "anonymousId": "anon-id-new", - "event": "event1", - "type": "track", - "properties": { - "listData": { - "remove": [1] - }, - "enablePartialFailure": true - }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-02-02T00:23:09.544Z" - }, - "metadata": { - "jobId": 3 - } - } -] diff --git a/test/__tests__/data/marketo_static_list_router_metadata_input.json b/test/__tests__/data/marketo_static_list_router_metadata_input.json deleted file mode 100644 index d006aa184b..0000000000 --- a/test/__tests__/data/marketo_static_list_router_metadata_input.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "batchedRequest": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3", - "headers": { - "Content-Type": "application/json", - "Authorization": "Bearer access_token_success" - }, - "params": {}, - "body": { - "JSON": {}, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - }, - "metadata": [ - { - "jobId": 1 - }, - { - "jobId": 2 - }, - { - "jobId": 3 - } - ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "accountId": "marketo_acct_id_success", - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "staticListId": 3027 - }, - "secretConfig": {}, - "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", - "name": "Marketo Static List", - "enabled": true, - "workspaceId": "1TSN08muJTZwH8iCDmnnRt1pmLd", - "deleted": false, - "createdAt": "2020-12-30T08:39:32.005Z", - "updatedAt": "2021-02-03T16:22:31.374Z", - "destinationDefinition": { - "config": { - "destConfig": { - "defaultConfig": ["accountId", "clientId", "clientSecret", "staticListId"] - }, - "secretKeys": ["clientSecret"], - "excludeKeys": [], - "includeKeys": [], - "routerTransform": true, - "supportedSourceTypes": ["android", "ios", "web", "unity", "amp", "cloud", "reactnative"] - }, - "id": "1aIXqM806xAVm92nx07YwKbRrO9", - "name": "MARKETO_STATIC_LIST", - "displayName": "Marketo Static List", - "createdAt": "2020-04-09T09:24:31.794Z", - "updatedAt": "2021-01-11T11:03:28.103Z" - }, - "transformations": [], - "isConnectionEnabled": true, - "isProcessorEnabled": true - } -} diff --git a/test/__tests__/data/marketo_static_list_router_metadata_output.json b/test/__tests__/data/marketo_static_list_router_metadata_output.json deleted file mode 100644 index bc560d73a7..0000000000 --- a/test/__tests__/data/marketo_static_list_router_metadata_output.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "destInfo": { - "authKey": "1mMy5cqbtfuaKZv1IhVQKnBdVwe" - }, - "jobId": 1 - }, - { - "destInfo": { - "authKey": "1mMy5cqbtfuaKZv1IhVQKnBdVwe" - }, - "jobId": 2 - }, - { - "destInfo": { - "authKey": "1mMy5cqbtfuaKZv1IhVQKnBdVwe" - }, - "jobId": 3 - } -] diff --git a/test/__tests__/data/marketo_static_list_router_output.json b/test/__tests__/data/marketo_static_list_router_output.json deleted file mode 100644 index 9c096b84c6..0000000000 --- a/test/__tests__/data/marketo_static_list_router_output.json +++ /dev/null @@ -1,170 +0,0 @@ -[ - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "DELETE", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ], - "metadata": [ - { - "jobId": 1 - } - ], - "batched": false, - "statusCode": 200, - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - } - }, - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=300&id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ], - "metadata": [ - { - "jobId": 2 - } - ], - "batched": false, - "statusCode": 200, - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - } - }, - { - "metadata": [ - { - "jobId": 3 - } - ], - "destination": { - "ID": "1zia9wKshXt80YksLmUdJnr7IHI", - "Name": "test_marketo", - "DestinationDefinition": { - "ID": "1iVQvTRMsPPyJzwol0ifH93QTQ6", - "Name": "MARKETO", - "DisplayName": "Marketo", - "transformAt": "processor", - "transformAtV1": "processor" - }, - "Config": { - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "accountId": "marketo_acct_id_success", - "staticListId": 1234 - }, - "Enabled": true, - "Transformations": [], - "IsProcessorEnabled": true - }, - "batched": false, - "statusCode": 400, - "error": "Event type track is not supported", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation" - } - } -] diff --git a/test/__tests__/data/pinterest_tag_output.json b/test/__tests__/data/pinterest_tag_output.json index d09e534f4b..9fb809d112 100644 --- a/test/__tests__/data/pinterest_tag_output.json +++ b/test/__tests__/data/pinterest_tag_output.json @@ -671,7 +671,12 @@ "advertiser_id": "123456", "app_id": "429047995", "custom_data": { - "contents": [{ "item_price": "undefined", "quantity": 1 }], + "contents": [ + { + "item_price": "undefined", + "quantity": 1 + } + ], "currency": "USD", "num_items": 0, "order_id": "50314b8e9bcf000000000000", @@ -698,7 +703,9 @@ }, "endpoint": "https://ct.pinterest.com/events/v3", "files": {}, - "headers": { "Content-Type": "application/json" }, + "headers": { + "Content-Type": "application/json" + }, "method": "POST", "params": {}, "type": "REST", @@ -906,8 +913,54 @@ "statusCode": 400, "error": "Conversion Token not found. Aborting" }, - { - "statusCode": 400, - "error": "custom event is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting" - } + [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api.pinterest.com/v5/ad_accounts/accountId123/events", + "headers": { + "Content-Type": "application/json", + "Authorization": "Bearer conversionToken123" + }, + "params": {}, + "body": { + "JSON": { + "event_name": "custom event", + "event_time": 1597383030, + "action_source": "web", + "event_id": "7208bbb6-2c4e-45bb-bf5b-ad426f3593e9", + "app_id": "429047995", + "user_data": { + "em": ["48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08"], + "ph": ["d164bbe036663cb5c96835e9ccc6501e9a521127ea62f6359744928ba932413b"], + "ln": ["dcf000c2386fb76d22cefc0d118a8511bb75999019cd373df52044bccd1bd251"], + "fn": ["9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"], + "ct": ["6689106ca7922c30b2fd2c175c85bc7fc2d52cc4941bdd7bb622c6cdc6284a85"], + "st": ["3b45022ab36728cdae12e709e945bba267c50ee8a91e6e4388539a8e03a3fdcd"], + "zp": ["1a4292e00780e18d00e76fde9850aee5344e939ba593333cd5e4b4aa2cd33b0c"], + "country": ["582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf"], + "hashed_maids": ["6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090"], + "client_user_agent": "chrome" + }, + "custom_data": { + "currency": "USD", + "value": "27.5", + "order_id": "50314b8e9bcf000000000000", + "num_items": 0, + "contents": [ + { + "quantity": 1, + "item_price": "undefined" + } + ] + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ] ] diff --git a/test/__tests__/data/sanity/active_campaign_output.json b/test/__tests__/data/sanity/active_campaign_output.json deleted file mode 100644 index 544f9b937f..0000000000 --- a/test/__tests__/data/sanity/active_campaign_output.json +++ /dev/null @@ -1,54 +0,0 @@ -[ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://active.campaigns.rudder.com/api/3/contact/sync", - "headers": { - "Content-Type": "application/json", - "Api-Token": "dummyApiToken" - }, - "params": {}, - "body": { - "JSON": { - "contact": { - "email": "manashi@gmail.com", - "phone": 9090909000, - "firstName": null, - "lastName": null - }, - "apiKey": "dummyApiKey" - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://active.campaigns.rudder.com/api/3/contact/sync", - "headers": { - "Content-Type": "application/json", - "Api-Token": "dummyApiToken" - }, - "params": {}, - "body": { - "JSON": { - "contact": { - "email": "testkolkata@rudderlabs.com", - "phone": "570-690-4150", - "firstName": "Sajal", - "lastName": "Mohanta" - }, - "apiKey": "dummyApiKey" - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - } -] diff --git a/test/__tests__/data/sanity/destination_config.json b/test/__tests__/data/sanity/destination_config.json deleted file mode 100644 index 11c999aa9c..0000000000 --- a/test/__tests__/data/sanity/destination_config.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "active_campaign": { - "config": { - "processor": { - "Config": { - "apiKey": "dummyApiKey", - "apiUrl": "https://active.campaigns.rudder.com", - "actid": "476550467", - "eventKey": "f8a866fddc721350fdc2fbbd2e5c43a6dddaaa03" - } - } - } - }, - "clevertap": { - "config": { - "processor": {}, - "router": {} - } - }, - "marketo": { - "config": { - "router": { - "Config": { - "accountId": "marketo_acct_id_success", - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "trackAnonymousEvents": true, - "customActivityEventMap": [{ "from": "Product Clicked", "to": "100001" }], - "customActivityPropertyMap": [{ "from": "name", "to": "productName" }], - "customActivityPrimaryKeyMap": [{ "from": "Product Clicked", "to": "name" }], - "leadTraitMapping": [{ "from": "leadScore", "to": "customLeadScore" }] - }, - "secretConfig": {}, - "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", - "name": "Marketo", - "enabled": true, - "workspaceId": "1TSN08muJTZwH8iCDmnnRt1pmLd", - "deleted": false, - "createdAt": "2020-12-30T08:39:32.005Z", - "updatedAt": "2021-02-03T16:22:31.374Z", - "destinationDefinition": { - "config": { - "destConfig": { - "defaultConfig": [ - "accountId", - "clientId", - "clientSecret", - "trackAnonymousEvents", - "customActivityEventMap", - "customActivityPropertyMap", - "customActivityPrimaryKeyMap", - "leadTraitMapping" - ] - }, - "secretKeys": ["clientSecret"], - "excludeKeys": [], - "includeKeys": [], - "routerTransform": true, - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative" - ] - }, - "responseRules": { - "responseType": "JSON", - "rules": { - "retryable": [ - { "success": "false", "errors.0.code": 600 }, - { "success": "false", "errors.0.code": 601 }, - { "success": "false", "errors.0.code": 602 }, - { "success": "false", "errors.0.code": 604 }, - { "success": "false", "errors.0.code": 606 }, - { "success": "false", "errors.0.code": 607 }, - { "success": "false", "errors.0.code": 608 }, - { "success": "false", "errors.0.code": 611 } - ], - "abortable": [ - { "success": "false", "errors.0.code": 603 }, - { "success": "false", "errors.0.code": 605 }, - { "success": "false", "errors.0.code": 609 }, - { "success": "false", "errors.0.code": 610 } - ] - } - }, - "id": "1aIXqM806xAVm92nx07YwKbRrO9", - "name": "MARKETO", - "displayName": "Marketo", - "createdAt": "2020-04-09T09:24:31.794Z", - "updatedAt": "2021-01-11T11:03:28.103Z" - }, - "transformations": [], - "isConnectionEnabled": true, - "isProcessorEnabled": true - } - } - } -} diff --git a/test/__tests__/data/sanity/marketo_router_output.json b/test/__tests__/data/sanity/marketo_router_output.json deleted file mode 100644 index 9f967074a3..0000000000 --- a/test/__tests__/data/sanity/marketo_router_output.json +++ /dev/null @@ -1,165 +0,0 @@ -[ - { - "batchedRequest": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://marketo_acct_id_success.mktorest.com/rest/v1/activities/external.json", - "headers": { - "Authorization": "Bearer access_token_success", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "input": [ - { - "activityDate": "2020-12-17T21:00:59.176Z", - "activityTypeId": 100001, - "attributes": [], - "leadId": 4, - "primaryAttributeValue": "Test Product" - } - ] - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - }, - "metadata": [ - { - "jobId": 1 - } - ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "accountId": "marketo_acct_id_success", - "clientId": "marketo_client_id_success", - "clientSecret": "marketo_client_secret_success", - "trackAnonymousEvents": true, - "customActivityEventMap": [ - { - "from": "Product Clicked", - "to": "100001" - } - ], - "customActivityPropertyMap": [ - { - "from": "name", - "to": "productName" - } - ], - "customActivityPrimaryKeyMap": [ - { - "from": "Product Clicked", - "to": "name" - } - ], - "leadTraitMapping": [ - { - "from": "leadScore", - "to": "customLeadScore" - } - ] - }, - "secretConfig": {}, - "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", - "name": "Marketo", - "enabled": true, - "workspaceId": "1TSN08muJTZwH8iCDmnnRt1pmLd", - "deleted": false, - "createdAt": "2020-12-30T08:39:32.005Z", - "updatedAt": "2021-02-03T16:22:31.374Z", - "destinationDefinition": { - "config": { - "destConfig": { - "defaultConfig": [ - "accountId", - "clientId", - "clientSecret", - "trackAnonymousEvents", - "customActivityEventMap", - "customActivityPropertyMap", - "customActivityPrimaryKeyMap", - "leadTraitMapping" - ] - }, - "secretKeys": ["clientSecret"], - "excludeKeys": [], - "includeKeys": [], - "routerTransform": true, - "supportedSourceTypes": ["android", "ios", "web", "unity", "amp", "cloud", "reactnative"] - }, - "responseRules": { - "responseType": "JSON", - "rules": { - "retryable": [ - { - "success": "false", - "errors.0.code": 600 - }, - { - "success": "false", - "errors.0.code": 601 - }, - { - "success": "false", - "errors.0.code": 602 - }, - { - "success": "false", - "errors.0.code": 604 - }, - { - "success": "false", - "errors.0.code": 606 - }, - { - "success": "false", - "errors.0.code": 607 - }, - { - "success": "false", - "errors.0.code": 608 - }, - { - "success": "false", - "errors.0.code": 611 - } - ], - "abortable": [ - { - "success": "false", - "errors.0.code": 603 - }, - { - "success": "false", - "errors.0.code": 605 - }, - { - "success": "false", - "errors.0.code": 609 - }, - { - "success": "false", - "errors.0.code": 610 - } - ] - } - }, - "id": "1aIXqM806xAVm92nx07YwKbRrO9", - "name": "MARKETO", - "displayName": "Marketo", - "createdAt": "2020-04-09T09:24:31.794Z", - "updatedAt": "2021-01-11T11:03:28.103Z" - }, - "transformations": [], - "isConnectionEnabled": true, - "isProcessorEnabled": true - } - } -] diff --git a/test/__tests__/data/sanity/sanity_input.json b/test/__tests__/data/sanity/sanity_input.json deleted file mode 100644 index 9dd9961160..0000000000 --- a/test/__tests__/data/sanity/sanity_input.json +++ /dev/null @@ -1,185 +0,0 @@ -{ - "messages": [ - { - "type": "identify", - "event": "identify", - "sentAt": "2021-02-08T12:45:42.760Z", - "userId": "User_111", - "channel": "mobile", - "context": { - "os": { - "name": "iOS", - "version": "13.0" - }, - "app": { - "name": "MyApp", - "build": "1", - "version": "1.0", - "namespace": "com.rudderlabs.MyApp" - }, - "device": { - "id": "e2b94e2d-8327-429c-9d91-792a80d189c8", - "name": "iPhone 11 Pro Max", - "type": "iOS", - "model": "iPhone", - "manufacturer": "Apple" - }, - "locale": "en-US", - "screen": { - "width": 896, - "height": 414, - "density": 3 - }, - "traits": { - "age": 24, - "city": "Bangalore", - "name": "Manashi Mazumder", - "email": "manashi@gmail.com", - "phone": 9090909000, - "userId": "User_111", - "anonymousId": "e2b94e2d-8327-429c-9d91-792a80d189c8" - }, - "library": { - "name": "rudder-ios-library", - "version": "1.0.11" - }, - "network": { - "wifi": true, - "carrier": "unavailable", - "cellular": false, - "bluetooth": false - }, - "timezone": "Asia/Kolkata", - "userAgent": "unknown" - }, - "rudderId": "139d65bb-8a40-48c7-854c-06bbf44f686e", - "messageId": "1612788330-7e1e60a8-fb7e-437d-81c1-5b000318d0cb", - "anonymousId": "e2b94e2d-8327-429c-9d91-792a80d189c8", - "integrations": { - "All": true - }, - "originalTimestamp": "2021-02-08T12:45:30.717Z" - }, - { - "type": "identify", - "sentAt": "2021-04-15T19:43:53.393Z", - "userId": "sajal1234", - "channel": "web", - "context": { - "id": "ID101", - "ip": "0.0.0.0", - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.17", - "namespace": "com.rudderlabs.javascript" - }, - "page": { - "url": "www.rudderstack.com", - "path": "/path5", - "title": "JS Test", - "search": "My Page", - "tab_url": "https://odd-rat-19.loca.lt/Rectified.html", - "referrer": "www.google.com", - "initial_referrer": "$direct", - "referring_domain": "", - "initial_referring_domain": "" - }, - "event": "Sample Identify call", - "locale": "en-US", - "screen": { - "density": 2.75 - }, - "traits": { - "id": "ID101", - "city": "east greenwich", - "plan": "Open source", - "tags": ["x0002x", "y0004y", "t0001t"], - "email": "testkolkata@rudderlabs.com", - "event": "Sample Identify call", - "lists": [ - { - "id": 2, - "status": "unsubscribed" - }, - { - "id": 3, - "status": "unsubscribe" - } - ], - "phone": "570-690-4150", - "state": "RI", - "title": "Mr", - "logins": 5, - "mobile": "123456786", - "rating": "Hot", - "street": "19123 forest lane", - "company": { - "id": 378763009439, - "name": "Rudderlabs", - "industry": "IT", - "employee_count": 1200 - }, - "country": "USA", - "sent_at": "20210109134567", - "birthDay": "2021/04/15", - "category": "SampleIdentify", - "industry": "ITES", - "lastName": "Mohanta", - "timezone": "Berlin", - "Homephone": 9836543283, - "createdAt": "2021/04/15", - "fieldInfo": { - "state": "California", - "Address": "kolkata", - "listBox": ["Option1", "Option2"], - "CheckBox": ["Option1", "Option2", "Option3"], - "TextArea": "This is a sample text area field value . it is tested for Active Campaign. It should have more than 100 words. Lorem ipsum is a dummy sentence to fill up any area. And also , it is used to fill up dummy website. So, it is wriiten by simply wasting time. ", - "DateField": "1988-12-05", - "HiddenField": "Hidden", - "RadioButton": "Option1", - "multiChoice": "Option 1", - "DateTimeField": "2020-05-19T02:45:00-05:00" - }, - "firstName": "Sajal", - "isEnabled": true, - "timestamp": "1403743443", - "event_text": "identify", - "leadSource": "WEB", - "postalCode": "94115", - "received_at": "202101091347654", - "organizationId": 378763009439, - "original_timestamp": "1403743443" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.1.17" - }, - "sent_at": "20210109134567", - "campaign": {}, - "timestamp": "1403743443", - "userAgent": "Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86_arm Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36", - "event_text": "identify", - "externalId": [ - { - "id": "0035g000002XN5MAAW", - "type": "Salesforce-Contact" - } - ], - "received_at": "202101091347654", - "original_timestamp": "1403743443" - }, - "rudderId": "bc2402b7-6796-4fa5-9beb-bad3761fc961", - "messageId": "9d0df235-d354-4a81-8056-07dcb58081d7", - "anonymousId": "anonIDfromAndroid", - "integrations": { - "All": true - }, - "originalTimestamp": "2021-04-15T19:43:53.392Z" - } - ] -} diff --git a/test/__tests__/data/sanity/sanity_router_input.json b/test/__tests__/data/sanity/sanity_router_input.json deleted file mode 100644 index 16b8ccffad..0000000000 --- a/test/__tests__/data/sanity/sanity_router_input.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "messages": [ - { - "anonymousId": "anon_id_success", - "channel": "mobile", - "context": { - "app": { - "build": "1", - "name": "TestAppName", - "namespace": "com.android.sample", - "version": "1.0" - }, - "device": { - "id": "anon_id_success", - "manufacturer": "Google", - "model": "Android SDK built for x86", - "name": "generic_x86", - "type": "android" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.1-beta.1" - }, - "locale": "en-US", - "network": { - "carrier": "Android", - "bluetooth": false, - "cellular": true, - "wifi": true - }, - "os": { - "name": "Android", - "version": "8.1.0" - }, - "screen": { - "density": 420, - "height": 1794, - "width": 1080 - }, - "timezone": "Asia/Kolkata", - "traits": { - "anonymousId": "anon_id_success" - }, - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 8.1.0; Android SDK built for x86 Build/OSM1.180201.007)" - }, - "event": "Product Clicked", - "integrations": { - "All": true - }, - "messageId": "id1", - "properties": { - "name": "Test Product" - }, - "originalTimestamp": "2020-12-17T21:00:59.176Z", - "type": "track", - "sentAt": "2020-03-12T09:05:03.421Z" - } - ] -} diff --git a/test/__tests__/data/sfmc_output.json b/test/__tests__/data/sfmc_output.json index 0271475e4a..aaaf23aea8 100644 --- a/test/__tests__/data/sfmc_output.json +++ b/test/__tests__/data/sfmc_output.json @@ -1,6 +1,6 @@ [ { - "error": "Creating or updating contacts is disabled" + "error": "Creating or updating contacts is disabled. To enable this feature set \"Do Not Create or Update Contacts\" to false" }, [ { diff --git a/test/__tests__/data/sfmc_router_output.json b/test/__tests__/data/sfmc_router_output.json index d207b792ee..beb90b5e13 100644 --- a/test/__tests__/data/sfmc_router_output.json +++ b/test/__tests__/data/sfmc_router_output.json @@ -37,7 +37,7 @@ }, "batched": false, "statusCode": 400, - "error": "Creating or updating contacts is disabled", + "error": "Creating or updating contacts is disabled. To enable this feature set \"Do Not Create or Update Contacts\" to false", "statTags": { "errorCategory": "dataValidation", "errorType": "configuration" diff --git a/test/__tests__/facebook_conversions.js b/test/__tests__/facebook_conversions.test.js similarity index 93% rename from test/__tests__/facebook_conversions.js rename to test/__tests__/facebook_conversions.test.js index a450952efe..5bb905b5c8 100644 --- a/test/__tests__/facebook_conversions.js +++ b/test/__tests__/facebook_conversions.test.js @@ -23,6 +23,8 @@ const outputRouterDataFile = fs.readFileSync( const inputRouterData = JSON.parse(inputRouterDataFile); const expectedRouterData = JSON.parse(outputRouterDataFile); +Date.now = jest.fn(() => new Date("2023-11-12T15:46:51.000Z")); // 2023-11-12T15:46:51.693229+05:30 + describe(`${name} Tests`, () => { describe("Processor", () => { testData.forEach((dataPoint, index) => { @@ -36,7 +38,7 @@ describe(`${name} Tests`, () => { }); }); }); - + describe("Router Tests", () => { it("Payload", async () => { const routerOutput = await transformer.processRouterDest(inputRouterData); diff --git a/test/__tests__/legacyRouter.test.ts b/test/__tests__/legacyRouter.test.ts index 768db08ca8..926f6e76d4 100644 --- a/test/__tests__/legacyRouter.test.ts +++ b/test/__tests__/legacyRouter.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import path from 'path'; -import DestinationController from '../../src/controllers/destination'; +import { DestinationController } from '../../src/controllers/destination'; const destArg = process.argv.filter((x) => x.startsWith('--destName='))[0]; // send arguments on which destination const typeArg = process.argv.filter((x) => x.startsWith('--type='))[0]; // send argument on which function diff --git a/test/__tests__/marketo_static_list.test.js b/test/__tests__/marketo_static_list.test.js deleted file mode 100644 index 43300f243a..0000000000 --- a/test/__tests__/marketo_static_list.test.js +++ /dev/null @@ -1,64 +0,0 @@ -const integration = "marketo_static_list"; -const name = "marketo_static_list"; -const version = "v0"; - -const fs = require("fs"); -const path = require("path"); - -const transformer = require(`../../src/${version}/destinations/${integration}/transform`); - -// Processor Test Data -const testDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}.json`) -); -const testData = JSON.parse(testDataFile); - -// Router Test Data -const inputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_input.json`) -); -const outputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_output.json`) -); -const inputRouterData = JSON.parse(inputRouterDataFile); -const expectedRouterData = JSON.parse(outputRouterDataFile); - -// Router Metadata Test files -const inputRouterMetadataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_metadata_input.json`) -); -const outputRouterMetadataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_metadata_output.json`) -); -const inputRouterMetadata = JSON.parse(inputRouterMetadataFile); -const expectedRouterMetadata = JSON.parse(outputRouterMetadataFile); - -describe(`${name} Tests`, () => { - describe("Processor", () => { - testData.forEach((dataPoint, index) => { - it(`${index}. ${integration} - ${dataPoint.description}`, async () => { - try { - const output = await transformer.process(dataPoint.input); - expect(output).toEqual(dataPoint.output); - } catch (error) { - expect(error.message).toEqual(dataPoint.output.error); - } - }); - }); - }); - - describe("Router Tests", () => { - it("Payload", async () => { - const routerOutput = await transformer.processRouterDest(inputRouterData); - expect(routerOutput).toEqual(expectedRouterData); - }); - }); - describe("Router Metadata Tests", () => { - it("Payload", async () => { - const routerMetadataOutput = await transformer.processMetadataForRouter( - inputRouterMetadata - ); - expect(routerMetadataOutput).toEqual(expectedRouterMetadata); - }); - }); -}); diff --git a/test/__tests__/sanity.test.js b/test/__tests__/sanity.test.js deleted file mode 100644 index ae5faa917c..0000000000 --- a/test/__tests__/sanity.test.js +++ /dev/null @@ -1,204 +0,0 @@ -jest.mock("axios"); -const name = "Sanity"; -const fs = require("fs"); -const path = require("path"); -const version = "v0"; -const { getDirectories } = require("./util"); -const { mockaxios } = require("../__mocks__/network"); - -// ******************************** -// Getting Started -// ******************************** -// sanity-folder-structure -// __tests__ -// | -// |--sanity.test.js -// |--data -// | | -// | |--sanity -// | | -// | {integration(s)}_output.json -// | {integration(s)}_router_output.json -// | sanity_input.json -// | sanity_router_input.json -// | destination_config.json - -// ------ destination_config.json ------ -// JSON to store the destination-config of all the destinations -// Each destination-config object has a config object storing the -// processor/ router (transform-at) configs -// ------------------------------------- -// If transformation is only done at processor -// only use the processor as key and store the -// destination definition as value. -// -// Format : -// { -// "clevertap": { -// "config": { -// "processor": { ...destination_definition }, -// "router": { ...destination_definition } -// } -// } -// .. -// .. -// } - -// ----- sanity_input.json ----- -// JSON to store the sanity input messages which will be -// used to test sanity for all the destination. -// -// Format: -// { -// "messages": [ -// { sanity_input_message_1}, -// { sanity_input_message_2}, -// { sanity_input_message_3} -// ... -// ] -// } - -// ----- sanity_router_input.json ----- -// JSON to store the sanity input messages which will be -// used to test sanity for all the destination. -// These inputs will be used for testing router -// transformation for all destination which support it. -// -// Format: -// { -// "messages": [ -// { router_sanity_input_message_1}, -// { router_sanity_input_message_2}, -// { router_sanity_input_message_3} -// ... -// ] -// } - -// ------ {integration(s)}_output.json ------ -// These are specific output for each of the destinations -// given the sanity input. We are using jest result matcher -// to check if the output is matching with the expected output. -// Example clevertap_output.json -// Format: -// [ -// {sanity_output_for_message_1}, -// {sanity_output_for_message_2}, -// .. -// ] - -// ------ {integration(s)}_router_output.json ------ -// These are specific output for each of the destinations -// given the router sanity input. -// ** CHECK IF THE PARTICULAR DESTINATION SUPPORTS ROUTER TRANSFORMATION ** -// Example clevertap_router_output.json -// Format: -// [ -// {router_sanity_output_for_message_1}, -// {router_sanity_output_for_message_2}, -// .. -// ] - -// Parsing all the destination names from /v0/destinations dir structure -// parsing it into an array of string. This keeping the destinations to test -// dynamic. -// const integrations = getDirectories( -// path.resolve(__dirname, `../${version}/destinations/`) -// ); -// For Testing Current: -// Uncomment this Line and comment the above 3 lines -const integrations = ["marketo"]; - -// Parsing the sanity input JSON which will be used for testing each destination -const processorSanityInput = JSON.parse( - fs.readFileSync(path.resolve(__dirname, `./data/sanity/sanity_input.json`)) -); - -// Parsing the sanity router input JSON which will be used for testing each destination -// which support it -const routerSanityInputRouter = JSON.parse( - fs.readFileSync( - path.resolve(__dirname, `./data/sanity/sanity_router_input.json`) - ) -); -// Parsing the destination config JSON from which we will get the destination definitions -// along with if the destination supports router-transformation -const destinationConfig = JSON.parse( - fs.readFileSync( - path.resolve(__dirname, `./data/sanity/destination_config.json`) - ) -); - -// Iterating each of the destinations -integrations.forEach(intg => { - // Getting the transformation object - const transformer = require(`../../src/${version}/destinations/${intg}/transform`); - // Getting the config for this particular destination - const { config } = destinationConfig[`${intg}`]; - // Where the ransformation is done at (processor, router ..) - Object.keys(config).forEach(processAt => { - // Depending on the case - switch (processAt) { - case "processor": - { - // Parsing the expected data for this particular destination - const expectedData = JSON.parse( - fs.readFileSync( - path.resolve(__dirname, `./data/sanity/${intg}_output.json`) - ) - ); - // For each of the messages we are processing using the transformer - processorSanityInput.messages.forEach((message, index) => { - // Building the event object with specified destination-definition - const event = { - message, - destination: config[`${processAt}`] - }; - // Sending the event to transformer and matching the result with expected output - it(`${name} - integration[Processor]: ${intg} payload:${index}`, async () => { - try { - const output = await transformer.process(event); - expect(output).toEqual(expectedData[index]); - } catch (error) { - expect(error.message).toEqual(expectedData[index].error); - } - }); - }); - } - break; - - case "router": - { - // Parsing the expected router output data for this particular destination - const expectedData = JSON.parse( - fs.readFileSync( - path.resolve( - __dirname, - `./data/sanity/${intg}_router_output.json` - ) - ) - ); - // For each of the messages we are processing using the router transformer - routerSanityInputRouter.messages.forEach((message, index) => { - // Building the event object with specified destination-definition - const events = [ - { - message, - metadata: { - jobId: 1 - }, - destination: config[`${processAt}`] - } - ]; - // Sending the event to router transformer of this destinationand matching the result with expected output - it(`${name} - integration(Router): ${intg} payload:${index}`, async () => { - const routerOutput = await transformer.processRouterDest(events); - expect(routerOutput[0]).toEqual(expectedData[index]); - }); - }); - } - break; - default: - throw new Error("Undefined Transform-At Config"); - } - }); -}); diff --git a/test/__tests__/user_transformation_ts.test.ts b/test/__tests__/user_transformation_ts.test.ts index 418c42fe33..971476e513 100644 --- a/test/__tests__/user_transformation_ts.test.ts +++ b/test/__tests__/user_transformation_ts.test.ts @@ -1,5 +1,5 @@ import fetch from 'node-fetch'; -import UserTransformService from '../../src/services/userTransform'; +import { UserTransformService } from '../../src/services/userTransform'; import { FeatureFlags, FEATURE_FILTER_CODE } from '../../src/middlewares/featureFlag'; jest.mock('node-fetch', () => jest.fn()); diff --git a/test/apitests/data_scenarios/cdk_v2/failure.json b/test/apitests/data_scenarios/cdk_v2/failure.json index f39d351b2d..1635a3f0db 100644 --- a/test/apitests/data_scenarios/cdk_v2/failure.json +++ b/test/apitests/data_scenarios/cdk_v2/failure.json @@ -646,7 +646,8 @@ "statusCode": 400, "error": "Action source must be one of app_android, app_ios, web, offline: Workflow: procWorkflow, Step: validateCommonFields, ChildStep: undefined, OriginalError: Action source must be one of app_android, app_ios, web, offline", "statTags": { - "errorCategory": "platform", + "errorCategory": "dataValidation", + "errorType": "instrumentation", "implementation": "cdkV2", "destType": "PINTEREST_TAG", "module": "destination", diff --git a/test/apitests/data_scenarios/source/failure.json b/test/apitests/data_scenarios/source/v0/failure.json similarity index 100% rename from test/apitests/data_scenarios/source/failure.json rename to test/apitests/data_scenarios/source/v0/failure.json diff --git a/test/apitests/data_scenarios/source/response_to_caller.json b/test/apitests/data_scenarios/source/v0/response_to_caller.json similarity index 100% rename from test/apitests/data_scenarios/source/response_to_caller.json rename to test/apitests/data_scenarios/source/v0/response_to_caller.json diff --git a/test/apitests/data_scenarios/source/successful.json b/test/apitests/data_scenarios/source/v0/successful.json similarity index 100% rename from test/apitests/data_scenarios/source/successful.json rename to test/apitests/data_scenarios/source/v0/successful.json diff --git a/test/apitests/data_scenarios/source/v1/failure.json b/test/apitests/data_scenarios/source/v1/failure.json new file mode 100644 index 0000000000..9bf77f9b53 --- /dev/null +++ b/test/apitests/data_scenarios/source/v1/failure.json @@ -0,0 +1,27 @@ +{ + "input": [ + { + "event": { + "anonymousId": "63767499ca6fb1b7c988d5bb", + "artist": "Gautam", + "genre": "Jazz", + "song": "Take Five" + }, + "source": { + "id": "source_id", + "config": { + "configField1": "configVal1" + } + } + } + ], + "output": [ + { + "statusCode": 500, + "error": "Cannot find module '../undefined/sources/NA_SOURCE/transform' from 'src/services/misc.ts'", + "statTags": { + "errorCategory": "transformation" + } + } + ] +} diff --git a/test/apitests/data_scenarios/source/v1/pipedream.json b/test/apitests/data_scenarios/source/v1/pipedream.json new file mode 100644 index 0000000000..1496471066 --- /dev/null +++ b/test/apitests/data_scenarios/source/v1/pipedream.json @@ -0,0 +1,49 @@ +{ + "input": [ + { + "event": { + "anonymousId": "63767499ca6fb1b7c988d5bb", + "artist": "Gautam", + "genre": "Jazz", + "song": "Take Five" + }, + "source": { + "id": "source_id", + "config": { + "configField1": "configVal1" + } + } + } + ], + "output": [ + { + "output": { + "batch": [ + { + "event": "pipedream_source_event", + "anonymousId": "63767499ca6fb1b7c988d5bb", + "context": { + "integration": { + "name": "PIPEDREAM" + }, + "library": { + "name": "unknown", + "version": "unknown" + } + }, + "integrations": { + "PIPEDREAM": false + }, + "type": "track", + "properties": { + "anonymousId": "63767499ca6fb1b7c988d5bb", + "artist": "Gautam", + "genre": "Jazz", + "song": "Take Five" + } + } + ] + } + } + ] +} diff --git a/test/apitests/data_scenarios/source/v1/successful.json b/test/apitests/data_scenarios/source/v1/successful.json new file mode 100644 index 0000000000..c42d723800 --- /dev/null +++ b/test/apitests/data_scenarios/source/v1/successful.json @@ -0,0 +1,38 @@ +{ + "input": [ + { + "event": { + "event": "Fulfillments Update", + "data": { + "fulfillment_id": "1234567890", + "status": "pending" + } + }, + "source": { + "id": "source_id", + "config": { + "configField1": "configVal1" + } + } + } + ], + "output": [ + { + "output": { + "batch": [ + { + "type": "track", + "event": "webhook_source_event", + "properties": { + "event": "Fulfillments Update", + "data": { + "fulfillment_id": "1234567890", + "status": "pending" + } + } + } + ] + } + } + ] +} diff --git a/test/apitests/service.api.test.ts b/test/apitests/service.api.test.ts index dfe7e10dd6..ee534d7b37 100644 --- a/test/apitests/service.api.test.ts +++ b/test/apitests/service.api.test.ts @@ -177,7 +177,7 @@ describe('Destination api tests', () => { describe('Source api tests', () => { test('(shopify) successful source transform', async () => { - const data = getDataFromPath('./data_scenarios/source/successful.json'); + const data = getDataFromPath('./data_scenarios/source/v0/successful.json'); const response = await request(server) .post('/v0/sources/shopify') .set('Accept', 'application/json') @@ -189,7 +189,7 @@ describe('Source api tests', () => { }); test('(shopify) failure source transform (shopify)', async () => { - const data = getDataFromPath('./data_scenarios/source/failure.json'); + const data = getDataFromPath('./data_scenarios/source/v0/failure.json'); const response = await request(server) .post('/v0/sources/shopify') .set('Accept', 'application/json') @@ -199,7 +199,7 @@ describe('Source api tests', () => { }); test('(shopify) success source transform (monday)', async () => { - const data = getDataFromPath('./data_scenarios/source/response_to_caller.json'); + const data = getDataFromPath('./data_scenarios/source/v0/response_to_caller.json'); const response = await request(server) .post('/v0/sources/monday') .set('Accept', 'application/json') @@ -207,6 +207,38 @@ describe('Source api tests', () => { expect(response.status).toEqual(200); expect(JSON.parse(response.text)).toEqual(data.output); }); + + test('(webhook) successful source transform for source present in v1 and server providing v0 endpoint', async () => { + const data = getDataFromPath('./data_scenarios/source/v1/successful.json'); + const response = await request(server) + .post('/v1/sources/webhook') + .set('Accept', 'application/json') + .send(data.input); + const parsedResp = JSON.parse(response.text); + delete parsedResp[0].output.batch[0].anonymousId; + expect(response.status).toEqual(200); + expect(parsedResp).toEqual(data.output); + }); + + test('(NA_SOURCE) failure source transform ', async () => { + const data = getDataFromPath('./data_scenarios/source/v1/failure.json'); + const response = await request(server) + .post('/v0/sources/NA_SOURCE') + .set('Accept', 'application/json') + .send(data.input); + expect(response.status).toEqual(200); + expect(JSON.parse(response.text)).toEqual(data.output); + }); + + test('(pipedream) success source transform for source present in v0 and server providing v1 endpoint', async () => { + const data = getDataFromPath('./data_scenarios/source/v1/pipedream.json'); + const response = await request(server) + .post('/v1/sources/pipedream') + .set('Accept', 'application/json') + .send(data.input); + expect(response.status).toEqual(200); + expect(JSON.parse(response.text)).toEqual(data.output); + }); }); describe('CDK V1 api tests', () => { diff --git a/test/controllerUtility/ctrl-utility.test.ts b/test/controllerUtility/ctrl-utility.test.ts index c3a668d7e7..bf9eef1846 100644 --- a/test/controllerUtility/ctrl-utility.test.ts +++ b/test/controllerUtility/ctrl-utility.test.ts @@ -1,5 +1,5 @@ import { ProcessorTransformationRequest, RouterTransformationRequestData } from '../../src/types'; -import ControllerUtility from '../../src/controllers/util'; +import { ControllerUtility } from '../../src/controllers/util'; type timestampTestCases = { caseName: string; diff --git a/test/integrations/destinations/active_campaign/processor/data.ts b/test/integrations/destinations/active_campaign/processor/data.ts index 09499a9eee..cef8c2a3a8 100644 --- a/test/integrations/destinations/active_campaign/processor/data.ts +++ b/test/integrations/destinations/active_campaign/processor/data.ts @@ -1,3 +1,6 @@ +import MockAdapter from 'axios-mock-adapter'; +import { isMatch } from 'lodash'; + export const data = [ { name: 'active_campaign', @@ -765,4 +768,389 @@ export const data = [ }, }, }, + + { + name: 'active_campaign', + description: + 'Test 7: node error(ECONNABORTED) where there is no response coming from dest. server', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'dummyApiKey', + apiUrl: 'https://active.campaigns.dumber.com', + actid: '476550467', + eventKey: 'f8a866fddc721350fdc2fbbd2e5c43a6dddaaa03', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { name: '', version: '' }, + screen: { density: 2 }, + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: 'anon_id', + userId: '123456', + type: 'identify', + traits: { + anonymousId: 'anon_id', + email: 'patjane@gmail.com', + phone: '92374162213', + tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + fieldInfo: { + Office: 'Trastkiv', + Country: 'Russia', + Likes: ['Potato', 'Onion'], + Random: 'random', + }, + lists: [ + { id: 2, status: 'subscribe' }, + { id: 3, status: 'unsubscribe' }, + { id: 3, status: 'unsubscribexyz' }, + ], + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + integrations: { All: true }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + '{"message":"Failed to create new contact (undefined,\\"[ECONNABORTED] :: Connection aborted\\")","destinationResponse":"[ECONNABORTED] :: Connection aborted"}', + statTags: { + destType: 'ACTIVE_CAMPAIGN', + errorCategory: 'network', + errorType: 'retryable', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 500, + }, + ], + }, + }, + mockFns: (mockAdapter: MockAdapter) => { + mockAdapter + .onPost( + 'https://active.campaigns.dumber.com/api/3/contact/sync', + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + contact: { + email: 'patjane@gmail.com', + phone: '92374162213', + }, + }); + }, + }, + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + 'Api-Token': 'dummyApiKey', + 'Content-Type': 'application/json', + }); + }, + }, + ) + .abortRequest(); + }, + }, + { + name: 'active_campaign', + description: 'Test 8: erreneous response from active_campaign server(5xx)', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'dummyApiKey', + apiUrl: 'https://active.campaigns.dumber2.com', + actid: '476550467', + eventKey: 'f8a866fddc721350fdc2fbbd2e5c43a6dddaaa03', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { name: '', version: '' }, + screen: { density: 2 }, + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: 'anon_id', + userId: '123456', + type: 'identify', + traits: { + anonymousId: 'anon_id', + email: 'patjane1@gmail.com', + phone: '92374162213', + tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + fieldInfo: { + Office: 'Trastkiv', + Country: 'Russia', + Likes: ['Potato', 'Onion'], + Random: 'random', + }, + lists: [ + { id: 2, status: 'subscribe' }, + { id: 3, status: 'unsubscribe' }, + { id: 3, status: 'unsubscribexyz' }, + ], + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + integrations: { All: true }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + '{"message":"Failed to create new contact (undefined,\\"\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n \\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\naccurx.api-us1.com | 504: Gateway time-out\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n

\\\\\\\\n Gateway time-out\\\\\\\\n Error code 504\\\\\\\\n

\\\\\\\\n
\\\\\\\\n Visit cloudflare.com for more information.\\\\\\\\n
\\\\\\\\n
2023-12-06 10:33:27 UTC
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n \\\\\\\\n
\\\\\\\\n
\\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n
\\\\\\\\n You\\\\\\\\n

\\\\\\\\n \\\\\\\\n Browser\\\\\\\\n \\\\\\\\n

\\\\\\\\n Working\\\\\\\\n
\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n
\\\\\\\\n Frankfurt\\\\\\\\n

\\\\\\\\n \\\\\\\\n Cloudflare\\\\\\\\n \\\\\\\\n

\\\\\\\\n Working\\\\\\\\n
\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n \\\\\\\\n
\\\\\\\\n accurx.api-us1.com\\\\\\\\n

\\\\\\\\n \\\\\\\\n Host\\\\\\\\n \\\\\\\\n

\\\\\\\\n Error\\\\\\\\n
\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n

What happened?

\\\\\\\\n

The web server reported a gateway time-out error.

\\\\\\\\n
\\\\\\\\n
\\\\\\\\n

What can I do?

\\\\\\\\n

Please try again in a few minutes.

\\\\\\\\n
\\\\\\\\n
\\\\\\\\n
\\\\\\\\n\\\\\\\\n \\\\\\\\n\\\\\\\\n\\\\\\\\n
\\\\\\\\n
\\\\\\\\n\\\\\\\\n\\\\\\\\n\\\\\\")\\")","destinationResponse":"\\\\n\\\\n\\\\n\\\\n \\\\n\\\\n\\\\n\\\\naccurx.api-us1.com | 504: Gateway time-out\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n
\\\\n
\\\\n
\\\\n

\\\\n Gateway time-out\\\\n Error code 504\\\\n

\\\\n
\\\\n Visit cloudflare.com for more information.\\\\n
\\\\n
2023-12-06 10:33:27 UTC
\\\\n
\\\\n
\\\\n
\\\\n
\\\\n \\\\n
\\\\n
\\\\n \\\\n \\\\n \\\\n \\\\n
\\\\n You\\\\n

\\\\n \\\\n Browser\\\\n \\\\n

\\\\n Working\\\\n
\\\\n\\\\n
\\\\n
\\\\n \\\\n \\\\n \\\\n \\\\n
\\\\n Frankfurt\\\\n

\\\\n \\\\n Cloudflare\\\\n \\\\n

\\\\n Working\\\\n
\\\\n\\\\n
\\\\n
\\\\n \\\\n \\\\n \\\\n \\\\n
\\\\n accurx.api-us1.com\\\\n

\\\\n \\\\n Host\\\\n \\\\n

\\\\n Error\\\\n
\\\\n\\\\n
\\\\n
\\\\n
\\\\n\\\\n
\\\\n
\\\\n
\\\\n

What happened?

\\\\n

The web server reported a gateway time-out error.

\\\\n
\\\\n
\\\\n

What can I do?

\\\\n

Please try again in a few minutes.

\\\\n
\\\\n
\\\\n
\\\\n\\\\n \\\\n\\\\n\\\\n
\\\\n
\\\\n\\\\n\\\\n\\")"}', + statTags: { + destType: 'ACTIVE_CAMPAIGN', + errorCategory: 'network', + errorType: 'retryable', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 504, + }, + ], + }, + }, + mockFns: (mockAdapter: MockAdapter) => { + mockAdapter + .onPost( + 'https://active.campaigns.dumber2.com/api/3/contact/sync', + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + contact: { + email: 'patjane1@gmail.com', + phone: '92374162213', + }, + }); + }, + }, + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + 'Api-Token': 'dummyApiKey', + 'Content-Type': 'application/json', + }); + }, + }, + ) + .replyOnce( + 504, + '\\n\\n\\n\\n \\n\\n\\n\\naccurx.api-us1.com | 504: Gateway time-out\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n
\\n
\\n
\\n

\\n Gateway time-out\\n Error code 504\\n

\\n
\\n Visit cloudflare.com for more information.\\n
\\n
2023-12-06 10:33:27 UTC
\\n
\\n
\\n
\\n
\\n \\n
\\n
\\n \\n \\n \\n \\n
\\n You\\n

\\n \\n Browser\\n \\n

\\n Working\\n
\\n\\n
\\n
\\n \\n \\n \\n \\n
\\n Frankfurt\\n

\\n \\n Cloudflare\\n \\n

\\n Working\\n
\\n\\n
\\n
\\n \\n \\n \\n \\n
\\n accurx.api-us1.com\\n

\\n \\n Host\\n \\n

\\n Error\\n
\\n\\n
\\n
\\n
\\n\\n
\\n
\\n
\\n

What happened?

\\n

The web server reported a gateway time-out error.

\\n
\\n
\\n

What can I do?

\\n

Please try again in a few minutes.

\\n
\\n
\\n
\\n\\n \\n\\n\\n
\\n
\\n\\n\\n")', + { + Accept: 'application/json, text/plain, */*', + 'Api-Token': 'dummyApiKey', + }, + ); + }, + }, + { + name: 'active_campaign', + description: 'Test 9: erreneous response from active_campaign server(4xx)', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'dummyApiKey', + apiUrl: 'https://active.campaigns.dumber2.com', + actid: '476550467', + eventKey: 'f8a866fddc721350fdc2fbbd2e5c43a6dddaaa03', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.0.0' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { name: '', version: '' }, + screen: { density: 2 }, + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: 'anon_id', + userId: '123456', + type: 'identify', + traits: { + anonymousId: 'anon_id', + email: 'patjane2@gmail.com', + phone: '92374162213', + tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + fieldInfo: { + Office: 'Trastkiv', + Country: 'Russia', + Likes: ['Potato', 'Onion'], + Random: 'random', + }, + lists: [ + { id: 2, status: 'subscribe' }, + { id: 3, status: 'unsubscribe' }, + { id: 3, status: 'unsubscribexyz' }, + ], + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + integrations: { All: true }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + '{"message":"Failed to create new contact (undefined,{\\"errors\\":[{\\"title\\":\\"Contact Email Address is not valid.\\",\\"detail\\":\\"\\",\\"code\\":\\"email_invalid\\",\\"error\\":\\"must_be_valid_email_address\\",\\"source\\":{\\"pointer\\":\\"/data/attributes/email\\"}}]})","destinationResponse":{"errors":[{"title":"Contact Email Address is not valid.","detail":"","code":"email_invalid","error":"must_be_valid_email_address","source":{"pointer":"/data/attributes/email"}}]}}', + statTags: { + destType: 'ACTIVE_CAMPAIGN', + errorCategory: 'network', + errorType: 'aborted', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 422, + }, + ], + }, + }, + mockFns: (mockAdapter: MockAdapter) => { + mockAdapter + .onPost( + 'https://active.campaigns.dumber2.com/api/3/contact/sync', + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + contact: { + email: 'patjane2@gmail.com', + phone: '92374162213', + }, + }); + }, + }, + { + asymmetricMatch: (actual) => { + return isMatch(actual, { + 'Api-Token': 'dummyApiKey', + 'Content-Type': 'application/json', + }); + }, + }, + ) + .replyOnce( + 422, + { + errors: [ + { + title: 'Contact Email Address is not valid.', + detail: '', + code: 'email_invalid', + error: 'must_be_valid_email_address', + source: { + pointer: '/data/attributes/email', + }, + }, + ], + }, + { + Accept: 'application/json, text/plain, */*', + 'Api-Token': 'dummyApiKey', + }, + ); + }, + }, ]; diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts new file mode 100644 index 0000000000..182969da73 --- /dev/null +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -0,0 +1,142 @@ +export const data = [ + { + name: 'adobe_analytics', + description: 'Test 0: Failure response from Adobe Analytics with reason', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.failure.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReport', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'ADOBE_ANALYTICS', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: '2S3s0dXXXXXX7m0UfBwyblDrzs', + workspaceId: '1pKWrE6GXXXXXKBikka1SbRgrSN', + }, + destinationResponse: '', + authErrorCategory: '', + message: + '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics : NO pagename OR pageurl', + }, + }, + }, + { + name: 'adobe_analytics', + description: 'Test 1: Failure response from Adobe Analytics without reason (Generic error)', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.failure2.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReportgeneric', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'ADOBE_ANALYTICS', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: '2S3s0dXXXXXX7m0UfBwyblDrzs', + workspaceId: '1pKWrE6GXXXXXKBikka1SbRgrSN', + }, + destinationResponse: '', + authErrorCategory: '', + message: + '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics with a general error', + }, + }, + }, + { + name: 'adobe_analytics', + description: 'Test 2: Success response from Adobe Analytics', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.success.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '127.0.1.0www.google.co.inGoogleid1110011prodViewGames;Monopoly;1;14.00,Games;UNO;2;6.90successreport', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + destinationResponse: 'SUCCESS', + }, + }, + }, +]; diff --git a/test/integrations/destinations/adobe_analytics/network.ts b/test/integrations/destinations/adobe_analytics/network.ts new file mode 100644 index 0000000000..2fe4f0204e --- /dev/null +++ b/test/integrations/destinations/adobe_analytics/network.ts @@ -0,0 +1,47 @@ +export const networkCallsData = [ + { + httpReq: { + url: 'https://adobe.failure.omtrdc.net/b/ss//6', + data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReport', + params: {}, + headers: { + 'Content-Type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 200, + data: 'FAILURENO pagename OR pageurl', + }, + }, + { + httpReq: { + url: 'https://adobe.failure2.omtrdc.net/b/ss//6', + data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReportgeneric', + params: {}, + headers: { + 'Content-Type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 200, + data: 'FAILURE', + }, + }, + { + httpReq: { + url: 'https://adobe.success.omtrdc.net/b/ss//6', + data: '127.0.1.0www.google.co.inGoogleid1110011prodViewGames;Monopoly;1;14.00,Games;UNO;2;6.90successreport', + params: {}, + headers: { + 'Content-Type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 200, + data: 'SUCCESS', + }, + }, +]; diff --git a/test/integrations/destinations/adobe_analytics/processor/data.ts b/test/integrations/destinations/adobe_analytics/processor/data.ts index 378523ac3c..fa050897c9 100644 --- a/test/integrations/destinations/adobe_analytics/processor/data.ts +++ b/test/integrations/destinations/adobe_analytics/processor/data.ts @@ -1,7 +1,7 @@ export const data = [ { name: 'adobe_analytics', - description: 'Test 0', + description: 'Test 0: [ECom]: Product Viewed', feature: 'processor', module: 'destination', version: 'v0', @@ -31,7 +31,7 @@ export const data = [ referring_domain: 'google.com', search: 'estore bestseller', title: 'The best sellers offered by EStore', - url: 'https://www.estore.com/best-seller/1', + url: 'https://www.estore.com/best-seller/News & Sports?ik=123&ij=456', name: 'Best Seller', }, screen: { @@ -61,7 +61,7 @@ export const data = [ coupon: 'DISC21', currency: 'USD', position: 1, - url: 'https://www.website.com/product/path', + url: 'https://www.website.com/product/path?ik=123&ij=456', image_url: 'https://www.website.com/product/path.png', currencyMerch: 25, addressMerch: 'Delhi', @@ -170,7 +170,7 @@ export const data = [ JSON_ARRAY: {}, XML: { payload: - '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellert01t02roottval001Kolkata9935400932RudderLabs JavaScript SDKr15,faze90Rciaz,hummer,tharhttps://www.estore.com/best-seller/1Best Sellercustompropval1custompropval22020-01-09T10:01:53.558Zmktcloudid001prodViewGames;Game;11;148.39footlockerrudderstackpoc', + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellert01t02roottval001Kolkata9935400932RudderLabs JavaScript SDKr15,faze90Rciaz,hummer,tharhttps://www.estore.com/best-seller/News%20&%20Sports?ik=123&ij=456Best Sellercustompropval1custompropval22020-01-09T10:01:53.558Zmktcloudid001prodViewGames;Game;11;148.39footlockerrudderstackpoc', }, FORM: {}, }, @@ -185,7 +185,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 1', + description: 'Test 1: [ECom]: Product Added', feature: 'processor', module: 'destination', version: 'v0', @@ -356,7 +356,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 2', + description: 'Test 2: [ECom]: Product Removed', feature: 'processor', module: 'destination', version: 'v0', @@ -527,7 +527,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 3', + description: 'Test 3: [ECom]: Cart Viewed', feature: 'processor', module: 'destination', version: 'v0', @@ -708,7 +708,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 4', + description: 'Test 4: [ECom]: Checkout started', feature: 'processor', module: 'destination', version: 'v0', @@ -896,7 +896,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 5', + description: 'Test 5: [ECom]: Order Completed', feature: 'processor', module: 'destination', version: 'v0', @@ -1085,7 +1085,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 6', + description: 'Test 6: Cart Opened', feature: 'processor', module: 'destination', version: 'v0', @@ -1265,7 +1265,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 7', + description: 'Test 7: [Custom] Watched Video', feature: 'processor', module: 'destination', version: 'v0', @@ -1285,7 +1285,7 @@ export const data = [ term: 'event data', content: 'Make sense of the modern data stack', }, - library: { name: 'RudderLabs JavaScript SDK', version: '2.9.1' }, + library: { name: 'RudderLabs JavaScript SDK ', version: '2.9.1' }, locale: 'en-US', page: { path: '/best-seller/1', @@ -1311,7 +1311,7 @@ export const data = [ traits: { roott01: 'roottval001' }, event: 'Watched Video', integrations: { All: true }, - properties: { plan: 'growth', video: 'TEDxGROWTH' }, + properties: { plan: 'growth', video: 'TEDxGROWTH&MARKETING' }, originalTimestamp: '2020-01-09T10:01:53.558Z', type: 'track', sentAt: '2020-01-09T10:02:03.257Z', @@ -1412,7 +1412,7 @@ export const data = [ JSON_ARRAY: {}, XML: { payload: - '17941080sales campaignweb127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerroottval001RudderLabs JavaScript SDKTEDxGROWTHoWatched Videohttps://www.estore.com/best-seller/1growth2020-01-09T10:01:53.558Zmktcloudid001event1footlockerrudderstackpoc', + '17941080sales campaignweb127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerroottval001RudderLabs JavaScript SDK <Custom>TEDxGROWTH&MARKETINGoWatched Videohttps://www.estore.com/best-seller/1growth2020-01-09T10:01:53.558Zmktcloudid001event1footlockerrudderstackpoc', }, FORM: {}, }, @@ -1427,7 +1427,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 8', + description: 'Test 8: Common Page Call', feature: 'processor', module: 'destination', version: 'v0', @@ -1597,7 +1597,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 9', + description: 'Test 9: Currency test event', feature: 'processor', module: 'destination', version: 'v0', @@ -1789,7 +1789,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 10', + description: 'Test 10: Override feature test', feature: 'processor', module: 'destination', version: 'v0', @@ -1988,7 +1988,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 11', + description: 'Test 11: Override hiers test', feature: 'processor', module: 'destination', version: 'v0', @@ -2188,7 +2188,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 12', + description: 'Test 12: product level eVaR', feature: 'processor', module: 'destination', version: 'v0', @@ -2390,7 +2390,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 13', + description: 'Test 13: [ERROR]: Invalid message type: Identify', feature: 'processor', module: 'destination', version: 'v0', @@ -2523,7 +2523,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 14', + description: 'Test 14: [ERROR]: Message Type is not present.', feature: 'processor', module: 'destination', version: 'v0', @@ -2697,7 +2697,8 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 15', + description: + 'Test 15: [ERROR]: The event is not a supported ECOM event or a mapped custom event.', feature: 'processor', module: 'destination', version: 'v0', @@ -2872,7 +2873,7 @@ export const data = [ }, { name: 'adobe_analytics', - description: 'Test 16', + description: 'Test 16: Test overrideEventName property', feature: 'processor', module: 'destination', version: 'v0', @@ -3056,4 +3057,49 @@ export const data = [ }, }, }, + { + name: 'adobe_analytics', + description: 'Test 17: Event is missing for track', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '78c53c15-32a1-4b65-adac-bec2d7bb8fab', + channel: 'web', + originalTimestamp: '2020-01-09T10:01:53.558Z', + type: 'track', + sentAt: '2020-01-09T10:02:03.257Z', + }, + destination: { + Config: {}, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: 'Event name is not present. Aborting message.', + statTags: { + destType: 'ADOBE_ANALYTICS', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/algolia/processor/data.ts b/test/integrations/destinations/algolia/processor/data.ts index f5c01e47e5..0cbdd8b31b 100644 --- a/test/integrations/destinations/algolia/processor/data.ts +++ b/test/integrations/destinations/algolia/processor/data.ts @@ -66,6 +66,13 @@ export const data = [ sentAt: '2019-10-14T09:03:22.563Z', }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -77,6 +84,10 @@ export const data = [ ], }, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -116,6 +127,10 @@ export const data = [ version: '1', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -197,7 +212,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -250,6 +276,10 @@ export const data = [ version: '1', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -322,7 +352,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -338,16 +379,23 @@ export const data = [ status: 200, body: [ { - error: 'Either filters or objectIds is required.', + error: + 'Either filters or objectIds is required.: Workflow: procWorkflow, Step: validateDestPayload, ChildStep: undefined, OriginalError: Either filters or objectIds is required.', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -419,7 +467,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -435,16 +494,23 @@ export const data = [ status: 200, body: [ { - error: 'eventType is mandatory for track call', + error: + 'eventType is mandatory for track call: Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: eventType is mandatory for track call', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -526,7 +592,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -548,16 +625,22 @@ export const data = [ body: [ { error: - 'for click eventType either both positions and queryId should be present or none', + 'for click eventType either both positions and queryId should be present or none: Workflow: procWorkflow, Step: validatePayloadForClickEvent, ChildStep: undefined, OriginalError: for click eventType either both positions and queryId should be present or none', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -639,7 +722,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -691,6 +785,10 @@ export const data = [ version: '1', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -772,7 +870,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -794,16 +903,22 @@ export const data = [ body: [ { error: - 'for click eventType either both positions and queryId should be present or none', + 'for click eventType either both positions and queryId should be present or none: Workflow: procWorkflow, Step: validatePayloadForClickEvent, ChildStep: undefined, OriginalError: for click eventType either both positions and queryId should be present or none', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -885,7 +1000,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -906,16 +1032,23 @@ export const data = [ status: 200, body: [ { - error: 'eventType can be either click, view or conversion', + error: + 'eventType can be either click, view or conversion: Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: eventType can be either click, view or conversion', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -997,7 +1130,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -1012,16 +1156,23 @@ export const data = [ status: 200, body: [ { - error: 'eventType is mandatory for track call', + error: + 'eventType is mandatory for track call: Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: eventType is mandatory for track call', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1092,7 +1243,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -1113,16 +1275,24 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "properties.index"', + error: + 'Missing required value from "properties.index": Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: Missing required value from "properties.index"', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1193,7 +1363,18 @@ export const data = [ }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + excludeKeys: [], + includeKeys: [], + }, + }, Config: { apiKey: 'dummyApiKey', applicationId: 'O2YARRI15I', @@ -1214,16 +1395,23 @@ export const data = [ status: 200, body: [ { - error: 'event name should be a string', + error: + 'event name should be a string: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: event name should be a string', statTags: { destType: 'ALGOLIA', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'native', + implementation: 'cdkV2', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, diff --git a/test/integrations/destinations/autopilot/processor/data.ts b/test/integrations/destinations/autopilot/processor/data.ts index 8ae3e28671..135e3e22f7 100644 --- a/test/integrations/destinations/autopilot/processor/data.ts +++ b/test/integrations/destinations/autopilot/processor/data.ts @@ -17,7 +17,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -85,6 +85,10 @@ export const data = [ type: 'identify', userId: 'user12345', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -123,6 +127,10 @@ export const data = [ userId: 'ac7722c2-ccb6-4ae2-baf6-1effe861f4cd', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -146,7 +154,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -219,6 +227,10 @@ export const data = [ type: 'track', userId: 'user12345', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -255,6 +267,10 @@ export const data = [ userId: 'ac7722c2-ccb6-4ae2-baf6-1effe861f4cd', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -278,7 +294,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -365,7 +381,8 @@ export const data = [ body: [ { statusCode: 400, - error: 'Bad event. Original error: message type "page" not supported for "autopilot"', + error: + 'message type page is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type page is not supported', metadata: { destinationId: 'destId', workspaceId: 'wspId', @@ -375,7 +392,7 @@ export const data = [ errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', feature: 'processor', destinationId: 'destId', workspaceId: 'wspId', @@ -403,7 +420,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -489,16 +506,18 @@ export const data = [ body: [ { statusCode: 400, - error: 'Unknown error occurred. Original error: Email is required for track calls', + error: + 'Email is required for track calls: Workflow: procWorkflow, Step: preparePayloadForTrack, ChildStep: undefined, OriginalError: Email is required for track calls', metadata: { destinationId: 'destId', workspaceId: 'wspId', }, statTags: { - errorCategory: 'transformation', + errorCategory: 'dataValidation', + errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', feature: 'processor', destinationId: 'destId', workspaceId: 'wspId', @@ -526,7 +545,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -612,16 +631,17 @@ export const data = [ { statusCode: 400, error: - 'Unknown error occurred. Original error: "type" is a required field and it must be a string', + 'message Type is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting message.', metadata: { destinationId: 'destId', workspaceId: 'wspId', }, statTags: { - errorCategory: 'transformation', + errorCategory: 'dataValidation', + errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', destinationId: 'destId', workspaceId: 'wspId', feature: 'processor', @@ -649,7 +669,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -736,7 +756,8 @@ export const data = [ body: [ { statusCode: 400, - error: 'Bad event. Original error: message type "group" not supported for "autopilot"', + error: + 'message type group is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type group is not supported', metadata: { destinationId: 'destId', workspaceId: 'wspId', @@ -746,7 +767,7 @@ export const data = [ errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', destinationId: 'destId', workspaceId: 'wspId', feature: 'processor', @@ -774,7 +795,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -906,7 +927,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -993,16 +1014,17 @@ export const data = [ { statusCode: 400, error: - 'Unknown error occurred. Original error: "type" is a required field and it must be a string', + 'message Type is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting message.', metadata: { destinationId: 'destId', workspaceId: 'wspId', }, statTags: { - errorCategory: 'transformation', + errorCategory: 'dataValidation', + errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', destinationId: 'destId', workspaceId: 'wspId', feature: 'processor', @@ -1030,7 +1052,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -1110,7 +1132,8 @@ export const data = [ body: [ { statusCode: 400, - error: 'Bad event. Original error: message type "group" not supported for "autopilot"', + error: + 'message type group is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type group is not supported', metadata: { destinationId: 'destId', workspaceId: 'wspId', @@ -1120,7 +1143,7 @@ export const data = [ errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', destinationId: 'destId', workspaceId: 'wspId', feature: 'processor', @@ -1148,7 +1171,7 @@ export const data = [ Name: 'AUTOPILOT', DisplayName: 'Autopilot', Config: { - cdkEnabled: true, + cdkV2Enabled: true, excludeKeys: [], includeKeys: [], }, @@ -1228,7 +1251,8 @@ export const data = [ body: [ { statusCode: 400, - error: 'Bad event. Original error: message type "Tals" not supported for "autopilot"', + error: + 'message type Tals is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type Tals is not supported', metadata: { destinationId: 'destId', workspaceId: 'wspId', @@ -1238,7 +1262,7 @@ export const data = [ errorType: 'instrumentation', destType: 'AUTOPILOT', module: 'destination', - implementation: 'cdkV1', + implementation: 'cdkV2', destinationId: 'destId', workspaceId: 'wspId', feature: 'processor', diff --git a/test/integrations/destinations/braze/dataDelivery/data.ts b/test/integrations/destinations/braze/dataDelivery/data.ts index 3e1805c01d..d62361e7f9 100644 --- a/test/integrations/destinations/braze/dataDelivery/data.ts +++ b/test/integrations/destinations/braze/dataDelivery/data.ts @@ -1,395 +1,391 @@ -import MockAdapter from "axios-mock-adapter"; +import MockAdapter from 'axios-mock-adapter'; export const data = [ { - "name": "braze", - "description": "Test 0", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test1", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 0', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test1', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], }, - "JSON_ARRAY": {}, - "XML": {} + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 200, - "body": { - "output": { - "status": 201, - "message": "Request for braze Processed Successfully", - "destinationResponse": { - "response": { - "aliases_processed": 1, - "message": "success" + output: { + response: { + status: 200, + body: { + output: { + status: 201, + message: 'Request for braze Processed Successfully', + destinationResponse: { + response: { + aliases_processed: 1, + message: 'success', }, - "status": 201 - } - } - } - } - } + status: 201, + }, + }, + }, + }, + }, }, { - "name": "braze", - "description": "Test 1", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test2", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 1', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test2', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], }, - "JSON_ARRAY": {}, - "XML": {} + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 200, - "body": { - "output": { - "status": 201, - "message": "Request for braze Processed Successfully", - "destinationResponse": { - "response": { - "message": "success", - "errors": [ - "minor error message" - ] + output: { + response: { + status: 200, + body: { + output: { + status: 201, + message: 'Request for braze Processed Successfully', + destinationResponse: { + response: { + message: 'success', + errors: ['minor error message'], }, - "status": 201 - } - } - } - } - } + status: 201, + }, + }, + }, + }, + }, }, { - "name": "braze", - "description": "Test 2", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test3", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 2', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test3', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], }, - "JSON_ARRAY": {}, - "XML": {} + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 200, - "body": { - "output": { - "status": 201, - "message": "Request failed for braze with status: 201", - "destinationResponse": { - "response": { - "message": "fatal error message", - "errors": [ - "minor error message" - ] + output: { + response: { + status: 200, + body: { + output: { + status: 201, + message: 'Request failed for braze with status: 201', + destinationResponse: { + response: { + message: 'fatal error message', + errors: ['minor error message'], }, - "status": 201 + status: 201, + }, + statTags: { + destType: 'BRAZE', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', }, - "statTags": { - "destType": "BRAZE", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "aborted", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } + }, + }, + }, + }, }, { - "name": "braze", - "description": "Test 3", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test4", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 3', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test4', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', + }, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 201, + message: 'Request for braze Processed Successfully', + destinationResponse: { + response: '', + status: 201, }, - "JSON_ARRAY": {}, - "XML": {} }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + }, }, - "output": { - "response": { - "status": 200, - "body": { - "output": { - "status": 201, - "message": "Request for braze Processed Successfully", - "destinationResponse": { - "response": "", - "status": 201 - } - } - } - } - } }, { - "name": "braze", - "description": "Test 4", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test5", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 4', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test5', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], }, - "JSON_ARRAY": {}, - "XML": {} + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 500, - "body": { - "output": { - "status": 500, - "message": "Request failed for braze with status: 500", - "destinationResponse": { - "response": "", - "status": 500 + output: { + response: { + status: 500, + body: { + output: { + status: 500, + message: 'Request failed for braze with status: 500', + destinationResponse: { + response: '', + status: 500, }, - "statTags": { - "destType": "BRAZE", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "retryable", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } + statTags: { + destType: 'BRAZE', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + }, + }, + }, + }, + }, }, { - "name": "braze", - "description": "Test 5", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test6", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: 'Test 5', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test6', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], }, - "JSON_ARRAY": {}, - "XML": {} + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 500, - "body": { - "output": { - "status": 500, - "message": "Request failed for braze with status: 500", - "destinationResponse": { - "response": "", - "status": 500 + output: { + response: { + status: 500, + body: { + output: { + status: 500, + message: 'Request failed for braze with status: 500', + destinationResponse: { + response: '', + status: 500, + }, + statTags: { + destType: 'BRAZE', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', }, - "statTags": { - "destType": "BRAZE", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "retryable", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } + }, + }, + }, }, mockFns: (mockAdapter: MockAdapter) => { // params has `{ destination: salesforce }` @@ -410,79 +406,437 @@ export const data = [ 'Content-Type': 'application/json', 'User-Agent': 'RudderLabs', }, - ).replyOnce((config) => { - // @ts-ignore - const err = AxiosError.from('DNS not found', 'ENOTFOUND', config) - return Promise.reject(err); + ) + .replyOnce((config) => { + // @ts-ignore + const err = AxiosError.from('DNS not found', 'ENOTFOUND', config); + return Promise.reject(err); }); - } + }, + }, + { + name: 'braze', + description: 'Test 6', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test7', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ + { + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + files: {}, + params: { + destination: 'braze', + }, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 500, + body: { + output: { + status: 500, + message: 'Request failed for braze with status: 500', + destinationResponse: { + response: '', + status: 500, + }, + statTags: { + destType: 'BRAZE', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + }, + }, + }, + }, + }, + }, + { + name: 'braze', + description: 'Test Transformer Proxy V1 input with v0 proxy handler', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/test1', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ + { + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + metadata: [ + { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + ], + files: {}, + params: { + destination: 'braze', + }, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '{"aliases_processed":1,"message":"success"}', + statusCode: 201, + metadata: { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + ], + }, + }, + }, + }, + }, + { + name: 'braze', + description: 'Test Transformer Proxy V1 input with v0 proxy handler Error returned', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/identify/testV1', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + aliases_to_identify: [ + { + external_id: 'gabi_userId_45', + user_alias: { + alias_label: 'rudder_id', + alias_name: 'gabi_anonId_45', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + metadata: [ + { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + ], + files: {}, + params: { + destination: 'braze', + }, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '{"code":400,"message":"Bad Req","status":"Fail Case"}', + statusCode: 401, + metadata: { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + ], + statTags: { + destType: 'BRAZE', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + }, + }, + }, + }, + }, }, { - "name": "braze", - "description": "Test 6", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "type": "REST", - "endpoint": "https://rest.iad-03.braze.com/users/identify/test7", - "method": "POST", - "userId": "gabi_userId_45", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer api_key", - "Content-Type": "application/json" - }, - "body": { - "FORM": {}, - "JSON": { - "aliases_to_identify": [ + name: 'braze', + description: + 'Test Transformer Proxy V1 input with v0 proxy handler Error returned Multiple metadata Track Event', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + type: 'REST', + endpoint: 'https://rest.iad-03.braze.com/users/track/testV1', + method: 'POST', + userId: 'gabi_userId_45', + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + }, + body: { + FORM: {}, + JSON: { + partner: 'RudderStack', + attributes: [ + { + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, { - "external_id": "gabi_userId_45", - "user_alias": { - "alias_label": "rudder_id", - "alias_name": "gabi_anonId_45" - } - } - ] + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, + { + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + metadata: [ + { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, }, - "JSON_ARRAY": {}, - "XML": {} + { + jobId: 3, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + { + jobId: 4, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + ], + files: {}, + params: { + destination: 'braze', }, - "files": {}, - "params": { - "destination": "braze" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 500, - "body": { - "output": { - "status": 500, - "message": "Request failed for braze with status: 500", - "destinationResponse": { - "response": "", - "status": 500 + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: + '{"message":"Valid data must be provided in the \'attributes\', \'events\', or \'purchases\' fields.","errors":[{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":0},{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":1}]}', + statusCode: 401, + metadata: { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + { + error: + '{"message":"Valid data must be provided in the \'attributes\', \'events\', or \'purchases\' fields.","errors":[{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":0},{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":1}]}', + statusCode: 401, + metadata: { + jobId: 3, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + { + error: + '{"message":"Valid data must be provided in the \'attributes\', \'events\', or \'purchases\' fields.","errors":[{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":0},{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":1}]}', + statusCode: 401, + metadata: { + jobId: 4, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + ], + statTags: { + destType: 'BRAZE', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', }, - "statTags": { - "destType": "BRAZE", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "retryable", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } - } -] \ No newline at end of file + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/braze/network.ts b/test/integrations/destinations/braze/network.ts index 1c39a247e4..3db50ca32c 100644 --- a/test/integrations/destinations/braze/network.ts +++ b/test/integrations/destinations/braze/network.ts @@ -391,5 +391,77 @@ const deleteNwData = [ }, }, }, + { + httpReq: { + url: 'https://rest.iad-03.braze.com/users/identify/testV1', + data: { + aliases_to_identify: [ + { + external_id: 'gabi_userId_45', + user_alias: { alias_label: 'rudder_id', alias_name: 'gabi_anonId_45' }, + }, + ], + }, + params: { destination: 'braze' }, + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + 'User-Agent': 'RudderLabs', + }, + method: 'POST', + }, + httpRes: { + data: { + code: 400, + message: 'Bad Req', + status: 'Fail Case', + }, + status: 401, + }, + }, + { + httpReq: { + url: 'https://rest.iad-03.braze.com/users/track/testV1', + data: { + partner: 'RudderStack', + attributes: [ + { + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, + { + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, + { + email: '123@a.com', + city: 'Disney', + country: 'USA', + firstname: 'Mickey', + external_id: '456345345', + }, + ], + }, + params: { destination: 'braze' }, + headers: { + Accept: 'application/json', + Authorization: 'Bearer api_key', + 'Content-Type': 'application/json', + 'User-Agent': 'RudderLabs', + }, + method: 'POST', + }, + httpRes: { + data: '{"message":"Valid data must be provided in the \'attributes\', \'events\', or \'purchases\' fields.","errors":[{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":0},{"type":"The value provided for the \'email\' field is not a valid email.","input_array":"attributes","index":1}]}', + status: 401, + }, + }, ]; export const networkCallsData = [...deleteNwData, ...dataDeliveryMocksData]; diff --git a/test/integrations/destinations/campaign_manager/dataDelivery/data.ts b/test/integrations/destinations/campaign_manager/dataDelivery/data.ts new file mode 100644 index 0000000000..601ad56401 --- /dev/null +++ b/test/integrations/destinations/campaign_manager/dataDelivery/data.ts @@ -0,0 +1,604 @@ +export const data = [ + { + name: 'campaign_manager', + description: 'Sucess insert request V0', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: '[CAMPAIGN_MANAGER Response Handler] - Request Processed Successfully', + destinationResponse: { + response: { + hasFailures: false, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + }, + }, + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Failure insert request', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437690/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: 'Campaign Manager: Aborting during CAMPAIGN_MANAGER response transformation', + statTags: { + errorCategory: 'network', + errorType: 'aborted', + destType: 'CAMPAIGN_MANAGER', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + }, + destinationResponse: { + response: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + errors: [ + { + code: 'NOT_FOUND', + message: 'Floodlight config id: 213123123 was not found.', + kind: 'dfareporting#conversionError', + }, + ], + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + }, + }, + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Failure insert request Aborted', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437691/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: 'Campaign Manager: Aborting during CAMPAIGN_MANAGER response transformation', + statTags: { + errorCategory: 'network', + errorType: 'aborted', + destType: 'CAMPAIGN_MANAGER', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + }, + destinationResponse: { + response: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + errors: [ + { + code: 'INVALID_ARGUMENT', + message: 'Floodlight config id: 213123123 was not found.', + kind: 'dfareporting#conversionError', + }, + ], + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + }, + }, + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Sucess and fail insert request v1', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437692/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 8, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + metadata: [ + { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + { + jobId: 3, + attemptNum: 1, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + ], + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: '[CAMPAIGN_MANAGER Response V1 Handler] - Request Processed Successfully', + destinationResponse: { + response: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + errors: [ + { + code: 'INVALID_ARGUMENT', + kind: 'dfareporting#conversionError', + message: 'Floodlight config id: 213123123 was not found.', + }, + ], + }, + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 8, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + rudderJobMetadata: [ + { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + { + jobId: 3, + attemptNum: 1, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + ], + }, + response: [ + { + error: 'Floodlight config id: 213123123 was not found., ', + statusCode: 400, + metadata: { + attemptNum: 0, + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + jobId: 2, + secret: { + access_token: 'secret', + developer_token: 'developer_Token', + refresh_token: 'refresh', + }, + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + userId: '', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + }, + }, + { + error: 'success', + metadata: { + attemptNum: 1, + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + jobId: 3, + secret: { + access_token: 'secret', + developer_token: 'developer_Token', + refresh_token: 'refresh', + }, + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + userId: '', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + }, + statusCode: 200, + }, + ], + }, + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Sucess insert request v1', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/43770/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + metadata: { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: '[CAMPAIGN_MANAGER Response V1 Handler] - Request Processed Successfully', + destinationResponse: { + response: { + hasFailures: false, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + rudderJobMetadata: { + jobId: 2, + attemptNum: 0, + userId: '', + sourceId: '2Vsge2uWYdrLfG7pZb5Y82eo4lr', + destinationId: '2RHh08uOsXqE9KvCDg3hoaeuK2L', + workspaceId: '2Csl0lSTbuM3qyHdaOQB2GcDH8o', + secret: { + access_token: 'secret', + refresh_token: 'refresh', + developer_token: 'developer_Token', + }, + }, + }, + response: [ + { + error: 'success', + statusCode: 200, + }, + ], + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/campaign_manager/network.ts b/test/integrations/destinations/campaign_manager/network.ts new file mode 100644 index 0000000000..ddecbaf8fa --- /dev/null +++ b/test/integrations/destinations/campaign_manager/network.ts @@ -0,0 +1,311 @@ +const Data = [ + { + httpReq: { + method: 'post', + url: 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchinsert', + data: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + }, + httpRes: { + data: { + hasFailures: false, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + statusText: 'OK', + }, + }, + { + httpReq: { + method: 'post', + url: 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437690/conversions/batchinsert', + data: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + }, + httpRes: { + data: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + errors: [ + { + code: 'NOT_FOUND', + message: 'Floodlight config id: 213123123 was not found.', + kind: 'dfareporting#conversionError', + }, + ], + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + statusText: 'OK', + }, + }, + { + httpReq: { + method: 'post', + url: 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/43770/conversions/batchinsert', + data: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + }, + httpRes: { + data: { + hasFailures: false, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + statusText: 'OK', + }, + }, + { + httpReq: { + method: 'post', + url: 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437692/conversions/batchinsert', + data: { + kind: 'dfareporting#conversionsBatchInsertRequest', + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 8, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + }, + httpRes: { + data: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + errors: [ + { + code: 'INVALID_ARGUMENT', + message: 'Floodlight config id: 213123123 was not found.', + kind: 'dfareporting#conversionError', + }, + ], + kind: 'dfareporting#conversionStatus', + }, + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 8, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + statusText: 'OK', + }, + }, + { + httpReq: { + method: 'post', + url: 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437691/conversions/batchinsert', + data: { + kind: 'dfareporting#conversionsBatchInsertRequest', + encryptionInfo: { + kind: 'dfareporting#encryptionInfo', + encryptionSource: 'AD_SERVING', + encryptionEntityId: '3564523', + encryptionEntityType: 'DCM_ACCOUNT', + }, + conversions: [ + { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + ], + }, + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + }, + httpRes: { + data: { + hasFailures: true, + status: [ + { + conversion: { + timestampMicros: '1668624722000000', + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + }, + errors: [ + { + code: 'INVALID_ARGUMENT', + message: 'Floodlight config id: 213123123 was not found.', + kind: 'dfareporting#conversionError', + }, + ], + kind: 'dfareporting#conversionStatus', + }, + ], + kind: 'dfareporting#conversionsBatchInsertResponse', + }, + status: 200, + statusText: 'OK', + }, + }, +]; +export const networkCallsData = [...Data]; diff --git a/test/integrations/destinations/campaign_manager/router/data.ts b/test/integrations/destinations/campaign_manager/router/data.ts index 95372e1925..2ab1813cf8 100644 --- a/test/integrations/destinations/campaign_manager/router/data.ts +++ b/test/integrations/destinations/campaign_manager/router/data.ts @@ -1,7 +1,7 @@ export const data = [ { name: 'campaign_manager', - description: 'Test 0', + description: 'Batch Different Type Requests', feature: 'router', module: 'destination', version: 'v0', @@ -77,7 +77,7 @@ export const data = [ properties: { profileId: 437689, floodlightConfigurationId: '213123123', - ordinal: 'string', + ordinal: '1', quantity: '455678', floodlightActivityId: '456543345245', value: 7, @@ -167,7 +167,7 @@ export const data = [ properties: { profileId: 437689, floodlightConfigurationId: '213123123', - ordinal: 'string', + ordinal: '2', floodlightActivityId: '456543345245', quantity: '455678', value: 7, @@ -256,16 +256,11 @@ export const data = [ properties: { profileId: 437689, floodlightConfigurationId: '213123123', - ordinal: 'string', + ordinal: '3', floodlightActivityId: '456543345245', - mobileDeviceId: 'string', value: 7, encryptedUserIdCandidates: ['dfghjbnm'], - gclid: 'string', - matchId: 'string', - dclid: 'string', quantity: '455678', - impressionId: 'string', limitAdTracking: true, childDirectedTreatment: true, encryptionInfo: { @@ -322,7 +317,7 @@ export const data = [ treatmentForUnderage: false, timestampMicros: '1668624722903000', floodlightConfigurationId: '213123123', - ordinal: 'string', + ordinal: '1', quantity: '455678', floodlightActivityId: '456543345245', value: 7, @@ -348,7 +343,7 @@ export const data = [ jobId: 1, }, ], - batched: false, + batched: true, statusCode: 200, destination: { Config: { @@ -387,7 +382,7 @@ export const data = [ treatmentForUnderage: false, timestampMicros: '1668624722903000', floodlightConfigurationId: '213123123', - ordinal: 'string', + ordinal: '2', quantity: '455678', floodlightActivityId: '456543345245', value: 7, @@ -411,7 +406,7 @@ export const data = [ jobId: 2, }, ], - batched: false, + batched: true, statusCode: 200, destination: { Config: { @@ -461,4 +456,802 @@ export const data = [ }, }, }, + { + name: 'campaign_manager', + description: 'Batch Sucessful BatchInsert Request', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + matchId: '123', + floodlightConfigurationId: '213123123', + quantity: '455678', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchinsert', + }, + type: 'track', + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '111', + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchinsert', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + ordinal: '1', + quantity: '455678', + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchinsert', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + ], + destType: 'campaign_manager', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + conversions: [ + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '123', + limitAdTracking: true, + childDirectedTreatment: true, + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '111', + limitAdTracking: true, + childDirectedTreatment: true, + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + ], + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Batch Sucessful BatchInsert and BatchUpdate Request', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + matchId: '123', + floodlightConfigurationId: '213123123', + quantity: '455678', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchupdate', + }, + type: 'track', + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '111', + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchupdate', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + floodlightActivityId: '456543345245', + value: 7, + gclid: '123', + ordinal: '1', + quantity: '455678', + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchinsert', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + ], + destType: 'campaign_manager', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchupdate', + headers: { + Authorization: 'Bearer dummyApiToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchUpdateRequest', + conversions: [ + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '123', + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + matchId: '111', + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://dfareporting.googleapis.com/dfareporting/v4/userprofiles/437689/conversions/batchinsert', + headers: { + Authorization: 'Bearer dummyApiToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + kind: 'dfareporting#conversionsBatchInsertRequest', + conversions: [ + { + floodlightConfigurationId: '213123123', + ordinal: '1', + timestampMicros: '1668624722903000', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + gclid: '123', + limitAdTracking: true, + childDirectedTreatment: true, + nonPersonalizedAd: false, + treatmentForUnderage: false, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + ], + }, + }, + }, + }, + { + name: 'campaign_manager', + description: 'Entire Batch has data instrumentation', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + quantity: '455678', + ordinal: '1', + floodlightActivityId: '456543345245', + value: 7, + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchupdate', + }, + type: 'track', + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + ordinal: '1', + floodlightActivityId: '456543345245', + quantity: '455678', + value: 7, + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchupdate', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + { + metadata: { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + message: { + channel: 'web', + event: 'Promotion Clicked', + type: 'track', + originalTimestamp: '2022-11-17T00:22:02.903+05:30', + properties: { + profileId: 437689, + floodlightConfigurationId: '213123123', + floodlightActivityId: '456543345245', + value: 7, + + ordinal: '1', + quantity: '455678', + limitAdTracking: true, + childDirectedTreatment: true, + requestType: 'batchinsert', + }, + anonymousId: 'randomId', + integrations: { + All: true, + }, + name: 'ApplicationLoaded', + sentAt: '2022-11-17T00:22:02.903+05:30', + }, + }, + ], + destType: 'campaign_manager', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 4, + }, + ], + batched: false, + statusCode: 400, + error: + '[CAMPAIGN MANAGER (DCM)]: Atleast one of encryptedUserId,encryptedUserIdCandidates, matchId, mobileDeviceId, gclid, dclid, impressionId.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'CAMPAIGN_MANAGER', + module: 'destination', + implementation: 'native', + feature: 'router', + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + { + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 5, + }, + ], + batched: false, + statusCode: 400, + error: + '[CAMPAIGN MANAGER (DCM)]: Atleast one of encryptedUserId,encryptedUserIdCandidates, matchId, mobileDeviceId, gclid, dclid, impressionId.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'CAMPAIGN_MANAGER', + module: 'destination', + implementation: 'native', + feature: 'router', + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + { + metadata: [ + { + secret: { + access_token: 'dummyApiToken', + refresh_token: 'efgh5678', + developer_token: 'ijkl91011', + }, + jobId: 6, + }, + ], + batched: false, + statusCode: 400, + error: + '[CAMPAIGN MANAGER (DCM)]: Atleast one of encryptedUserId,encryptedUserIdCandidates, matchId, mobileDeviceId, gclid, dclid, impressionId.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'CAMPAIGN_MANAGER', + module: 'destination', + implementation: 'native', + feature: 'router', + }, + destination: { + Config: { + treatmentForUnderage: false, + limitAdTracking: false, + childDirectedTreatment: false, + nonPersonalizedAd: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', + }, + }, + }, + ], + }, + }, + }, + }, ]; diff --git a/test/integrations/destinations/dcm_floodlight/processor/data.ts b/test/integrations/destinations/dcm_floodlight/processor/data.ts new file mode 100644 index 0000000000..e4b582a3f7 --- /dev/null +++ b/test/integrations/destinations/dcm_floodlight/processor/data.ts @@ -0,0 +1,5003 @@ +export const data = [ + { + name: 'dcm_floodlight', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '22448662', + activityTag: '', + groupTag: '', + conversionEvents: [ + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'rudder2', + to: '2', + }, + ], + eventName: 'Product viewed', + floodlightActivityTag: 'signu01', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'signu01', + floodlightGroupTag: 'conv02', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Product viewed', + properties: { + orderId: 111, + quantity: 2, + revenue: 800, + rudder1: 'rudder-v1', + rudder2: 'rudder-v2', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=22448662;cat=signu01;type=conv01;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=rudder-v1;u2=rudder-v2', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash2', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Sign up Completed', + properties: { + orderId: 111, + quantity: 2, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=signu0;type=conv01;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash2', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order Complete', + properties: { + orderId: 111, + quantity: 2, + revenue: 800, + rudder1: 'rudder-v1', + akash2: 'akash-v2', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=order0;type=conv000;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=rudder-v1;u2=akash-v2', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 3', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash2', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + quantity: 2, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=2;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 4', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash1', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + { + customVariables: [ + { + from: 'rudder2', + to: '1', + }, + { + from: 'akash2', + to: '2', + }, + { + from: 'friendlyName2', + to: '3', + }, + { + from: 'name2', + to: '4', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Purchase', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + rudder2: 'rudder2', + akash2: 'akash2', + friendlyName2: 'friendlyName2', + name2: 'name2', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=Pur0;type=conv111;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=rudder2;u2=akash2;u3=friendlyName2;u4=name2', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 5', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash1', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + { + customVariables: [ + { + from: 'rudder2', + to: '1', + }, + { + from: 'akash2', + to: '2', + }, + { + from: 'friendlyName2', + to: '3', + }, + { + from: 'name2', + to: '4', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Sign up Completed', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'advertisingId is required: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: advertisingId is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 6', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash1', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + }, + event: 'Sign up Completed', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'track:: userAgent is required: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: track:: userAgent is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 7', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'akash1', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + akash1: 'akash-v1', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=3;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=akash-v1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 8', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=3;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 9', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Sample event', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'track:: Conversion event not found: Workflow: procWorkflow, Step: handleConversionEvents, ChildStep: undefined, OriginalError: track:: Conversion event not found', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 10', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=1;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 11', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 4, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=6;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 12', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Checkout Started', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=check0;type=conv00;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=111;qty=999999;cost=800;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 13', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'OrDeR complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + rudder1: 'rudder-v1', + akash1: 'akash-v1', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=order0;type=conv000;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=rudder-v1;u2=akash-v1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 14', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + rudder1: 'rudder-v1', + akash1: 'akash-v1', + }, + integrations: { + All: true, + 'DCM Floodlight': {}, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=order0;type=conv000;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;u1=rudder-v1;u2=akash-v1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 15', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + rudder1: 100, + akash1: 5987, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=order0;type=conv000;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;u1=100;u2=5987', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 16', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: true, + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + rudder1: 'rudder-v1', + akash1: 'akash-v1', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 1, + GDPR: 1, + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=order0;type=conv000;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=1;tfua=1;npa=1;u1=rudder-v1;u2=akash-v1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 17', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: true, + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'Yes', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'COPPA: valid parameters are [1|true] or [0|false]: Workflow: procWorkflow, Step: handleIntegrationsObject, ChildStep: undefined, OriginalError: COPPA: valid parameters are [1|true] or [0|false]', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 18', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: true, + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: 'Yes', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'GDPR: valid parameters are [1|true] or [0|false]: Workflow: procWorkflow, Step: handleIntegrationsObject, ChildStep: undefined, OriginalError: GDPR: valid parameters are [1|true] or [0|false]', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 19', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: true, + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: 'No', + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'npa: valid parameters are [1|true] or [0|false]: Workflow: procWorkflow, Step: handleIntegrationsObject, ChildStep: undefined, OriginalError: npa: valid parameters are [1|true] or [0|false]', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 20', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'Yes', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Order complete', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: 'true', + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'dc_lat: valid parameters are [1|true] or [0|false]: Workflow: procWorkflow, Step: cleanPayload, ChildStep: undefined, OriginalError: dc_lat: valid parameters are [1|true] or [0|false]', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 21', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'page', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'Yes', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: 'true', + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'page:: Conversion event not found: Workflow: procWorkflow, Step: handleConversionEvents, ChildStep: undefined, OriginalError: page:: Conversion event not found', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'DCM_FLOODLIGHT', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 22', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Viewed Sign up Completed Page', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'page', + channel: 'web', + name: 'Sign up Completed', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: 'true', + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=signu0;type=conv01;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 23', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '22448662', + activityTag: '', + groupTag: '', + conversionEvents: [ + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'rudder2', + to: '2', + }, + ], + eventName: 'Product viewed', + floodlightActivityTag: 'signu01', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'signu01', + floodlightGroupTag: 'conv02', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Product viewed', + properties: { + orderId: 111, + quantity: 2, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=22448662;cat=signu01;type=conv01;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 24', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + from: 'rudder1', + to: '1', + }, + { + from: 'akash1', + to: '2', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + from: '', + to: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Purchase', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + rudder2: 0, + akash2: 'akash2', + friendlyName2: false, + name2: '1234', + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=Pur0;type=conv111;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=0;u2=akash2;u4=1234', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 25', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '12649566', + activityTag: 'check0', + groupTag: 'conv00', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Viewed Page', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + eventName: 'Checkout Started', + floodlightActivityTag: '', + floodlightGroupTag: '', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'page', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: 'true', + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=signu0;type=conv01;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'dcm_floodlight', + description: 'Test 26', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + activityTag: '', + advertiserId: '12649566', + conversionEvents: [ + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Sign up Completed', + floodlightActivityTag: 'signu0', + floodlightGroupTag: 'conv01', + salesTag: false, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder1', + }, + { + to: '2', + from: 'akash1', + }, + ], + eventName: 'Order Complete', + floodlightActivityTag: 'order0', + floodlightGroupTag: 'conv000', + salesTag: false, + }, + { + customVariables: [ + { + to: '', + from: '', + }, + ], + eventName: 'Checkout Started', + floodlightActivityTag: 'check0', + floodlightGroupTag: 'conv00', + salesTag: true, + }, + { + customVariables: [ + { + to: '1', + from: 'rudder2', + }, + { + to: '2', + from: 'akash2', + }, + { + to: '3', + from: 'friendlyName2', + }, + { + to: '4', + from: 'name2', + }, + ], + eventName: 'Purchase', + floodlightActivityTag: 'Pur0', + floodlightGroupTag: 'conv111', + salesTag: false, + }, + ], + groupTag: '', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + userId: '1234', + type: 'track', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + adTrackingEnabled: 'true', + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + brand: 'Google2', + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + traits: { + name2: 'traits-v1', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + event: 'Purchase', + properties: { + orderId: 111, + quantity: 999999, + revenue: 800, + products: [ + { + sku: '45790-32', + url: 'https://www.example.com/product/path', + name: 'Monopoly: 3rd Edition', + price: 19, + category: 'Games', + quantity: 1, + image_url: 'https:///www.example.com/product/path.jpg', + product_id: '507f1f77bcf86cd799439011', + }, + { + sku: '46493-32', + name: 'Uno Card Game', + price: 3, + category: 'Games', + quantity: 2, + product_id: '505bd76785ebb509fc183733', + }, + ], + rudder2: '0', + akash2: 'akash2', + friendlyName2: false, + }, + integrations: { + All: true, + 'DCM Floodlight': { + COPPA: 'false', + GDPR: '1', + npa: true, + }, + }, + messageId: 'ea5cfab2-3961-4d8a-8187-3d1858c90a9f', + originalTimestamp: '2020-01-17T04:53:51.185Z', + receivedAt: '2020-01-17T10:23:52.688+05:30', + sentAt: '2020-01-17T04:53:52.667Z', + timestamp: '2020-01-17T10:23:51.206+05:30', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: + 'https://ad.doubleclick.net/ddm/activity/src=12649566;cat=Pur0;type=conv111;dc_rdid=T0T0T072-5e28-45a1-9eda-ce22a3e36d1a;ord=ea5cfab2-3961-4d8a-8187-3d1858c90a9f;dc_lat=1;tag_for_child_directed_treatment=0;tfua=1;npa=1;u1=0;u2=akash2;u4=traits-v1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/dynamic_yield/processor/data.ts b/test/integrations/destinations/dynamic_yield/processor/data.ts new file mode 100644 index 0000000000..f72f1574f7 --- /dev/null +++ b/test/integrations/destinations/dynamic_yield/processor/data.ts @@ -0,0 +1,1041 @@ +export const data = [ + { + name: 'dynamic_yield', + description: 'Identify call without hashed email 21313123', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'peter@example.com', + }, + type: 'identify', + userId: 'user0', + version: '1', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: true, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'user0' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Identify User', + properties: { + dyType: 'identify-v1', + hashedEmail: + 'f111db891a36b76df28abc74867e6c7248f796e045117f0cff27b6e2be25d2df', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Identify call with hashed email', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'f111db891a36b76df28abc74867e6c7248f796e045117f0cff27b6e2be25d2df', + }, + type: 'identify', + userId: 'user0', + version: '1', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'user0' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Identify User', + properties: { + dyType: 'identify-v1', + hashedEmail: + 'f111db891a36b76df28abc74867e6c7248f796e045117f0cff27b6e2be25d2df', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Track call with Product Added event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Product Added', + userId: 'testuserId1', + properties: { + product_id: '123', + sku: 'item-34454ga', + category: 'Games', + name: 'Game', + brand: 'Gamepro', + variant: '111', + price: 39.95, + quantity: 1, + coupon: 'DISC21', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.png', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'testuserId1' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Add to Cart', + properties: { + dyType: 'add-to-cart-v1', + value: 39.95, + productId: 'item-34454ga', + quantity: 1, + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Identify call without email', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: {}, + type: 'identify', + userId: 'user0', + version: '1', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'user0' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Identify User', + properties: { + dyType: 'identify-v1', + cuid: 'user0', + cuidType: 'userId', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Track call with Product Removed event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Product Removed', + userId: 'testuserId1', + properties: { + product_id: '123', + sku: 'item-34454ga', + category: 'Games', + name: 'Game', + brand: 'Gamepro', + variant: '111', + price: 39.95, + quantity: 1, + coupon: 'DISC21', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.png', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'testuserId1' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Remove from Cart', + properties: { + dyType: 'remove-from-cart-v1', + value: 39.95, + productId: 'item-34454ga', + quantity: 1, + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Track call with Product Added to Wishlist event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Product Added to Wishlist', + userId: 'testuserId1', + properties: { + product_id: '123', + sku: 'item-34454ga', + category: 'Games', + name: 'Game', + brand: 'Gamepro', + variant: '111', + price: 39.95, + quantity: 1, + coupon: 'DISC21', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.png', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'testuserId1' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Add to Wishlist', + properties: { + dyType: 'add-to-wishlist-v1', + value: 39.95, + productId: 'item-34454ga', + quantity: 1, + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Track call with order completed event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Order Completed', + userId: 'testuserId1', + properties: { + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + total: 20, + revenue: 15, + shipping: 4, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + products: [ + { + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://dy-api.com/v2/collect/user/event', + headers: { + 'Content-Type': 'application/json', + 'DY-API-Key': 'dummyApiKey', + }, + params: {}, + body: { + JSON: { + user: { id: 'testuserId1' }, + session: { custom: '16733896350494' }, + context: { device: { ip: '54.100.200.255' } }, + events: [ + { + name: 'Purchase', + properties: { + dyType: 'purchase-v1', + uniqueTransactionId: '1234', + value: 15, + currency: 'USD', + cart: [ + { + itemPrice: 14, + productId: 'G-32', + quantity: 1, + }, + { + itemPrice: 3.45, + productId: 'F-32', + quantity: 2, + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Unsupported group call check', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'peter@example.com', + }, + type: 'group', + userId: 'user0', + version: '1', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'message type group is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type group is not supported', + statTags: { + destType: 'DYNAMIC_YIELD', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Event type not present', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'peter@example.com', + }, + userId: 'user0', + version: '1', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'message Type is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting message.', + statTags: { + destType: 'DYNAMIC_YIELD', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'API Key not present', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + type: 'identify', + context: { + ip: '54.100.200.255', + sessionId: '16733896350494', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36', + }, + integrations: { + All: true, + }, + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'peter@example.com', + }, + userId: 'user0', + version: '1', + }, + destination: { + Config: {}, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'Api Key is not present: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Api Key is not present', + statTags: { + destType: 'DYNAMIC_YIELD', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'dynamic_yield', + description: 'Event is not there in input', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + userId: 'testuserId1', + properties: { + product_id: '123', + sku: 'item-34454ga', + category: 'Games', + name: 'Game', + brand: 'Gamepro', + variant: '111', + price: 39.95, + quantity: 1, + coupon: 'DISC21', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.png', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'event is not present. Aborting.: Workflow: procWorkflow, Step: validateInputForTrack, ChildStep: undefined, OriginalError: event is not present. Aborting.', + statTags: { + destType: 'DYNAMIC_YIELD', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/eloqua/processor/data.ts b/test/integrations/destinations/eloqua/processor/data.ts new file mode 100644 index 0000000000..50aad5639a --- /dev/null +++ b/test/integrations/destinations/eloqua/processor/data.ts @@ -0,0 +1,460 @@ +export const data = [ + { + name: 'eloqua', + description: 'identify payload pass', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + traits: { + C_FirstName: 'Test User', + C_patient_id1: 1, + C_MobilePhone: '+008822773355', + C_City: 'Scranton', + C_date_of_birth_1life1: '22/12/01', + }, + userId: 'testUser1234@keeptesting.com', + context: { + sources: { + job_id: '2RVkqlV1adBiIpj33kWlQzchMP1/Syncher', + version: 'v1.28.0', + job_run_id: 'cja699onfuet3te5obc0', + task_run_id: 'cja699onfuet3te5obcg', + }, + externalId: [ + { + id: 'testUser1234@keeptesting.com', + type: 'ELOQUA-contacts', + identifierType: 'C_EmailAddress', + }, + ], + mappedToDestination: 'true', + }, + recordId: '1', + rudderId: '3606d3c7-8741-4245-a254-450e137d3866', + messageId: '40def17a-1b6a-4d2d-a851-2a8d96f913bd', + }, + destination: { + Config: { + customerAccountId: '89236978', + customerId: '78678678', + audienceId: '564567', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: '', + headers: {}, + params: {}, + body: { + JSON: { + identifierFieldName: 'C_EmailAddress', + data: { + C_FirstName: 'Test User', + C_patient_id1: '1', + C_MobilePhone: '+008822773355', + C_City: 'Scranton', + C_date_of_birth_1life1: '22/12/01', + C_EmailAddress: 'testUser1234@keeptesting.com', + }, + customObjectId: 'contacts', + type: 'identify', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'eloqua', + description: 'type not correect', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'audiencelist', + traits: { + C_FirstName: 'Test User', + C_patient_id1: 1, + C_MobilePhone: '+008822773355', + C_City: 'Scranton', + C_date_of_birth_1life1: '22/12/01', + }, + userId: 'testUser1234@keeptesting.com', + context: { + sources: { + job_id: '2RVkqlV1adBiIpj33kWlQzchMP1/Syncher', + version: 'v1.28.0', + job_run_id: 'cja699onfuet3te5obc0', + task_run_id: 'cja699onfuet3te5obcg', + }, + externalId: [ + { + id: 'testUser1234@keeptesting.com', + type: 'ELOQUA-contacts', + identifierType: 'C_EmailAddress', + }, + ], + mappedToDestination: 'true', + }, + recordId: '1', + rudderId: '3606d3c7-8741-4245-a254-450e137d3866', + messageId: '40def17a-1b6a-4d2d-a851-2a8d96f913bd', + }, + destination: { + Config: { + customerAccountId: '89236978', + customerId: '78678678', + audienceId: '564567', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Event type audiencelist is not supported. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Event type audiencelist is not supported. Aborting message.', + statTags: { + destType: 'ELOQUA', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'eloqua', + description: 'trits not correect', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + userId: 'testUser1234@keeptesting.com', + context: { + sources: { + job_id: '2RVkqlV1adBiIpj33kWlQzchMP1/Syncher', + version: 'v1.28.0', + job_run_id: 'cja699onfuet3te5obc0', + task_run_id: 'cja699onfuet3te5obcg', + }, + externalId: [ + { + id: 'testUser1234@keeptesting.com', + type: 'ELOQUA-contacts', + identifierType: 'C_EmailAddress', + }, + ], + mappedToDestination: 'true', + }, + recordId: '1', + rudderId: '3606d3c7-8741-4245-a254-450e137d3866', + messageId: '40def17a-1b6a-4d2d-a851-2a8d96f913bd', + }, + destination: { + Config: { + customerAccountId: '89236978', + customerId: '78678678', + audienceId: '564567', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Message traits/properties not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Message traits/properties not present. Aborting message.', + statTags: { + destType: 'ELOQUA', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'eloqua', + description: 'identify payload pass 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + traits: { + C_FirstName: 'Test User', + C_patient_id1: 1, + C_MobilePhone: '+008822773355', + C_City: 'Scranton', + C_date_of_birth_1life1: '22/12/01', + }, + userId: 'testUser1234@keeptesting.com', + context: { + sources: { + job_id: '2RVkqlV1adBiIpj33kWlQzchMP1/Syncher', + version: 'v1.28.0', + job_run_id: 'cja699onfuet3te5obc0', + task_run_id: 'cja699onfuet3te5obcg', + }, + externalId: [ + { + id: 'testUser1234@keeptesting.com', + type: 'ELOQUA-contacts', + identifierType: 'C_EmailAddress', + }, + ], + mappedToDestination: 'true', + }, + recordId: '1', + rudderId: '3606d3c7-8741-4245-a254-450e137d3866', + messageId: '40def17a-1b6a-4d2d-a851-2a8d96f913bd', + }, + destination: { + Config: { + customerAccountId: '89236978', + customerId: '78678678', + audienceId: '564567', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: '', + headers: {}, + params: {}, + body: { + JSON: { + identifierFieldName: 'C_EmailAddress', + data: { + C_FirstName: 'Test User', + C_patient_id1: '1', + C_MobilePhone: '+008822773355', + C_City: 'Scranton', + C_date_of_birth_1life1: '22/12/01', + C_EmailAddress: 'testUser1234@keeptesting.com', + }, + customObjectId: 'contacts', + type: 'identify', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'eloqua', + description: 'track payload pass', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'track', + properties: { + key11: 'Test User', + key21: 1, + contactID11: '+008822773355', + }, + userId: 'testUser1234@keeptesting.com', + channel: 'sources', + context: { + sources: { + job_id: '2RVkqlV1adBiIpj33kWlQzchMP1/Syncher', + version: 'v1.28.0', + job_run_id: 'cja699onfuet3te5obc0', + task_run_id: 'cja699onfuet3te5obcg', + }, + externalId: [ + { + id: 'testUser1234@keeptesting.com', + type: 'ELOQUA-172', + identifierType: 'contactID1', + }, + ], + mappedToDestination: 'true', + }, + recordId: '1', + rudderId: '3606d3c7-8741-4245-a254-450e137d3866', + messageId: '40def17a-1b6a-4d2d-a851-2a8d96f913bd', + }, + destination: { + Config: { + customerAccountId: '89236978', + customerId: '78678678', + audienceId: '564567', + hashEmail: false, + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: '', + headers: {}, + params: {}, + body: { + JSON: { + identifierFieldName: 'contactID1', + data: { + key11: 'Test User', + key21: '1', + contactID11: '+008822773355', + contactID1: 'testUser1234@keeptesting.com', + }, + customObjectId: '172', + type: 'track', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts b/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts index e4e4a7d4c8..eb9ce344e0 100644 --- a/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts +++ b/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts @@ -1,3 +1,5 @@ +import { VERSION } from '../../../../../src/v0/destinations/facebook_pixel/config'; + export const data = [ { name: 'facebook_pixel', @@ -24,8 +26,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_access_token`, params: { destination: 'facebook_pixel', }, @@ -89,8 +90,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=my_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=my_access_token`, params: { destination: 'facebook_pixel', }, @@ -139,8 +139,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_timestamp_correct_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_timestamp_correct_access_token`, params: { destination: 'facebook_pixel', }, @@ -209,8 +208,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=throttled_valid_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=throttled_valid_access_token`, params: { destination: 'facebook_pixel', }, @@ -274,8 +272,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_account_id_valid_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_account_id_valid_access_token`, params: { destination: 'facebook_pixel', }, @@ -290,7 +287,7 @@ export const data = [ output: { status: 400, message: - "Object with ID 'PIXEL_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", + "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", destinationResponse: { error: { message: @@ -342,8 +339,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=not_found_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=not_found_access_token`, params: { destination: 'facebook_pixel', }, @@ -411,8 +407,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234570/events?access_token=valid_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234570/events?access_token=valid_access_token`, }, method: 'POST', }, @@ -477,8 +472,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234571/events?access_token=valid_access_token', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234571/events?access_token=valid_access_token`, }, method: 'POST', }, @@ -543,8 +537,7 @@ export const data = [ userId: '', headers: {}, version: '1', - endpoint: - 'https://graph.facebook.com/v17.0/1234567891234572/events?access_token=valid_access_token_unhandled_response', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234572/events?access_token=valid_access_token_unhandled_response`, }, method: 'POST', }, diff --git a/test/integrations/destinations/facebook_pixel/network.ts b/test/integrations/destinations/facebook_pixel/network.ts index a63970c4c6..05b3a05fd0 100644 --- a/test/integrations/destinations/facebook_pixel/network.ts +++ b/test/integrations/destinations/facebook_pixel/network.ts @@ -1,10 +1,11 @@ import { data } from './dataDelivery/data'; import { getFormData } from '../../../../src/adapters/network'; +import { VERSION } from '../../../../src/v0/destinations/facebook_pixel/config'; export const networkCallsData = [ { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_access_token`, data: getFormData(data[0].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -24,7 +25,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_timestamp_correct_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_timestamp_correct_access_token`, data: getFormData(data[2].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -49,7 +50,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=throttled_valid_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=throttled_valid_access_token`, data: getFormData(data[3].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -69,7 +70,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_account_id_valid_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_account_id_valid_access_token`, data: getFormData(data[4].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -91,7 +92,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=not_found_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=not_found_access_token`, data: getFormData(data[5].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -112,7 +113,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234570/events?access_token=valid_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234570/events?access_token=valid_access_token`, data: getFormData(data[6].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -133,7 +134,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234571/events?access_token=valid_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234571/events?access_token=valid_access_token`, data: getFormData(data[7].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -154,7 +155,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234572/events?access_token=valid_access_token_unhandled_response', + url: `https://graph.facebook.com/${VERSION}/1234567891234572/events?access_token=valid_access_token_unhandled_response`, data: getFormData(data[8].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -175,7 +176,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/1234567891234567/events?access_token=my_access_token', + url: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=my_access_token`, data: getFormData(data[1].input.request.body.body.FORM).toString(), params: { destination: 'facebook_pixel' }, headers: { 'User-Agent': 'RudderLabs' }, diff --git a/test/integrations/destinations/facebook_pixel/processor/data.ts b/test/integrations/destinations/facebook_pixel/processor/data.ts index d5d0a8ec96..557bc7066c 100644 --- a/test/integrations/destinations/facebook_pixel/processor/data.ts +++ b/test/integrations/destinations/facebook_pixel/processor/data.ts @@ -1,3 +1,5 @@ +import { VERSION } from '../../../../../src/v0/destinations/facebook_pixel/config'; + export const mockFns = (_) => { // @ts-ignore jest.useFakeTimers().setSystemTime(new Date('2023-10-15')); @@ -106,7 +108,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -445,7 +447,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -569,7 +571,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -688,7 +690,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -807,7 +809,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -927,7 +929,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1047,7 +1049,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1166,7 +1168,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1284,7 +1286,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1419,7 +1421,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1554,7 +1556,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1705,7 +1707,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1855,7 +1857,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -1984,7 +1986,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2106,7 +2108,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2249,7 +2251,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2392,7 +2394,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2516,7 +2518,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2640,7 +2642,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2768,7 +2770,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -2893,7 +2895,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3014,7 +3016,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3133,7 +3135,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3282,7 +3284,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3510,7 +3512,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3631,7 +3633,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -3884,7 +3886,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -4027,7 +4029,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -4289,7 +4291,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -4752,7 +4754,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -4897,7 +4899,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -5178,7 +5180,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -5310,7 +5312,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -5440,7 +5442,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -6032,8 +6034,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: - 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=dummyAccessToken', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=dummyAccessToken`, headers: {}, params: {}, body: { @@ -6058,4 +6059,405 @@ export const data = [ }, }, }, + { + name: 'facebook_pixel', + description: 'Test 48', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + email: 'test@rudderstack.com', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + type: 'track', + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2023-10-14T15:46:51.693229+05:30', + anonymousId: '00000000000000000000000000', + userId: '12345', + event: 'order completed', + properties: { + category: ['clothing', 'fishing'], + order_id: 'rudderstackorder1', + total: 99.99, + revenue: 12.24, + shipping: 13.99, + tax: 20.99, + currency: 'INR', + products: [ + { + quantity: 1, + price: 24.75, + name: 'my product', + sku: 'p-298', + delivery_category: 'home_delivery', + }, + { + quantity: 3, + price: 24.75, + name: 'other product', + sku: 'p-299', + delivery_category: 'home_delivery', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T11:15:53.296Z', + }, + destination: { + Config: { + blacklistPiiProperties: [ + { + blacklistPiiProperties: '', + blacklistPiiHash: true, + }, + ], + categoryToContent: [ + { + from: 'clothing', + to: 'product', + }, + ], + accessToken: '09876', + pixelId: 'dummyPixelId', + eventsToEvents: [ + { + from: '', + to: '', + }, + ], + eventCustomProperties: [ + { + eventCustomProperties: '', + }, + ], + valueFieldIdentifier: 'properties.price', + advancedMapping: false, + whitelistPiiProperties: [ + { + whitelistPiiProperties: '', + }, + ], + }, + Enabled: true, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: { + data: [ + '{"user_data":{"external_id":"5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5","em":"1c5e54849f5c711ce38fa60716fbbe44bff478f9ca250897b39cdfc2438cd1bd","client_user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"},"event_name":"Purchase","event_time":1697278611,"event_id":"ec5481b6-a926-4d2e-b293-0b3a77c4d3be","action_source":"website","custom_data":{"category[0]":"clothing","category[1]":"fishing","order_id":"rudderstackorder1","total":99.99,"revenue":12.24,"shipping":13.99,"tax":20.99,"currency":"INR","products[0].quantity":1,"products[0].price":24.75,"products[0].name":"my product","products[0].sku":"p-298","products[0].delivery_category":"home_delivery","products[1].quantity":3,"products[1].price":24.75,"products[1].name":"other product","products[1].sku":"p-299","products[1].delivery_category":"home_delivery","content_category":"clothing,fishing","content_ids":["p-298","p-299"],"content_type":"product","value":12.24,"contents":[{"id":"p-298","quantity":1,"item_price":24.75,"delivery_category":"home_delivery"},{"id":"p-299","quantity":3,"item_price":24.75,"delivery_category":"home_delivery"}],"num_items":2}}', + ], + }, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'facebook_pixel', + description: 'Test 49', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + channel: 'mobile', + destination_props: { + Fb: { + app_id: 'RudderFbApp', + }, + }, + context: { + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, + screen: { + height: '100', + density: 50, + }, + traits: { + email: ' aBc@gmail.com ', + address: { + zip: 1234, + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + revenue: 400, + additional_bet_index: 0, + content_ids: ['prod1', 'prod2'], + }, + timestamp: '2023-10-14T00:00:00.693229+05:30', + type: 'track', + }, + destination: { + Config: { + limitedDataUsage: true, + blacklistPiiProperties: [ + { + blacklistPiiProperties: '', + blacklistPiiHash: false, + }, + ], + accessToken: '09876', + pixelId: 'dummyPixelId', + eventsToEvents: [ + { + from: '', + to: '', + }, + ], + eventCustomProperties: [ + { + eventCustomProperties: '', + }, + ], + removeExternalId: true, + valueFieldIdentifier: '', + advancedMapping: false, + whitelistPiiProperties: [ + { + whitelistPiiProperties: '', + }, + ], + }, + Enabled: true, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: { + data: [ + '{"user_data":{"em":"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08","zp":"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"},"event_name":"spin_result","event_time":1697221800,"action_source":"app","custom_data":{"additional_bet_index":0,"value":400,"content_ids":["prod1","prod2"]}}', + ], + }, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'facebook_pixel', + description: 'Test 50', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + channel: 'mobile', + destination_props: { + Fb: { + app_id: 'RudderFbApp', + }, + }, + context: { + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, + screen: { + height: '100', + density: 50, + }, + traits: { + email: ' aBc@gmail.com ', + address: { + zip: 1234, + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + revenue: 400, + additional_bet_index: 0, + contents: [ + { + id: 'prod1', + quantity: 5, + item_price: 55, + }, + ], + }, + timestamp: '2023-10-14T00:00:00.693229+05:30', + type: 'track', + }, + destination: { + Config: { + limitedDataUsage: true, + blacklistPiiProperties: [ + { + blacklistPiiProperties: '', + blacklistPiiHash: false, + }, + ], + accessToken: '09876', + pixelId: 'dummyPixelId', + eventsToEvents: [ + { + from: '', + to: '', + }, + ], + eventCustomProperties: [ + { + eventCustomProperties: '', + }, + ], + removeExternalId: true, + valueFieldIdentifier: '', + advancedMapping: false, + whitelistPiiProperties: [ + { + whitelistPiiProperties: '', + }, + ], + }, + Enabled: true, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: { + data: [ + '{"user_data":{"em":"48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08","zp":"03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"},"event_name":"spin_result","event_time":1697221800,"action_source":"app","custom_data":{"additional_bet_index":0,"value":400,"contents":[{"id":"prod1","quantity":5,"item_price":55}]}}', + ], + }, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, ].map((d) => ({ ...d, mockFns })); diff --git a/test/integrations/destinations/facebook_pixel/router/data.ts b/test/integrations/destinations/facebook_pixel/router/data.ts index ef6b9f8635..ee2f6968b1 100644 --- a/test/integrations/destinations/facebook_pixel/router/data.ts +++ b/test/integrations/destinations/facebook_pixel/router/data.ts @@ -1,3 +1,5 @@ +import { VERSION } from '../../../../../src/v0/destinations/facebook_pixel/config'; + export const mockFns = (_) => { // @ts-ignore jest.useFakeTimers().setSystemTime(new Date('2023-10-15')); @@ -193,7 +195,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { @@ -254,7 +256,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/dummyPixelId/events?access_token=09876', + endpoint: `https://graph.facebook.com/${VERSION}/dummyPixelId/events?access_token=09876`, headers: {}, params: {}, body: { diff --git a/test/integrations/destinations/fb/dataDelivery/data.ts b/test/integrations/destinations/fb/dataDelivery/data.ts index 70538a6ea0..f9405ba4b3 100644 --- a/test/integrations/destinations/fb/dataDelivery/data.ts +++ b/test/integrations/destinations/fb/dataDelivery/data.ts @@ -1,357 +1,372 @@ +import { VERSION } from '../../../../../src/v0/destinations/fb/config'; + export const data = [ { - "name": "fb", - "description": "Test 0", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "body": { - "XML": {}, - "JSON_ARRAY": {}, - "FORM": { - "event": "CUSTOM_APP_EVENTS", - "advertiser_id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "ud[em]": "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "ud[fn]": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", - "ud[ge]": "62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a", - "ud[ln]": "3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3", - "ud[ph]": "588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f", - "extinfo": "[\"a2\",\"\",\"\",\"\",\"8.1.0\",\"Redmi 6\",\"\",\"\",\"Banglalink\",640,480,\"1.23\",0,0,0,\"Europe/Berlin\"]", - "app_user_id": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "custom_events": "[{\"_logTime\":1567333011693,\"_eventName\":\"spin_result\",\"_valueToSum\":400,\"fb_currency\":\"GBP\",\"additional_bet_index\":0,\"battle_id\":\"N/A\",\"bet_amount\":9,\"bet_level\":1,\"bet_multiplier\":1,\"coin_balance\":9466052,\"current_module_name\":\"CasinoGameModule\",\"days_in_game\":0,\"extra_param\":\"N/A\",\"fb_profile\":\"0\",\"featureGameType\":\"N/A\",\"game_fps\":30,\"game_id\":\"fireEagleBase\",\"game_name\":\"FireEagleSlots\",\"gem_balance\":0,\"graphicsQuality\":\"HD\",\"idfa\":\"2bf99787-33d2-4ae2-a76a-c49672f97252\",\"internetReachability\":\"ReachableViaLocalAreaNetwork\",\"isLowEndDevice\":\"False\",\"is_auto_spin\":\"False\",\"is_turbo\":\"False\",\"isf\":\"False\",\"ishighroller\":\"False\",\"jackpot_win_amount\":90,\"jackpot_win_type\":\"Silver\",\"level\":6,\"lifetime_gem_balance\":0,\"no_of_spin\":1,\"player_total_battles\":0,\"player_total_shields\":0,\"start_date\":\"2019-08-01\",\"total_payments\":0,\"tournament_id\":\"T1561970819\",\"userId\":\"c82cbdff-e5be-4009-ac78-cdeea09ab4b1\",\"versionSessionCount\":2,\"win_amount\":0,\"fb_content_id\":[\"123\",\"345\",\"567\"]}]", - "advertiser_tracking_enabled": "0", - "application_tracking_enabled": "0" + name: 'fb', + description: 'Test 0', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + body: { + XML: {}, + JSON_ARRAY: {}, + FORM: { + event: 'CUSTOM_APP_EVENTS', + advertiser_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + 'ud[em]': '48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', + 'ud[fn]': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', + 'ud[ge]': '62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a', + 'ud[ln]': '3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3', + 'ud[ph]': '588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f', + extinfo: + '["a2","","","","8.1.0","Redmi 6","","","Banglalink",640,480,"1.23",0,0,0,"Europe/Berlin"]', + app_user_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + custom_events: + '[{"_logTime":1567333011693,"_eventName":"spin_result","_valueToSum":400,"fb_currency":"GBP","additional_bet_index":0,"battle_id":"N/A","bet_amount":9,"bet_level":1,"bet_multiplier":1,"coin_balance":9466052,"current_module_name":"CasinoGameModule","days_in_game":0,"extra_param":"N/A","fb_profile":"0","featureGameType":"N/A","game_fps":30,"game_id":"fireEagleBase","game_name":"FireEagleSlots","gem_balance":0,"graphicsQuality":"HD","idfa":"2bf99787-33d2-4ae2-a76a-c49672f97252","internetReachability":"ReachableViaLocalAreaNetwork","isLowEndDevice":"False","is_auto_spin":"False","is_turbo":"False","isf":"False","ishighroller":"False","jackpot_win_amount":90,"jackpot_win_type":"Silver","level":6,"lifetime_gem_balance":0,"no_of_spin":1,"player_total_battles":0,"player_total_shields":0,"start_date":"2019-08-01","total_payments":0,"tournament_id":"T1561970819","userId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","versionSessionCount":2,"win_amount":0,"fb_content_id":["123","345","567"]}]', + advertiser_tracking_enabled: '0', + application_tracking_enabled: '0', }, - "JSON": {} + JSON: {}, + }, + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities?access_token=invalid_access_token`, + files: {}, + headers: { + 'x-forwarded-for': '1.2.3.4', }, - "endpoint": "https://graph.facebook.com/v17.0/RudderFbApp/activities?access_token=invalid_access_token", - "files": {}, - "headers": { - "x-forwarded-for": "1.2.3.4" + method: 'POST', + statusCode: 200, + type: 'REST', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + version: '1', + params: { + destination: 'fb', }, - "method": "POST", - "statusCode": 200, - "type": "REST", - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "version": "1", - "params": { - "destination": "fb" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 400, - "body": { - "output": { - "status": 400, - "message": "Invalid OAuth 2.0 access token", - "destinationResponse": { - "error": { - "message": "The access token could not be decrypted", - "type": "OAuthException", - "code": 190, - "fbtrace_id": "fbpixel_trace_id" + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: 'Invalid OAuth 2.0 access token', + destinationResponse: { + error: { + message: 'The access token could not be decrypted', + type: 'OAuthException', + code: 190, + fbtrace_id: 'fbpixel_trace_id', }, - "status": 500 + status: 500, }, - "statTags": { - "destType": "FB", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "aborted", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } + statTags: { + destType: 'FB', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + }, + }, + }, + }, + }, }, { - "name": "fb", - "description": "Test 1", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "body": { - "XML": {}, - "JSON_ARRAY": {}, - "FORM": { - "event": "CUSTOM_APP_EVENTS", - "advertiser_id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "ud[em]": "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "ud[fn]": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", - "ud[ge]": "62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a", - "ud[ln]": "3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3", - "ud[ph]": "588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f", - "extinfo": "[\"a2\",\"\",\"\",\"\",\"8.1.0\",\"Redmi 6\",\"\",\"\",\"Banglalink\",640,480,\"1.23\",0,0,0,\"Europe/Berlin\"]", - "app_user_id": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "custom_events": "[{\"_logTime\":1567333011693,\"_eventName\":\"spin_result\",\"_valueToSum\":400,\"fb_currency\":\"GBP\",\"additional_bet_index\":0,\"battle_id\":\"N/A\",\"bet_amount\":9,\"bet_level\":1,\"bet_multiplier\":1,\"coin_balance\":9466052,\"current_module_name\":\"CasinoGameModule\",\"days_in_game\":0,\"extra_param\":\"N/A\",\"fb_profile\":\"0\",\"featureGameType\":\"N/A\",\"game_fps\":30,\"game_id\":\"fireEagleBase\",\"game_name\":\"FireEagleSlots\",\"gem_balance\":0,\"graphicsQuality\":\"HD\",\"idfa\":\"2bf99787-33d2-4ae2-a76a-c49672f97252\",\"internetReachability\":\"ReachableViaLocalAreaNetwork\",\"isLowEndDevice\":\"False\",\"is_auto_spin\":\"False\",\"is_turbo\":\"False\",\"isf\":\"False\",\"ishighroller\":\"False\",\"jackpot_win_amount\":90,\"jackpot_win_type\":\"Silver\",\"level\":6,\"lifetime_gem_balance\":0,\"no_of_spin\":1,\"player_total_battles\":0,\"player_total_shields\":0,\"start_date\":\"2019-08-01\",\"total_payments\":0,\"tournament_id\":\"T1561970819\",\"userId\":\"c82cbdff-e5be-4009-ac78-cdeea09ab4b1\",\"versionSessionCount\":2,\"win_amount\":0,\"fb_content_id\":[\"123\",\"345\",\"567\"]}]", - "advertiser_tracking_enabled": "0", - "application_tracking_enabled": "0" + name: 'fb', + description: 'Test 1', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + body: { + XML: {}, + JSON_ARRAY: {}, + FORM: { + event: 'CUSTOM_APP_EVENTS', + advertiser_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + 'ud[em]': '48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', + 'ud[fn]': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', + 'ud[ge]': '62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a', + 'ud[ln]': '3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3', + 'ud[ph]': '588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f', + extinfo: + '["a2","","","","8.1.0","Redmi 6","","","Banglalink",640,480,"1.23",0,0,0,"Europe/Berlin"]', + app_user_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + custom_events: + '[{"_logTime":1567333011693,"_eventName":"spin_result","_valueToSum":400,"fb_currency":"GBP","additional_bet_index":0,"battle_id":"N/A","bet_amount":9,"bet_level":1,"bet_multiplier":1,"coin_balance":9466052,"current_module_name":"CasinoGameModule","days_in_game":0,"extra_param":"N/A","fb_profile":"0","featureGameType":"N/A","game_fps":30,"game_id":"fireEagleBase","game_name":"FireEagleSlots","gem_balance":0,"graphicsQuality":"HD","idfa":"2bf99787-33d2-4ae2-a76a-c49672f97252","internetReachability":"ReachableViaLocalAreaNetwork","isLowEndDevice":"False","is_auto_spin":"False","is_turbo":"False","isf":"False","ishighroller":"False","jackpot_win_amount":90,"jackpot_win_type":"Silver","level":6,"lifetime_gem_balance":0,"no_of_spin":1,"player_total_battles":0,"player_total_shields":0,"start_date":"2019-08-01","total_payments":0,"tournament_id":"T1561970819","userId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","versionSessionCount":2,"win_amount":0,"fb_content_id":["123","345","567"]}]', + advertiser_tracking_enabled: '0', + application_tracking_enabled: '0', }, - "JSON": {} + JSON: {}, }, - "endpoint": "https://graph.facebook.com/v17.0/RudderFbApp/activities?access_token=my_access_token", - "files": {}, - "headers": { - "x-forwarded-for": "1.2.3.4" + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities?access_token=my_access_token`, + files: {}, + headers: { + 'x-forwarded-for': '1.2.3.4', + }, + method: 'POST', + statusCode: 200, + type: 'REST', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + version: '1', + params: { + destination: 'fb', }, - "method": "POST", - "statusCode": 200, - "type": "REST", - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "version": "1", - "params": { - "destination": "fb" - } }, - "method": "POST" - } + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: 'Request Processed Successfully', + destinationResponse: { + events_received: 1, + fbtrace_id: 'facebook_trace_id', + }, + }, + }, + }, }, - "output": { - "response": { - "status": 200, - "body": { - "output": { - "status": 200, - "message": "Request Processed Successfully", - "destinationResponse": { - "events_received": 1, - "fbtrace_id": "facebook_trace_id" - } - } - } - } - } }, { - "name": "fb", - "description": "Test 2", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "body": { - "XML": {}, - "JSON_ARRAY": {}, - "FORM": { - "event": "CUSTOM_APP_EVENTS", - "advertiser_id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "ud[em]": "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "ud[fn]": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", - "ud[ge]": "62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a", - "ud[ln]": "3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3", - "ud[ph]": "588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f", - "extinfo": "[\"a2\",\"\",\"\",\"\",\"8.1.0\",\"Redmi 6\",\"\",\"\",\"Banglalink\",640,480,\"1.23\",0,0,0,\"Europe/Berlin\"]", - "app_user_id": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "custom_events": "[{\"_logTime\":1567333011693,\"_eventName\":\"spin_result\",\"_valueToSum\":400,\"fb_currency\":\"GBP\",\"additional_bet_index\":0,\"battle_id\":\"N/A\",\"bet_amount\":9,\"bet_level\":1,\"bet_multiplier\":1,\"coin_balance\":9466052,\"current_module_name\":\"CasinoGameModule\",\"days_in_game\":0,\"extra_param\":\"N/A\",\"fb_profile\":\"0\",\"featureGameType\":\"N/A\",\"game_fps\":30,\"game_id\":\"fireEagleBase\",\"game_name\":\"FireEagleSlots\",\"gem_balance\":0,\"graphicsQuality\":\"HD\",\"idfa\":\"2bf99787-33d2-4ae2-a76a-c49672f97252\",\"internetReachability\":\"ReachableViaLocalAreaNetwork\",\"isLowEndDevice\":\"False\",\"is_auto_spin\":\"False\",\"is_turbo\":\"False\",\"isf\":\"False\",\"ishighroller\":\"False\",\"jackpot_win_amount\":90,\"jackpot_win_type\":\"Silver\",\"level\":6,\"lifetime_gem_balance\":0,\"no_of_spin\":1,\"player_total_battles\":0,\"player_total_shields\":0,\"start_date\":\"2019-08-01\",\"total_payments\":0,\"tournament_id\":\"T1561970819\",\"userId\":\"c82cbdff-e5be-4009-ac78-cdeea09ab4b1\",\"versionSessionCount\":2,\"win_amount\":0,\"fb_content_id\":[\"123\",\"345\",\"567\"]}]", - "advertiser_tracking_enabled": "0", - "application_tracking_enabled": "0" + name: 'fb', + description: 'Test 2', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + body: { + XML: {}, + JSON_ARRAY: {}, + FORM: { + event: 'CUSTOM_APP_EVENTS', + advertiser_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + 'ud[em]': '48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', + 'ud[fn]': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', + 'ud[ge]': '62c66a7a5dd70c3146618063c344e531e6d4b59e379808443ce962b3abd63c5a', + 'ud[ln]': '3547cb112ac4489af2310c0626cdba6f3097a2ad5a3b42ddd3b59c76c7a079a3', + 'ud[ph]': '588211a01b10feacbf7988d97a06e86c18af5259a7f457fd8759b7f7409a7d1f', + extinfo: + '["a2","","","","8.1.0","Redmi 6","","","Banglalink",640,480,"1.23",0,0,0,"Europe/Berlin"]', + app_user_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + custom_events: + '[{"_logTime":1567333011693,"_eventName":"spin_result","_valueToSum":400,"fb_currency":"GBP","additional_bet_index":0,"battle_id":"N/A","bet_amount":9,"bet_level":1,"bet_multiplier":1,"coin_balance":9466052,"current_module_name":"CasinoGameModule","days_in_game":0,"extra_param":"N/A","fb_profile":"0","featureGameType":"N/A","game_fps":30,"game_id":"fireEagleBase","game_name":"FireEagleSlots","gem_balance":0,"graphicsQuality":"HD","idfa":"2bf99787-33d2-4ae2-a76a-c49672f97252","internetReachability":"ReachableViaLocalAreaNetwork","isLowEndDevice":"False","is_auto_spin":"False","is_turbo":"False","isf":"False","ishighroller":"False","jackpot_win_amount":90,"jackpot_win_type":"Silver","level":6,"lifetime_gem_balance":0,"no_of_spin":1,"player_total_battles":0,"player_total_shields":0,"start_date":"2019-08-01","total_payments":0,"tournament_id":"T1561970819","userId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","versionSessionCount":2,"win_amount":0,"fb_content_id":["123","345","567"]}]', + advertiser_tracking_enabled: '0', + application_tracking_enabled: '0', }, - "JSON": {} + JSON: {}, + }, + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_timestamp_correct_access_token`, + files: {}, + headers: { + 'x-forwarded-for': '1.2.3.4', }, - "endpoint": "https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_timestamp_correct_access_token", - "files": {}, - "headers": { - "x-forwarded-for": "1.2.3.4" + method: 'POST', + statusCode: 200, + type: 'REST', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + version: '1', + params: { + destination: 'fb', }, - "method": "POST", - "statusCode": 200, - "type": "REST", - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "version": "1", - "params": { - "destination": "fb" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 400, - "body": { - "output": { - "status": 400, - "message": "Event Timestamp Too Old", - "destinationResponse": { - "error": { - "message": "Invalid parameter", - "type": "OAuthException", - "code": 100, - "error_subcode": 2804003, - "is_transient": false, - "error_user_title": "Event Timestamp Too Old", - "error_user_msg": "The timestamp for this event is too far in the past. Events need to be sent from your server within 7 days of when they occurred. Enter a timestamp that has occurred within the last 7 days.", - "fbtrace_id": "A6UyEgg_HdoiRX9duxcBOjb" + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: 'Event Timestamp Too Old', + destinationResponse: { + error: { + message: 'Invalid parameter', + type: 'OAuthException', + code: 100, + error_subcode: 2804003, + is_transient: false, + error_user_title: 'Event Timestamp Too Old', + error_user_msg: + 'The timestamp for this event is too far in the past. Events need to be sent from your server within 7 days of when they occurred. Enter a timestamp that has occurred within the last 7 days.', + fbtrace_id: 'A6UyEgg_HdoiRX9duxcBOjb', }, - "status": 400 + status: 400, }, - "statTags": { - "destType": "FB", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "aborted", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } + statTags: { + destType: 'FB', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + }, + }, + }, + }, + }, }, { - "name": "fb", - "description": "Test 3", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/1234567891234567/events?access_token=throttled_valid_access_token", - "headers": {}, - "body": { - "JSON": {}, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": { - "extinfo": "[\"a2\",\"\",\"\",\"\",\"8.1.0\",\"Redmi 6\",\"\",\"\",\"Banglalink\",0,100,\"50.00\",0,0,0,\"\"]", - "custom_events": "[{\"_logTime\":1567333011693,\"_eventName\":\"Viewed Screen\",\"fb_description\":\"Main.1233\"}]", - "ud[em]": "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "advertiser_tracking_enabled": "0", - "application_tracking_enabled": "0", - "event": "CUSTOM_APP_EVENTS" - } + name: 'fb', + description: 'Test 3', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=throttled_valid_access_token`, + headers: {}, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: { + extinfo: + '["a2","","","","8.1.0","Redmi 6","","","Banglalink",0,100,"50.00",0,0,0,""]', + custom_events: + '[{"_logTime":1567333011693,"_eventName":"Viewed Screen","fb_description":"Main.1233"}]', + 'ud[em]': '48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', + advertiser_tracking_enabled: '0', + application_tracking_enabled: '0', + event: 'CUSTOM_APP_EVENTS', + }, + }, + files: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + statusCode: 200, + params: { + destination: 'fb', }, - "files": {}, - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "statusCode": 200, - "params": { - "destination": "fb" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 429, - "body": { - "output": { - "status": 429, - "message": "API User Too Many Calls", - "destinationResponse": { - "error": { - "message": "User request limit reached", - "type": "OAuthException", - "code": 17, - "fbtrace_id": "facebook_px_trace_id_4" + output: { + response: { + status: 429, + body: { + output: { + status: 429, + message: 'API User Too Many Calls', + destinationResponse: { + error: { + message: 'User request limit reached', + type: 'OAuthException', + code: 17, + fbtrace_id: 'facebook_px_trace_id_4', }, - "status": 500 + status: 500, + }, + statTags: { + destType: 'FB', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'throttled', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', }, - "statTags": { - "destType": "FB", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "throttled", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } + }, + }, + }, + }, }, { - "name": "fb", - "description": "Test 4", - "feature": "dataDelivery", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://graph.facebook.com/v17.0/1234567891234567/events?access_token=invalid_account_id_valid_access_token", - "headers": {}, - "body": { - "JSON": {}, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": { - "extinfo": "[\"a2\",\"\",\"\",\"\",\"8.1.0\",\"Redmi 6\",\"\",\"\",\"Banglalink\",0,100,\"50.00\",0,0,0,\"\"]", - "custom_events": "[{\"_logTime\":1567333011693,\"_eventName\":\"Viewed Screen\",\"fb_description\":\"Main.1233\"}]", - "ud[em]": "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "advertiser_tracking_enabled": "0", - "application_tracking_enabled": "0", - "event": "CUSTOM_APP_EVENTS" - } + name: 'fb', + description: 'Test 4', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: `https://graph.facebook.com/${VERSION}/1234567891234567/events?access_token=invalid_account_id_valid_access_token`, + headers: {}, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: { + extinfo: + '["a2","","","","8.1.0","Redmi 6","","","Banglalink",0,100,"50.00",0,0,0,""]', + custom_events: + '[{"_logTime":1567333011693,"_eventName":"Viewed Screen","fb_description":"Main.1233"}]', + 'ud[em]': '48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', + advertiser_tracking_enabled: '0', + application_tracking_enabled: '0', + event: 'CUSTOM_APP_EVENTS', + }, + }, + files: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + statusCode: 200, + params: { + destination: 'fb', }, - "files": {}, - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "statusCode": 200, - "params": { - "destination": "fb" - } }, - "method": "POST" - } + method: 'POST', + }, }, - "output": { - "response": { - "status": 400, - "body": { - "output": { - "status": 400, - "message": "Object with ID 'PIXEL_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", - "destinationResponse": { - "error": { - "message": "Unsupported post request. Object with ID '1234567891234569' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api", - "type": "GraphMethodException", - "code": 100, - "error_subcode": 33, - "fbtrace_id": "facebook_px_trace_id_5" + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: + "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", + destinationResponse: { + error: { + message: + "Unsupported post request. Object with ID '1234567891234569' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api", + type: 'GraphMethodException', + code: 100, + error_subcode: 33, + fbtrace_id: 'facebook_px_trace_id_5', }, - "status": 400 + status: 400, }, - "statTags": { - "destType": "FB", - "errorCategory": "network", - "destinationId": "Non-determininable", - "workspaceId": "Non-determininable", - "errorType": "aborted", - "feature": "dataDelivery", - "implementation": "native", - "module": "destination" - } - } - } - } - } - } -] \ No newline at end of file + statTags: { + destType: 'FB', + errorCategory: 'network', + destinationId: 'Non-determininable', + workspaceId: 'Non-determininable', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + }, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/fb/network.ts b/test/integrations/destinations/fb/network.ts index 07a84a7e66..1a2f114d74 100644 --- a/test/integrations/destinations/fb/network.ts +++ b/test/integrations/destinations/fb/network.ts @@ -2,6 +2,7 @@ import { cloneDeep } from 'lodash'; import { getFormData } from '../../../../src/adapters/network'; import * as fbPixelNw from '../facebook_pixel/network'; import { data } from './dataDelivery/data'; +import { VERSION } from '../../../../src/v0/destinations/fb/config'; const fbPixelTcs = data .filter((_, i) => [2, 3, 4].includes(i)) @@ -19,7 +20,7 @@ const fbPixelTcs = data export const networkCallsData = [ { httpReq: { - url: 'https://graph.facebook.com/v17.0/RudderFbApp/activities?access_token=invalid_access_token', + url: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities?access_token=invalid_access_token`, data: getFormData(data[0].input.request.body.body.FORM).toString(), params: { destination: 'fb' }, headers: { 'User-Agent': 'RudderLabs' }, @@ -39,7 +40,7 @@ export const networkCallsData = [ }, { httpReq: { - url: 'https://graph.facebook.com/v17.0/RudderFbApp/activities?access_token=my_access_token', + url: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities?access_token=my_access_token`, data: getFormData(data[1].input.request.body.body.FORM).toString(), params: { destination: 'fb' }, headers: { 'x-forwarded-for': '1.2.3.4', 'User-Agent': 'RudderLabs' }, diff --git a/test/integrations/destinations/fb/processor/data.ts b/test/integrations/destinations/fb/processor/data.ts index 9b57f3ef78..a437b90855 100644 --- a/test/integrations/destinations/fb/processor/data.ts +++ b/test/integrations/destinations/fb/processor/data.ts @@ -1,3 +1,5 @@ +import { VERSION } from '../../../../../src/v0/destinations/fb/config'; + export const data = [ { name: 'fb', @@ -618,7 +620,7 @@ export const data = [ }, JSON: {}, }, - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, files: {}, headers: { 'x-forwarded-for': '1.2.3.4', @@ -803,7 +805,7 @@ export const data = [ }, JSON: {}, }, - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, files: {}, headers: { 'x-forwarded-for': '1.2.3.4', @@ -893,7 +895,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -993,7 +995,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1177,7 +1179,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1277,7 +1279,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1377,7 +1379,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1551,7 +1553,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1731,7 +1733,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { @@ -1831,7 +1833,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: { 'x-forwarded-for': '2.3.4.5', }, @@ -2153,7 +2155,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/RudderFbApp/activities', + endpoint: `https://graph.facebook.com/${VERSION}/RudderFbApp/activities`, headers: {}, params: {}, body: { diff --git a/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts b/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts new file mode 100644 index 0000000000..3066dae887 --- /dev/null +++ b/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts @@ -0,0 +1,575 @@ +import { getEndPoint } from '../../../../../src/v0/destinations/fb_custom_audience/config'; + +export const data = [ + { + name: 'fb_custom_audience', + description: 'successfully adding users to audience', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'successResponse', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: 'Request Processed Successfully', + destinationResponse: { + audience_id: 'aud1', + invalid_entry_samples: {}, + num_invalid_entries: 0, + num_received: 4, + session_id: '123', + }, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'user addition failed due to missing permission', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'permissionMissingError', + }, + params: { + access_token: 'BCD', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + ['2', '13', '2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN'], + ], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 400, + body: { + output: { + destinationResponse: { + error: { + code: 294, + message: + 'Missing permission. Please make sure you have ads_management permission and the application is included in the allowlist', + type: 'GraphMethodException', + }, + status: 400, + }, + message: + 'Missing permission. Please make sure you have ads_management permission and the application is included in the allowlist', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 400, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'user addition failed due to unavailable audience error', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'audienceUnavailableError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 400, + body: { + output: { + destinationResponse: { + error: { + code: 1487301, + message: + 'Custom Audience Unavailable: The custom audience you are trying to use has not been shared with your ad account', + type: 'GraphMethodException', + }, + status: 400, + }, + message: + 'Custom Audience Unavailable: The custom audience you are trying to use has not been shared with your ad account', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 400, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'user addition failed because the custom audience has been deleted', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'audienceDeletedError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 400, + body: { + output: { + destinationResponse: { + error: { + code: 1487366, + message: 'Custom Audience Has Been Deleted', + type: 'GraphMethodException', + }, + status: 400, + }, + message: 'Custom Audience Has Been Deleted', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 400, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'Failed to update the custom audience for unknown reason', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'failedToUpdateAudienceError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 400, + body: { + output: { + destinationResponse: { + error: { + code: 2650, + message: 'Failed to update the custom audience', + type: 'GraphMethodException', + }, + status: 400, + }, + message: 'Failed to update the custom audience', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 400, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: + 'Failed to update the custom audience as excessive number of parameters were passed in the request', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'parameterExceededError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 400, + body: { + output: { + destinationResponse: { + error: { + code: 105, + message: 'The number of parameters exceeded the maximum for this operation', + type: 'GraphMethodException', + }, + status: 400, + }, + message: 'The number of parameters exceeded the maximum for this operation', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 400, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'user update request is throttled due to too many calls to the ad account', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'tooManyCallsError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 429, + body: { + output: { + destinationResponse: { + error: { + code: 80003, + message: 'There have been too many calls to this ad-account.', + type: 'GraphMethodException', + }, + status: 429, + }, + message: 'There have been too many calls to this ad-account.', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'throttled', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 429, + }, + }, + }, + }, + }, + { + name: 'fb_custom_audience', + description: 'user having permission issue while updating audience', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'code200PermissionError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + }, + }, + output: { + response: { + status: 403, + body: { + output: { + destinationResponse: { + error: { + code: 200, + fbtrace_id: 'AFfWqjY-_y2Q92DsyJ4DQ6f', + message: '(#200) The current user can not update audience 23861283180290489', + type: 'OAuthException', + }, + status: 403, + }, + message: '(#200) The current user can not update audience 23861283180290489', + statTags: { + destType: 'FB_CUSTOM_AUDIENCE', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 403, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/fb_custom_audience/network.ts b/test/integrations/destinations/fb_custom_audience/network.ts new file mode 100644 index 0000000000..bbdc1ffc28 --- /dev/null +++ b/test/integrations/destinations/fb_custom_audience/network.ts @@ -0,0 +1,483 @@ +import { getEndPoint } from '../../../../src/v0/destinations/fb_custom_audience/config'; + +export const networkCallsData = [ + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'successResponse', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + audience_id: 'aud1', + session_id: '123', + num_received: 4, + num_invalid_entries: 0, + invalid_entry_samples: {}, + }, + status: 200, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'permissionMissingError', + }, + params: { + access_token: 'BCD', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBM', 'DOBD', 'DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2', '13', '2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 294, + message: + 'Missing permission. Please make sure you have ads_management permission and the application is included in the allowlist', + type: 'GraphMethodException', + }, + }, + status: 400, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'audienceUnavailableError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: ['DOBY', 'PHONE', 'GEN', 'FI', 'MADID', 'ZIP', 'ST', 'COUNTRY'], + data: [['2013', '@09432457768', 'f', 'Ms.', 'ABC', 'ZIP ', '123abc ', 'IN']], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 1487301, + message: + 'Custom Audience Unavailable: The custom audience you are trying to use has not been shared with your ad account', + type: 'GraphMethodException', + }, + }, + status: 400, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'audienceDeletedError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 1487366, + message: 'Custom Audience Has Been Deleted', + type: 'GraphMethodException', + }, + }, + status: 400, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'failedToUpdateAudienceError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 2650, + message: 'Failed to update the custom audience', + type: 'GraphMethodException', + }, + }, + status: 400, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'parameterExceededError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 105, + message: 'The number of parameters exceeded the maximum for this operation', + type: 'GraphMethodException', + }, + }, + status: 400, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'tooManyCallsError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 80003, + message: 'There have been too many calls to this ad-account.', + type: 'GraphMethodException', + }, + }, + status: 429, + }, + }, + { + httpReq: { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: getEndPoint('aud1'), + headers: { + 'test-dest-response-key': 'code200PermissionError', + }, + params: { + access_token: 'ABC', + payload: { + is_raw: true, + data_source: { + sub_type: 'ANYTHING', + }, + schema: [ + 'EMAIL', + 'DOBM', + 'DOBD', + 'DOBY', + 'PHONE', + 'GEN', + 'FI', + 'MADID', + 'ZIP', + 'ST', + 'COUNTRY', + ], + data: [ + [ + 'shrouti@abc.com', + '2', + '13', + '2013', + '@09432457768', + 'f', + 'Ms.', + 'ABC', + 'ZIP ', + '123abc ', + 'IN', + ], + ], + }, + }, + userId: '', + body: { + JSON: {}, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + }, + httpRes: { + data: { + error: { + code: 200, + fbtrace_id: 'AFfWqjY-_y2Q92DsyJ4DQ6f', + message: '(#200) The current user can not update audience 23861283180290489', + type: 'OAuthException', + }, + }, + status: 403, + }, + }, +]; diff --git a/test/integrations/destinations/fb_custom_audience/processor/data.ts b/test/integrations/destinations/fb_custom_audience/processor/data.ts index 17dcda3a98..4f892f6fef 100644 --- a/test/integrations/destinations/fb_custom_audience/processor/data.ts +++ b/test/integrations/destinations/fb_custom_audience/processor/data.ts @@ -1,3 +1,5 @@ +import { getEndPoint } from '../../../../../src/v0/destinations/fb_custom_audience/config'; + export const data = [ { name: 'fb_custom_audience', @@ -552,7 +554,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -607,7 +609,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -763,7 +765,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -818,7 +820,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -963,7 +965,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -993,7 +995,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1123,7 +1125,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1179,7 +1181,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1336,7 +1338,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -1391,7 +1393,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1547,7 +1549,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1602,7 +1604,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -1758,7 +1760,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -1813,7 +1815,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -1955,7 +1957,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -2097,7 +2099,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, userId: '', params: { @@ -2226,7 +2228,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -28302,7 +28304,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -34844,7 +34846,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -41386,7 +41388,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -47902,7 +47904,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', diff --git a/test/integrations/destinations/fb_custom_audience/router/data.ts b/test/integrations/destinations/fb_custom_audience/router/data.ts index c458b45c91..efefb80a89 100644 --- a/test/integrations/destinations/fb_custom_audience/router/data.ts +++ b/test/integrations/destinations/fb_custom_audience/router/data.ts @@ -1,3 +1,5 @@ +import { getEndPoint } from '../../../../../src/v0/destinations/fb_custom_audience/config'; + export const data = [ { name: 'fb_custom_audience', @@ -189,7 +191,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -241,7 +243,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -332,7 +334,7 @@ export const data = [ version: '1', type: 'REST', method: 'DELETE', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -383,7 +385,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -26748,7 +26750,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/23848494844100489/users', + endpoint: getEndPoint('23848494844100489'), headers: {}, params: { access_token: 'ABC', @@ -26874,7 +26876,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -33409,7 +33411,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -39944,7 +39946,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', @@ -46453,7 +46455,7 @@ export const data = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://graph.facebook.com/v17.0/aud1/users', + endpoint: getEndPoint('aud1'), headers: {}, params: { access_token: 'ABC', diff --git a/test/integrations/destinations/fullstory/processor/data.ts b/test/integrations/destinations/fullstory/processor/data.ts new file mode 100644 index 0000000000..d206b4a84f --- /dev/null +++ b/test/integrations/destinations/fullstory/processor/data.ts @@ -0,0 +1,462 @@ +export const data = [ + { + name: 'fullstory', + description: 'Complete track event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + 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, + 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: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + 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: {}, + }, + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.fullstory.com/v2/events', + headers: { + authorization: 'Basic dummyfullstoryAPIKey', + 'content-type': 'application/json', + }, + params: {}, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'fullstory', + description: 'Missing event name', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + 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: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'event is required for track call: Workflow: procWorkflow, Step: validateEventName, ChildStep: undefined, OriginalError: event is required for track call', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'FULLSTORY', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'fullstory', + description: 'Complete identify event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + 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: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + 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: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'fullstory', + description: 'Identify event with needed traits', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + 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: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + 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: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/gladly/network.ts b/test/integrations/destinations/gladly/network.ts new file mode 100644 index 0000000000..8c1c228738 --- /dev/null +++ b/test/integrations/destinations/gladly/network.ts @@ -0,0 +1,120 @@ +const deleteNwData = [ + { + httpReq: { + method: 'get', + url: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles?email=test%40rudderlabs.com', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + }, + }, + httpRes: { + data: [], + status: 200, + }, + }, + { + httpReq: { + method: 'get', + url: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles?email=test%2B2%40rudderlabs.com', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + }, + }, + httpRes: { + data: [ + { + emails: [ + { + normalized: 'test+2@rudderstack.com', + original: 'test+2@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@2', + name: 'Test Rudderstack', + phones: [], + id: 'user@2', + }, + ], + status: 200, + }, + }, + { + httpReq: { + method: 'get', + url: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles?phoneNumber=%2B91%209999999988', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + }, + }, + httpRes: { + data: [ + { + emails: [ + { + normalized: 'test+3@rudderstack.com', + original: 'test+3@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@3', + name: 'Test Rudderstack', + phones: [], + id: 'user@3', + }, + { + emails: [ + { + normalized: 'test+4@rudderstack.com', + original: 'test+4@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@4', + name: 'Test Rudderstack', + phones: [], + id: 'user@4', + }, + ], + status: 200, + }, + }, + { + httpReq: { + method: 'get', + url: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles?email=test6%40rudderlabs.com', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + }, + }, + httpRes: { + data: [], + status: 200, + }, + }, + { + httpReq: { + method: 'get', + url: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles?email=abc', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + }, + }, + httpRes: { + data: { + errors: [ + { + attr: 'email', + code: 'invalid', + detail: 'invalid email address', + }, + ], + }, + status: 400, + }, + }, +]; + +export const networkCallsData = [...deleteNwData]; diff --git a/test/integrations/destinations/gladly/processor/data.ts b/test/integrations/destinations/gladly/processor/data.ts new file mode 100644 index 0000000000..e81af999fb --- /dev/null +++ b/test/integrations/destinations/gladly/processor/data.ts @@ -0,0 +1,809 @@ +export const data = [ + { + name: 'gladly', + description: 'No message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + channel: 'web', + context: { + traits: { + age: 23, + email: 'adc@test.com', + firstName: 'Test', + }, + }, + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 1, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 1, + }, + statusCode: 400, + error: + 'message Type is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'GLADLY', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Unsupported message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + channel: 'web', + context: { + traits: { + age: 23, + email: 'adc@test.com', + firstName: 'Test', + }, + }, + event: 'Product Viewed', + type: 'track', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 2, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 2, + }, + statusCode: 400, + error: + 'message type track is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type track is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'GLADLY', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Missing config', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + channel: 'web', + context: { + traits: { + age: 23, + email: 'adc@test.com', + firstName: 'Test', + }, + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 3, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 3, + }, + statusCode: 400, + error: + 'User Name is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: User Name is not present. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'GLADLY', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Create customer with email as lookup field', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'externalCustomer@1', + channel: 'web', + context: { + traits: { + age: 23, + email: 'test@rudderlabs.com', + phone: '+91 9999999999', + firstName: 'Test', + lastName: 'Rudderlabs', + address: 'california usa', + }, + externalId: [ + { + id: 'user@1', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 4, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'california usa', + customAttributes: { age: 23 }, + emails: [{ original: 'test@rudderlabs.com' }], + externalCustomerId: 'externalCustomer@1', + id: 'user@1', + phones: [{ original: '+91 9999999999' }], + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'POST', + files: {}, + params: {}, + }, + metadata: { jobId: 4 }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Update customer with email as lookup field', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'externalCustomer@2', + channel: 'web', + context: { + traits: { + age: 23, + email: 'test+2@rudderlabs.com', + phone: '+91 9999999998', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + externalId: [ + { + id: 'user@2', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 5, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'New York, USA', + customAttributes: { age: 23 }, + emails: [{ original: 'test+2@rudderlabs.com' }], + externalCustomerId: 'externalCustomer@2', + phones: [{ original: '+91 9999999998' }], + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@2', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'PATCH', + files: {}, + params: {}, + }, + metadata: { jobId: 5 }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Update customer with phone as lookup field', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'externalCustomer@3', + channel: 'web', + context: { + traits: { + phone: '+91 9999999988', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + externalId: [ + { + id: 'user@3', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 6, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'New York, USA', + externalCustomerId: 'externalCustomer@3', + phones: [{ original: '+91 9999999988' }], + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@3', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'PATCH', + files: {}, + params: {}, + }, + metadata: { jobId: 6 }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Required values are not present in payload to create or update customer', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + traits: { + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + }, + type: 'identify', + anonymousId: '78c53c15-32a1-4b65-adac-bec2d7bb8fab', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 7, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 7, + }, + statusCode: 400, + error: + 'One of phone, email, userId or GladlyCustomerId is required for an identify call: Workflow: procWorkflow, Step: validatePayload, ChildStep: undefined, OriginalError: One of phone, email, userId or GladlyCustomerId is required for an identify call', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'GLADLY', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Multiple emails and phones are present in payload', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'externalCustomer@6', + channel: 'web', + context: { + traits: { + age: 23, + email: [ + 'test6@rudderlabs.com', + 'test6home@rudderlabs.com', + 'test6office@rudderlabs.com', + ], + phone: ['+91 8888888888', '+91 8888888889'], + firstName: 'Test', + lastName: 'Rudderlabs', + address: 'Germany', + }, + externalId: [ + { + id: 'user@6', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 8, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'Germany', + customAttributes: { age: 23 }, + emails: [ + { original: 'test6@rudderlabs.com' }, + { original: 'test6home@rudderlabs.com' }, + { original: 'test6office@rudderlabs.com' }, + ], + externalCustomerId: 'externalCustomer@6', + id: 'user@6', + phones: [{ original: '+91 8888888888' }, { original: '+91 8888888889' }], + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'POST', + files: {}, + params: {}, + }, + metadata: { jobId: 8 }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Create customer with only GladlyCustomerId', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + traits: { + firstName: 'Test', + lastName: 'Undefined', + address: 'India', + isProUser: true, + }, + externalId: [ + { + id: 'user@9', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 9, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'India', + customAttributes: { isProUser: true }, + id: 'user@9', + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'POST', + files: {}, + params: {}, + }, + metadata: { jobId: 9 }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'gladly', + description: 'Create customer with invalid lookup field value', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + traits: { + firstName: 'Test', + lastName: 'Undefined', + address: 'Pakistan', + email: 'abc', + }, + externalId: [ + { + id: 'user@10', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.757+05:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 10, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + JSON: { + address: 'Pakistan', + emails: [{ original: 'abc' }], + id: 'user@10', + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + userId: '', + version: '1', + type: 'REST', + method: 'POST', + files: {}, + params: {}, + }, + metadata: { jobId: 10 }, + statusCode: 200, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/gladly/router/data.ts b/test/integrations/destinations/gladly/router/data.ts new file mode 100644 index 0000000000..413c92e247 --- /dev/null +++ b/test/integrations/destinations/gladly/router/data.ts @@ -0,0 +1,604 @@ +export const data = [ + { + name: 'gladly', + description: 'Gladly router tests', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + userId: 'externalCustomer@1', + channel: 'web', + context: { + traits: { + age: 23, + email: 'test@rudderlabs.com', + phone: '+91 9999999999', + firstName: 'Test', + lastName: 'Rudderlabs', + address: 'california usa', + }, + externalId: [ + { + id: 'user@1', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 1, + }, + }, + { + message: { + userId: 'externalCustomer@2', + channel: 'web', + context: { + traits: { + age: 23, + email: 'test+2@rudderlabs.com', + phone: '+91 9999999998', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + externalId: [ + { + id: 'user@2', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 2, + }, + }, + { + message: { + userId: 'externalCustomer@3', + channel: 'web', + context: { + traits: { + phone: '+91 9999999988', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + externalId: [ + { + id: 'user@3', + type: 'GladlyCustomerId', + }, + ], + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 3, + }, + }, + ], + destType: 'gladly', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'california usa', + customAttributes: { + age: 23, + }, + emails: [ + { + original: 'test@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@1', + id: 'user@1', + phones: [ + { + original: '+91 9999999999', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 1, + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'New York, USA', + customAttributes: { + age: 23, + }, + emails: [ + { + original: 'test+2@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@2', + phones: [ + { + original: '+91 9999999998', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@2', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'PATCH', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 2, + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'New York, USA', + externalCustomerId: 'externalCustomer@3', + phones: [ + { + original: '+91 9999999988', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@3', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'PATCH', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 3, + }, + ], + statusCode: 200, + }, + ], + }, + }, + }, + }, + { + name: 'gladly', + description: 'Gladly rETL tests', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + userId: 'externalCustomer@1', + channel: 'web', + context: { + externalId: [ + { + id: 'externalCustomer@1', + identifierType: 'externalCustomerId', + }, + ], + mappedToDestination: true, + }, + traits: { + id: 'user@1', + emails: ['test@rudderlabs.com'], + phones: ['+91 9999999999'], + firstName: 'Test', + lastName: 'Rudderlabs', + address: 'california usa', + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 1, + }, + }, + { + message: { + userId: 'externalCustomer@2', + channel: 'web', + context: { + externalId: [ + { + id: 'externalCustomer@2', + identifierType: 'externalCustomerId', + }, + ], + mappedToDestination: true, + }, + traits: { + id: 'user@2', + emails: 'test+2@rudderlabs.com', + phones: '+91 9999999998', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 2, + }, + }, + { + message: { + userId: 'externalCustomer@3', + channel: 'web', + context: { + externalId: [ + { + id: 'externalCustomer@3', + identifierType: 'externalCustomerId', + }, + ], + mappedToDestination: true, + }, + traits: { + id: 'user@3', + phones: '+91 9999999988', + firstName: 'Test', + lastName: 'Rudderstack', + address: 'New York, USA', + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiToken: 'testApiToken', + userName: 'testUserName', + domain: 'rudderlabs.us-uat.gladly.qa', + }, + }, + metadata: { + jobId: 3, + }, + }, + ], + destType: 'gladly', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'california usa', + emails: [ + { + original: 'test@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@1', + id: 'user@1', + phones: [ + { + original: '+91 9999999999', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 1, + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'New York, USA', + emails: [ + { + original: 'test+2@rudderlabs.com', + }, + ], + externalCustomerId: 'externalCustomer@2', + phones: [ + { + original: '+91 9999999998', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@2', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'PATCH', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 2, + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + address: 'New York, USA', + externalCustomerId: 'externalCustomer@3', + phones: [ + { + original: '+91 9999999988', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://rudderlabs.us-uat.gladly.qa/api/v1/customer-profiles/user@3', + files: {}, + headers: { + Authorization: 'Basic dGVzdFVzZXJOYW1lOnRlc3RBcGlUb2tlbg==', + 'Content-Type': 'application/json', + }, + method: 'PATCH', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiToken: 'testApiToken', + domain: 'rudderlabs.us-uat.gladly.qa', + userName: 'testUserName', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: [ + { + jobId: 3, + }, + ], + statusCode: 200, + }, + ], + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/heap/processor/data.ts b/test/integrations/destinations/heap/processor/data.ts index be4f9c87bf..6efa45435c 100644 --- a/test/integrations/destinations/heap/processor/data.ts +++ b/test/integrations/destinations/heap/processor/data.ts @@ -15,7 +15,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -26,6 +26,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -104,6 +108,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -125,7 +133,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -136,6 +144,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -221,6 +233,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -242,7 +258,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: false, + cdkV2Enabled: false, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -253,6 +269,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -311,8 +331,14 @@ export const data = [ feature: 'processor', implementation: 'native', module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -334,7 +360,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: false, + cdkV2Enabled: false, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -345,6 +371,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -403,6 +433,8 @@ export const data = [ { error: 'message type page not supported for heap', statTags: { + destinationId: 'destId', + workspaceId: 'wspId', destType: 'HEAP', errorCategory: 'dataValidation', errorType: 'instrumentation', @@ -411,6 +443,10 @@ export const data = [ module: 'destination', }, statusCode: 400, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -432,7 +468,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -443,6 +479,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -530,6 +570,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -551,7 +595,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -562,6 +606,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -649,6 +697,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -670,7 +722,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -681,6 +733,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -771,6 +827,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -792,7 +852,7 @@ export const data = [ }, DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, DisplayName: 'Heap.io', ID: '1WTbl0l5GjOQKOvfmcGwk0T49kV', @@ -803,6 +863,10 @@ export const data = [ Name: 'heap test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -888,6 +952,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, diff --git a/test/integrations/destinations/kochava/processor/data.ts b/test/integrations/destinations/kochava/processor/data.ts index d17e9795ff..06b5667c2a 100644 --- a/test/integrations/destinations/kochava/processor/data.ts +++ b/test/integrations/destinations/kochava/processor/data.ts @@ -12,7 +12,7 @@ export const data = [ destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -22,6 +22,10 @@ export const data = [ Name: 'kochava test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, message: { anonymousId: 'sampath', channel: 'web', @@ -103,6 +107,10 @@ export const data = [ userId: 'sampath', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -144,12 +152,13 @@ export const data = [ sentAt: '2019-10-14T09:03:22.563Z', }, metadata: { - destinationId: '1WTpIHpH7NTBgjeiUPW1kCUgZGI', + destinationId: 'destId', + workspaceId: 'wspId', }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -170,18 +179,21 @@ export const data = [ status: 200, body: [ { - error: 'Bad event. Original error: message type "identify" not supported for "kochava"', + error: + 'message type identify is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type identify is not supported', metadata: { - destinationId: '1WTpIHpH7NTBgjeiUPW1kCUgZGI', + destinationId: 'destId', + workspaceId: 'wspId', }, statTags: { destType: 'KOCHAVA', errorCategory: 'dataValidation', - destinationId: '1WTpIHpH7NTBgjeiUPW1kCUgZGI', + destinationId: 'destId', errorType: 'instrumentation', feature: 'processor', - implementation: 'cdkV1', + implementation: 'cdkV2', module: 'destination', + workspaceId: 'wspId', }, statusCode: 400, }, @@ -225,10 +237,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -288,6 +304,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -329,10 +349,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -392,6 +416,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -444,10 +472,14 @@ export const data = [ type: 'screen', sentAt: '2020-03-12T09:05:13.042Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -511,6 +543,10 @@ export const data = [ userId: '5094f5704b9cf2b3', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -564,10 +600,14 @@ export const data = [ type: 'screen', sentAt: '2020-03-12T09:05:13.042Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -631,6 +671,10 @@ export const data = [ userId: '5094f5704b9cf2b3', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -687,7 +731,7 @@ export const data = [ destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -697,6 +741,10 @@ export const data = [ Name: 'kochava test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -750,6 +798,10 @@ export const data = [ userId: '5094f5704b9cf2b3', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -800,10 +852,14 @@ export const data = [ type: 'screen', sentAt: '2020-03-12T09:05:13.042Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -862,6 +918,10 @@ export const data = [ userId: '5094f5704b9cf2b3', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -914,7 +974,7 @@ export const data = [ destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -924,6 +984,10 @@ export const data = [ Name: 'kochava test', Transformations: [], }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -972,6 +1036,10 @@ export const data = [ userId: '5094f5704b9cf2b3', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1012,10 +1080,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -1074,6 +1146,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1115,10 +1191,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -1182,6 +1262,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1222,10 +1306,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -1289,6 +1377,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1329,10 +1421,14 @@ export const data = [ integrations: { All: true }, sentAt: '2019-10-14T09:03:22.563Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { Config: { apiKey: '' }, DestinationDefinition: { - Config: { cdkEnabled: true }, + Config: { cdkV2Enabled: true }, DisplayName: 'Kochava', ID: '1WTpBSTiL3iAUHUdW7rHT4sawgU', Name: 'KOCHAVA', @@ -1396,6 +1492,10 @@ export const data = [ userId: '00000000000000000000000000', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, diff --git a/test/integrations/destinations/launchdarkly_audience/processor/data.ts b/test/integrations/destinations/launchdarkly_audience/processor/data.ts new file mode 100644 index 0000000000..b26cf60f4c --- /dev/null +++ b/test/integrations/destinations/launchdarkly_audience/processor/data.ts @@ -0,0 +1,611 @@ +export const data = [ + { + name: 'launchdarkly_audience', + description: 'Unsupported event type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'abc', + properties: { + listData: { + add: [ + { + identifier: 'alex@email.com', + }, + { + identifier: 'ryan@email.com', + }, + { + identifier: 'van@email.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'Event type abc is not supported. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Event type abc is not supported. Aborting message.', + statTags: { + destType: 'LAUNCHDARKLY_AUDIENCE', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'List data is not passed', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: {}, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + '`listData` is not present inside properties. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: `listData` is not present inside properties. Aborting message.', + statTags: { + destType: 'LAUNCHDARKLY_AUDIENCE', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'List data is empty', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: { + listData: {}, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + '`listData` is empty. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: `listData` is empty. Aborting message.', + statTags: { + destType: 'LAUNCHDARKLY_AUDIENCE', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'Unsupported action type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: { + listData: { + update: [ + { + identifier: 'alex@email.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'Unsupported action type. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Unsupported action type. Aborting message.', + statTags: { + destType: 'LAUNCHDARKLY_AUDIENCE', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'Add members to the audience list', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + identifier: 'alex@email.com', + }, + { + identifier: 'ryan@email.com', + }, + { + identifier: 'van@email.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.launchdarkly.com/api/v2/segment-targets/rudderstack', + headers: { + Authorization: 'test-accessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + environmentId: 'test-clientSideId', + cohortId: 'test-audienceId', + cohortName: 'test-audienceName', + listData: { + add: [ + { + id: 'alex@email.com', + }, + { + id: 'ryan@email.com', + }, + { + id: 'van@email.com', + }, + ], + remove: [], + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'Remove members from the audience list', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: { + listData: { + remove: [ + { + identifier: 'alex@email.com', + }, + { + identifier: 'ryan@email.com', + }, + { + identifier: 'van@email.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.launchdarkly.com/api/v2/segment-targets/rudderstack', + headers: { + Authorization: 'test-accessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + environmentId: 'test-clientSideId', + cohortId: 'test-audienceId', + cohortName: 'test-audienceName', + listData: { + remove: [ + { + id: 'alex@email.com', + }, + { + id: 'ryan@email.com', + }, + { + id: 'van@email.com', + }, + ], + add: [], + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, + { + name: 'launchdarkly_audience', + description: 'Add/Remove members', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user123', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + identifier: 'alex@email.com', + }, + { + userId: 'user1', + }, + ], + remove: [ + { + identifier: 'ryan@email.com', + }, + { + identifier: 'van@email.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { + audienceId: 'test-audienceId', + audienceName: 'test-audienceName', + accessToken: 'test-accessToken', + clientSideId: 'test-clientSideId', + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.launchdarkly.com/api/v2/segment-targets/rudderstack', + headers: { + Authorization: 'test-accessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + environmentId: 'test-clientSideId', + cohortId: 'test-audienceId', + cohortName: 'test-audienceName', + listData: { + add: [ + { + id: 'alex@email.com', + }, + ], + remove: [ + { + id: 'ryan@email.com', + }, + { + id: 'van@email.com', + }, + ], + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/lytics/processor/data.ts b/test/integrations/destinations/lytics/processor/data.ts index e04b1aa413..344eecc3cd 100644 --- a/test/integrations/destinations/lytics/processor/data.ts +++ b/test/integrations/destinations/lytics/processor/data.ts @@ -112,12 +112,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -197,6 +201,10 @@ export const data = [ files: {}, userId: '', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, statusCode: 200, }, ], @@ -255,12 +263,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -295,6 +307,10 @@ export const data = [ files: {}, userId: '', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, statusCode: 200, }, ], @@ -361,12 +377,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -401,6 +421,10 @@ export const data = [ files: {}, userId: '', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, statusCode: 200, }, ], @@ -459,12 +483,17 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + ID: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq', + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -500,6 +529,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -557,12 +590,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -598,6 +635,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -655,12 +696,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -696,6 +741,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -753,7 +802,7 @@ export const data = [ }, metadata: { destinationID: 'ewksfdgDFSdvzsdmwsdfvcxj' }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], @@ -771,13 +820,14 @@ export const data = [ body: [ { error: - 'Unknown error occurred. Original error: "type" is a required field and it must be a string', + 'message Type is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting message.', metadata: { destinationID: 'ewksfdgDFSdvzsdmwsdfvcxj' }, statTags: { destType: 'LYTICS', - errorCategory: 'transformation', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', - implementation: 'cdkV1', + implementation: 'cdkV2', module: 'destination', }, statusCode: 400, @@ -839,7 +889,7 @@ export const data = [ }, metadata: { destinationID: 'ewksfdgDFSdvzsdmwsdfvcxj' }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], @@ -856,14 +906,15 @@ export const data = [ status: 200, body: [ { - error: 'Bad event. Original error: message type "gone" not supported for "lytics"', + error: + 'message type gone is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type gone is not supported', metadata: { destinationID: 'ewksfdgDFSdvzsdmwsdfvcxj' }, statTags: { destType: 'LYTICS', errorCategory: 'dataValidation', errorType: 'instrumentation', feature: 'processor', - implementation: 'cdkV1', + implementation: 'cdkV2', module: 'destination', }, statusCode: 400, @@ -984,12 +1035,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -1070,6 +1125,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1119,12 +1178,16 @@ export const data = [ destination_props: { AF: { af_uid: 'afUid' } }, }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -1160,6 +1223,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1209,12 +1276,16 @@ export const data = [ destination_props: { AF: { af_uid: 'afUid' } }, }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -1250,6 +1321,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -1309,12 +1384,16 @@ export const data = [ userId: 'rudder123', }, destination: { - DestinationDefinition: { Config: { cdkEnabled: true } }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, Config: { apiKey: 'dummyApiKey', stream: 'default' }, Enabled: true, Transformations: [], IsProcessorEnabled: true, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], method: 'POST', @@ -1352,6 +1431,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, diff --git a/test/integrations/destinations/marketo_static_list/processor/data.ts b/test/integrations/destinations/marketo_static_list/processor/data.ts index 51e4e87824..05fba54f6a 100644 --- a/test/integrations/destinations/marketo_static_list/processor/data.ts +++ b/test/integrations/destinations/marketo_static_list/processor/data.ts @@ -62,9 +62,9 @@ export const data = [ output: { version: '1', type: 'REST', - method: 'POST', + method: 'DELETE', endpoint: - 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3', + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6', headers: { Authorization: 'Bearer access_token_success', 'Content-Type': 'application/json', @@ -80,9 +80,9 @@ export const data = [ output: { version: '1', type: 'REST', - method: 'DELETE', + method: 'POST', endpoint: - 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6', + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3', headers: { Authorization: 'Bearer access_token_success', 'Content-Type': 'application/json', diff --git a/test/integrations/destinations/marketo_static_list/router/data.ts b/test/integrations/destinations/marketo_static_list/router/data.ts index 23b2ea8ea3..840ad773b3 100644 --- a/test/integrations/destinations/marketo_static_list/router/data.ts +++ b/test/integrations/destinations/marketo_static_list/router/data.ts @@ -1,7 +1,8 @@ export const data = [ { name: 'marketo_static_list', - description: 'Test 0', + description: + 'Test 0: Test audiencelist event with add and remove: Test eventtype lowercase and uppercase', feature: 'router', module: 'destination', version: 'v0', @@ -99,7 +100,7 @@ export const data = [ userId: 'user 1', anonymousId: 'anon-id-new', event: 'event1', - type: 'audiencelist', + type: 'audienceList', properties: { listData: { add: [ @@ -1172,50 +1173,6 @@ export const data = [ jobId: 2, }, }, - { - destination: { - ID: '1zia9wKshXt80YksLmUdJnr7IHI', - Name: 'test_marketo', - DestinationDefinition: { - ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', - Name: 'MARKETO', - DisplayName: 'Marketo', - transformAt: 'processor', - transformAtV1: 'processor', - }, - Config: { - clientId: 'marketo_client_id_success', - clientSecret: 'marketo_client_secret_success', - accountId: 'marketo_acct_id_success', - staticListId: 1234, - }, - Enabled: true, - Transformations: [], - IsProcessorEnabled: true, - }, - message: { - userId: 'user 1', - anonymousId: 'anon-id-new', - event: 'event1', - type: 'track', - properties: { - listData: { - remove: [1], - }, - enablePartialFailure: true, - }, - context: { - ip: '14.5.67.21', - library: { - name: 'http', - }, - }, - timestamp: '2020-02-02T00:23:09.544Z', - }, - metadata: { - jobId: 3, - }, - }, ], destType: 'marketo_static_list', }, @@ -1232,9 +1189,9 @@ export const data = [ { version: '1', type: 'REST', - method: 'POST', + method: 'DELETE', endpoint: - 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3', + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6', headers: { Authorization: 'Bearer access_token_success', 'Content-Type': 'application/json', @@ -1251,9 +1208,9 @@ export const data = [ { version: '1', type: 'REST', - method: 'DELETE', + method: 'POST', endpoint: - 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6', + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=1&id=2&id=3', headers: { Authorization: 'Bearer access_token_success', 'Content-Type': 'application/json', @@ -1371,18 +1328,325 @@ export const data = [ IsProcessorEnabled: true, }, }, + ], + }, + }, + }, + }, + { + name: 'marketo_static_list', + description: 'Test 1: Test record and audiencelist events in a single batch', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1001, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', + }, + externalId: [ + { + type: 'marketoStaticListId', + identifierType: 'id', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 1, + }, + }, { - metadata: [ - { - destInfo: { - authKey: '1zia9wKshXt80YksLmUdJnr7IHI', + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1002, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', }, - jobId: 3, + externalId: [ + { + type: 'marketoStaticListId', + identifierType: 'id', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', }, - ], + recordId: '3', + }, + metadata: { + jobId: 2, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1003, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', + }, + externalId: [ + { + type: 'marketoStaticListId', + identifierType: 'id', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 3, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + identifierType: 'id', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2001', + }, + type: 'record', + }, + metadata: { + jobId: 4, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + identifierType: 'id', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2002', + }, + type: 'record', + }, + metadata: { + jobId: 5, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + identifierType: 'id', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2003', + }, + type: 'record', + }, + metadata: { + jobId: 6, + }, + }, + { destination: { ID: '1zia9wKshXt80YksLmUdJnr7IHI', - Name: 'test_marketo', + Name: 'test_marketo_al', DestinationDefinition: { ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', Name: 'MARKETO', @@ -1400,12 +1664,1981 @@ export const data = [ Transformations: [], IsProcessorEnabled: true, }, - batched: false, - statusCode: 400, - error: 'Event type track is not supported', - statTags: { - errorCategory: 'dataValidation', - errorType: 'instrumentation', + message: { + userId: 'user 1', + anonymousId: 'anon-id-new', + event: 'event1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + id: 101, + }, + { + id: 102, + }, + { + id: 103, + }, + ], + remove: [ + { + id: 4, + }, + { + id: 5, + }, + { + id: 6, + }, + ], + }, + enablePartialFailure: true, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 7, + }, + }, + { + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo_al', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1234, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + userId: 'user 1', + anonymousId: 'anon-id-new', + event: 'event1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + id: 0, + }, + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + { + id: 4, + }, + { + id: 5, + }, + { + id: 6, + }, + { + id: 7, + }, + { + id: 8, + }, + { + id: 9, + }, + { + id: 10, + }, + { + id: 11, + }, + { + id: 12, + }, + { + id: 13, + }, + { + id: 14, + }, + { + id: 15, + }, + { + id: 16, + }, + { + id: 17, + }, + { + id: 18, + }, + { + id: 19, + }, + { + id: 20, + }, + { + id: 21, + }, + { + id: 22, + }, + { + id: 23, + }, + { + id: 24, + }, + { + id: 25, + }, + { + id: 26, + }, + { + id: 27, + }, + { + id: 28, + }, + { + id: 29, + }, + { + id: 30, + }, + { + id: 31, + }, + { + id: 32, + }, + { + id: 33, + }, + { + id: 34, + }, + { + id: 35, + }, + { + id: 36, + }, + { + id: 37, + }, + { + id: 38, + }, + { + id: 39, + }, + { + id: 40, + }, + { + id: 41, + }, + { + id: 42, + }, + { + id: 43, + }, + { + id: 44, + }, + { + id: 45, + }, + { + id: 46, + }, + { + id: 47, + }, + { + id: 48, + }, + { + id: 49, + }, + { + id: 50, + }, + { + id: 51, + }, + { + id: 52, + }, + { + id: 53, + }, + { + id: 54, + }, + { + id: 55, + }, + { + id: 56, + }, + { + id: 57, + }, + { + id: 58, + }, + { + id: 59, + }, + { + id: 60, + }, + { + id: 61, + }, + { + id: 62, + }, + { + id: 63, + }, + { + id: 64, + }, + { + id: 65, + }, + { + id: 66, + }, + { + id: 67, + }, + { + id: 68, + }, + { + id: 69, + }, + { + id: 70, + }, + { + id: 71, + }, + { + id: 72, + }, + { + id: 73, + }, + { + id: 74, + }, + { + id: 75, + }, + { + id: 76, + }, + { + id: 77, + }, + { + id: 78, + }, + { + id: 79, + }, + { + id: 80, + }, + { + id: 81, + }, + { + id: 82, + }, + { + id: 83, + }, + { + id: 84, + }, + { + id: 85, + }, + { + id: 86, + }, + { + id: 87, + }, + { + id: 88, + }, + { + id: 89, + }, + { + id: 90, + }, + { + id: 91, + }, + { + id: 92, + }, + { + id: 93, + }, + { + id: 94, + }, + { + id: 95, + }, + { + id: 96, + }, + { + id: 97, + }, + { + id: 98, + }, + { + id: 99, + }, + { + id: 100, + }, + { + id: 101, + }, + { + id: 102, + }, + { + id: 103, + }, + { + id: 104, + }, + { + id: 105, + }, + { + id: 106, + }, + { + id: 107, + }, + { + id: 108, + }, + { + id: 109, + }, + { + id: 110, + }, + { + id: 111, + }, + { + id: 112, + }, + { + id: 113, + }, + { + id: 114, + }, + { + id: 115, + }, + { + id: 116, + }, + { + id: 117, + }, + { + id: 118, + }, + { + id: 119, + }, + { + id: 120, + }, + { + id: 121, + }, + { + id: 122, + }, + { + id: 123, + }, + { + id: 124, + }, + { + id: 125, + }, + { + id: 126, + }, + { + id: 127, + }, + { + id: 128, + }, + { + id: 129, + }, + { + id: 130, + }, + { + id: 131, + }, + { + id: 132, + }, + { + id: 133, + }, + { + id: 134, + }, + { + id: 135, + }, + { + id: 136, + }, + { + id: 137, + }, + { + id: 138, + }, + { + id: 139, + }, + { + id: 140, + }, + { + id: 141, + }, + { + id: 142, + }, + { + id: 143, + }, + { + id: 144, + }, + { + id: 145, + }, + { + id: 146, + }, + { + id: 147, + }, + { + id: 148, + }, + { + id: 149, + }, + { + id: 150, + }, + { + id: 151, + }, + { + id: 152, + }, + { + id: 153, + }, + { + id: 154, + }, + { + id: 155, + }, + { + id: 156, + }, + { + id: 157, + }, + { + id: 158, + }, + { + id: 159, + }, + { + id: 160, + }, + { + id: 161, + }, + { + id: 162, + }, + { + id: 163, + }, + { + id: 164, + }, + { + id: 165, + }, + { + id: 166, + }, + { + id: 167, + }, + { + id: 168, + }, + { + id: 169, + }, + { + id: 170, + }, + { + id: 171, + }, + { + id: 172, + }, + { + id: 173, + }, + { + id: 174, + }, + { + id: 175, + }, + { + id: 176, + }, + { + id: 177, + }, + { + id: 178, + }, + { + id: 179, + }, + { + id: 180, + }, + { + id: 181, + }, + { + id: 182, + }, + { + id: 183, + }, + { + id: 184, + }, + { + id: 185, + }, + { + id: 186, + }, + { + id: 187, + }, + { + id: 188, + }, + { + id: 189, + }, + { + id: 190, + }, + { + id: 191, + }, + { + id: 192, + }, + { + id: 193, + }, + { + id: 194, + }, + { + id: 195, + }, + { + id: 196, + }, + { + id: 197, + }, + { + id: 198, + }, + { + id: 199, + }, + { + id: 200, + }, + { + id: 201, + }, + { + id: 202, + }, + { + id: 203, + }, + { + id: 204, + }, + { + id: 205, + }, + { + id: 206, + }, + { + id: 207, + }, + { + id: 208, + }, + { + id: 209, + }, + { + id: 210, + }, + { + id: 211, + }, + { + id: 212, + }, + { + id: 213, + }, + { + id: 214, + }, + { + id: 215, + }, + { + id: 216, + }, + { + id: 217, + }, + { + id: 218, + }, + { + id: 219, + }, + { + id: 220, + }, + { + id: 221, + }, + { + id: 222, + }, + { + id: 223, + }, + { + id: 224, + }, + { + id: 225, + }, + { + id: 226, + }, + { + id: 227, + }, + { + id: 228, + }, + { + id: 229, + }, + { + id: 230, + }, + { + id: 231, + }, + { + id: 232, + }, + { + id: 233, + }, + { + id: 234, + }, + { + id: 235, + }, + { + id: 236, + }, + { + id: 237, + }, + { + id: 238, + }, + { + id: 239, + }, + { + id: 240, + }, + { + id: 241, + }, + { + id: 242, + }, + { + id: 243, + }, + { + id: 244, + }, + { + id: 245, + }, + { + id: 246, + }, + { + id: 247, + }, + { + id: 248, + }, + { + id: 249, + }, + { + id: 250, + }, + { + id: 251, + }, + { + id: 252, + }, + { + id: 253, + }, + { + id: 254, + }, + { + id: 255, + }, + { + id: 256, + }, + { + id: 257, + }, + { + id: 258, + }, + { + id: 259, + }, + { + id: 260, + }, + { + id: 261, + }, + { + id: 262, + }, + { + id: 263, + }, + { + id: 264, + }, + { + id: 265, + }, + { + id: 266, + }, + { + id: 267, + }, + { + id: 268, + }, + { + id: 269, + }, + { + id: 270, + }, + { + id: 271, + }, + { + id: 272, + }, + { + id: 273, + }, + { + id: 274, + }, + { + id: 275, + }, + { + id: 276, + }, + { + id: 277, + }, + { + id: 278, + }, + { + id: 279, + }, + { + id: 280, + }, + { + id: 281, + }, + { + id: 282, + }, + { + id: 283, + }, + { + id: 284, + }, + { + id: 285, + }, + { + id: 286, + }, + { + id: 287, + }, + { + id: 288, + }, + { + id: 289, + }, + { + id: 290, + }, + { + id: 291, + }, + { + id: 292, + }, + { + id: 293, + }, + { + id: 294, + }, + { + id: 295, + }, + { + id: 296, + }, + { + id: 297, + }, + { + id: 298, + }, + { + id: 299, + }, + { + id: 300, + }, + { + id: 301, + }, + { + id: 302, + }, + { + id: 303, + }, + { + id: 304, + }, + { + id: 305, + }, + { + id: 306, + }, + { + id: 307, + }, + { + id: 308, + }, + { + id: 309, + }, + { + id: 310, + }, + { + id: 311, + }, + { + id: 312, + }, + { + id: 313, + }, + { + id: 314, + }, + { + id: 315, + }, + { + id: 316, + }, + { + id: 317, + }, + { + id: 318, + }, + { + id: 319, + }, + { + id: 320, + }, + { + id: 321, + }, + { + id: 322, + }, + { + id: 323, + }, + { + id: 324, + }, + { + id: 325, + }, + { + id: 326, + }, + { + id: 327, + }, + { + id: 328, + }, + { + id: 329, + }, + { + id: 330, + }, + { + id: 331, + }, + { + id: 332, + }, + { + id: 333, + }, + { + id: 334, + }, + { + id: 335, + }, + { + id: 336, + }, + { + id: 337, + }, + { + id: 338, + }, + { + id: 339, + }, + { + id: 340, + }, + { + id: 341, + }, + { + id: 342, + }, + { + id: 343, + }, + { + id: 344, + }, + { + id: 345, + }, + { + id: 346, + }, + { + id: 347, + }, + { + id: 348, + }, + { + id: 349, + }, + { + id: 350, + }, + ], + }, + enablePartialFailure: true, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 8, + }, + }, + ], + destType: 'marketo_static_list', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=2001&id=2002&id=2003', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 4, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 5, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 6, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1122/leads.json?id=1001&id=1002&id=1003', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 1, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 2, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 3, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=4&id=5&id=6', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=101&id=102&id=103', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 7, + destInfo: { + authKey: '1zia9wKshXt80YksLmUdJnr7IHI', + }, + }, + ], + batched: false, + statusCode: 200, + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo_al', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1234, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=0&id=1&id=2&id=3&id=4&id=5&id=6&id=7&id=8&id=9&id=10&id=11&id=12&id=13&id=14&id=15&id=16&id=17&id=18&id=19&id=20&id=21&id=22&id=23&id=24&id=25&id=26&id=27&id=28&id=29&id=30&id=31&id=32&id=33&id=34&id=35&id=36&id=37&id=38&id=39&id=40&id=41&id=42&id=43&id=44&id=45&id=46&id=47&id=48&id=49&id=50&id=51&id=52&id=53&id=54&id=55&id=56&id=57&id=58&id=59&id=60&id=61&id=62&id=63&id=64&id=65&id=66&id=67&id=68&id=69&id=70&id=71&id=72&id=73&id=74&id=75&id=76&id=77&id=78&id=79&id=80&id=81&id=82&id=83&id=84&id=85&id=86&id=87&id=88&id=89&id=90&id=91&id=92&id=93&id=94&id=95&id=96&id=97&id=98&id=99&id=100&id=101&id=102&id=103&id=104&id=105&id=106&id=107&id=108&id=109&id=110&id=111&id=112&id=113&id=114&id=115&id=116&id=117&id=118&id=119&id=120&id=121&id=122&id=123&id=124&id=125&id=126&id=127&id=128&id=129&id=130&id=131&id=132&id=133&id=134&id=135&id=136&id=137&id=138&id=139&id=140&id=141&id=142&id=143&id=144&id=145&id=146&id=147&id=148&id=149&id=150&id=151&id=152&id=153&id=154&id=155&id=156&id=157&id=158&id=159&id=160&id=161&id=162&id=163&id=164&id=165&id=166&id=167&id=168&id=169&id=170&id=171&id=172&id=173&id=174&id=175&id=176&id=177&id=178&id=179&id=180&id=181&id=182&id=183&id=184&id=185&id=186&id=187&id=188&id=189&id=190&id=191&id=192&id=193&id=194&id=195&id=196&id=197&id=198&id=199&id=200&id=201&id=202&id=203&id=204&id=205&id=206&id=207&id=208&id=209&id=210&id=211&id=212&id=213&id=214&id=215&id=216&id=217&id=218&id=219&id=220&id=221&id=222&id=223&id=224&id=225&id=226&id=227&id=228&id=229&id=230&id=231&id=232&id=233&id=234&id=235&id=236&id=237&id=238&id=239&id=240&id=241&id=242&id=243&id=244&id=245&id=246&id=247&id=248&id=249&id=250&id=251&id=252&id=253&id=254&id=255&id=256&id=257&id=258&id=259&id=260&id=261&id=262&id=263&id=264&id=265&id=266&id=267&id=268&id=269&id=270&id=271&id=272&id=273&id=274&id=275&id=276&id=277&id=278&id=279&id=280&id=281&id=282&id=283&id=284&id=285&id=286&id=287&id=288&id=289&id=290&id=291&id=292&id=293&id=294&id=295&id=296&id=297&id=298&id=299', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/1234/leads.json?id=300&id=301&id=302&id=303&id=304&id=305&id=306&id=307&id=308&id=309&id=310&id=311&id=312&id=313&id=314&id=315&id=316&id=317&id=318&id=319&id=320&id=321&id=322&id=323&id=324&id=325&id=326&id=327&id=328&id=329&id=330&id=331&id=332&id=333&id=334&id=335&id=336&id=337&id=338&id=339&id=340&id=341&id=342&id=343&id=344&id=345&id=346&id=347&id=348&id=349&id=350', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 8, + destInfo: { + authKey: '1zia9wKshXt80YksLmUdJnr7IHI', + }, + }, + ], + batched: false, + statusCode: 200, + destination: { + ID: '1zia9wKshXt80YksLmUdJnr7IHI', + Name: 'test_marketo_al', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1234, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + ], + }, + }, + }, + }, + { + name: 'marketo_static_list', + description: 'Test 2: Test record evemts', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + destType: 'marketo_static_list', + input: [ + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1001, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', + }, + externalId: [ + { + type: 'marketoStaticListId', + id: 'id001', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 1, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1002, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', + }, + externalId: [ + { + type: 'marketoStaticListId', + id: 'id002', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 2, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + type: 'record', + action: 'insert', + fields: { + id: 1003, + }, + channel: 'sources', + context: { + sources: { + job_id: '2VsZs4hyPpq7f1p8igrpmHsibHl', + version: 'feat.mirrorRetlEvent', + job_run_id: 'ck99nbd2kqiljdihhkh0', + task_run_id: 'ck99nbd2kqiljdihhkhg', + }, + externalId: [ + { + type: 'marketoStaticListId', + id: 'id001', + }, + ], + destinationFields: 'id', + mappedToDestination: 'true', + }, + recordId: '3', + }, + metadata: { + jobId: 3, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + id: 'id002', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2001', + }, + type: 'record', + }, + metadata: { + jobId: 4, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + id: 'id001', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2002', + }, + type: 'record', + }, + metadata: { + jobId: 5, + }, + }, + { + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + message: { + action: 'delete', + context: { + destinationFields: 'id', + externalId: [ + { + id: 'id002', + type: 'marketoStaticListId', + }, + ], + mappedToDestination: 'true', + sources: { + job_id: 'sf', + job_run_id: 'ck985bve58cvnti48120', + task_run_id: 'ck985bve58cvnti4812g', + version: '', + }, + }, + recordId: '2', + rudderId: '2', + fields: { + id: '2003', + }, + type: 'record', + }, + metadata: { + jobId: 6, + }, + }, + ], + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id001/leads.json?id=2002', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 5, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id001/leads.json?id=1001&id=1003', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 1, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 3, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'DELETE', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=2001&id=2003', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 4, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + { + jobId: 6, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://marketo_acct_id_success.mktorest.com/rest/v1/lists/id002/leads.json?id=1002', + headers: { + Authorization: 'Bearer access_token_success', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + metadata: [ + { + jobId: 2, + destInfo: { + authKey: '1zwa1wKshSt81YksKmUdJnr4IOK', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + ID: '1zwa1wKshSt81YksKmUdJnr4IOK', + Name: 'test_marketo_rc', + DestinationDefinition: { + ID: '1iVQvTRMsPPyJzwol0ifH93QTQ6', + Name: 'MARKETO', + DisplayName: 'Marketo', + transformAt: 'processor', + transformAtV1: 'processor', + }, + Config: { + clientId: 'marketo_client_id_success', + clientSecret: 'marketo_client_secret_success', + accountId: 'marketo_acct_id_success', + staticListId: 1122, + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, }, }, ], diff --git a/test/integrations/destinations/moengage/processor/data.ts b/test/integrations/destinations/moengage/processor/data.ts index 50b0361381..1ce8705f53 100644 --- a/test/integrations/destinations/moengage/processor/data.ts +++ b/test/integrations/destinations/moengage/processor/data.ts @@ -2777,4 +2777,105 @@ export const data = [ }, }, }, + { + name: 'moengage', + description: + 'when identify is sent without context, the event should not throw internal server error', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + event: 'identify', + sentAt: '2023-11-22T03:42:40.346Z', + userId: 'userId16', + channel: 'mobile', + rudderId: 'dummy-rudderId', + timestamp: '2023-11-22T03:42:31.470Z', + receivedAt: '2023-11-22T03:42:43.281Z', + request_ip: '114.122.233.48', + anonymousId: 'anon-dummyId-1', + integrations: { + All: true, + }, + originalTimestamp: '2023-11-22T03:42:28.535Z', + }, + destination: { + ID: '1iuTZs6eEZVMm6GjRBe6bNShaL3', + Name: 'MoEngage Testing', + DestinationDefinition: { + ID: '1iu4802Tx27kNC4KNYYou6D8jzL', + Name: 'MOENGAGE', + DisplayName: 'MoEngage', + Config: { + destConfig: { defaultConfig: ['apiId', 'apiKey', 'region'] }, + excludeKeys: [], + includeKeys: [], + supportedSourceTypes: [ + 'android', + 'ios', + 'web', + 'unity', + 'amp', + 'cloud', + 'reactnative', + ], + }, + }, + Config: { + apiId: 'W0ZHNMPI2O4KHJ48ZILZACRA', + apiKey: 'dummyApiKey', + eventDelivery: false, + eventDeliveryTS: 1602757086384, + region: 'US', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON: { + attributes: {}, + customer_id: 'userId16', + type: 'customer', + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api-01.moengage.com/v1/customer/W0ZHNMPI2O4KHJ48ZILZACRA', + files: {}, + headers: { + Authorization: 'Basic VzBaSE5NUEkyTzRLSEo0OFpJTFpBQ1JBOmR1bW15QXBpS2V5', + 'Content-Type': 'application/json', + 'MOE-APPKEY': 'W0ZHNMPI2O4KHJ48ZILZACRA', + }, + method: 'POST', + params: {}, + type: 'REST', + userId: 'anon-dummyId-1', + version: '1', + }, + statusCode: 200, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/mp/common.ts b/test/integrations/destinations/mp/common.ts index ad12566cc6..76ed25a760 100644 --- a/test/integrations/destinations/mp/common.ts +++ b/test/integrations/destinations/mp/common.ts @@ -20,4 +20,42 @@ const sampleDestination = { Transformations: [], }; -export { sampleDestination, defaultMockFns }; +const destinationWithSetOnceProperty = { + Config: { + apiSecret: 'dummySecret', + dataResidency: 'us', + identityMergeApi: 'simplified', + setOnceProperties: [ + { + property: 'nationality', + }, + { + property: 'firstName', + }, + { + property: 'address.city', + }, + ], + superProperties: [ + { + property: 'random', + }, + ], + token: 'dummyToken', + useNativeSDK: false, + useNewMapping: false, + userDeletionApi: 'engage', + whitelistedEvents: [], + }, + DestinationDefinition: { + DisplayName: 'Kiss Metrics', + ID: '1WhbSZ6uA3H5ChVifHpfL2H6sie', + Name: 'MIXPANEL', + }, + Enabled: true, + ID: '1WhcOCGgj9asZu850HvugU2C3Aq', + Name: 'Kiss Metrics', + Transformations: [], +}; + +export { sampleDestination, defaultMockFns, destinationWithSetOnceProperty }; diff --git a/test/integrations/destinations/mp/processor/data.ts b/test/integrations/destinations/mp/processor/data.ts index 2745c09ecc..a6ba51ee78 100644 --- a/test/integrations/destinations/mp/processor/data.ts +++ b/test/integrations/destinations/mp/processor/data.ts @@ -1,5 +1,5 @@ import { overrideDestination } from '../../../testUtils'; -import { sampleDestination, defaultMockFns } from '../common'; +import { sampleDestination, defaultMockFns, destinationWithSetOnceProperty } from '../common'; export const data = [ { @@ -5852,4 +5852,273 @@ export const data = [ }, }, }, + { + name: 'mp', + description: 'Test Set Once Property', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + description: 'Alias: with property beyond and within exclusion list', + destination: destinationWithSetOnceProperty, + message: { + anonymousId: 'e6ab2c5e-2cda-44a9-a962-e2f67df78bca', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.5', + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.5', + }, + locale: 'en-GB', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + traits: { + address: { + city: 'Disney', + }, + country: 'USA', + email: 'TestSanity@disney.com', + firstName: 'Mickey test', + lastName: 'VarChange', + createdAt: '2020-01-23T08:54:02.362Z', + nationality: 'USA', + random: 'superProp', + }, + page: { + path: '/destinations/mixpanel', + referrer: '', + search: '', + title: '', + url: 'https://docs.rudderstack.com/destinations/mixpanel', + category: 'destination', + initial_referrer: 'https://docs.rudderstack.com', + initial_referring_domain: 'docs.rudderstack.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36', + }, + integrations: { + All: true, + }, + page: { + path: '/destinations/mixpanel', + referrer: '', + search: '', + title: '', + url: 'https://docs.rudderstack.com/destinations/mixpanel', + category: 'destination', + initial_referrer: 'https://docs.rudderstack.com', + initial_referring_domain: 'docs.rudderstack.com', + }, + request_ip: '[::1]:53709', + type: 'identify', + userId: 'Santiy', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.mixpanel.com/engage/', + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: { + batch: + '[{"$set_once":{"$first_name":"Mickey test","$city":"Disney","nationality":"USA"},"$token":"dummyToken","$distinct_id":"Santiy"}]', + }, + XML: {}, + FORM: {}, + }, + files: {}, + userId: 'Santiy', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.mixpanel.com/engage/', + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: { + batch: + '[{"$set":{"$created":"2020-01-23T08:54:02.362Z","$email":"TestSanity@disney.com","$country_code":"USA","$initial_referrer":"https://docs.rudderstack.com","$initial_referring_domain":"docs.rudderstack.com","random":"superProp","$lastName":"VarChange","$browser":"Chrome","$browser_version":"79.0.3945.117"},"$token":"dummyToken","$distinct_id":"Santiy","$ip":"0.0.0.0","$time":null}]', + }, + XML: {}, + FORM: {}, + }, + files: {}, + userId: 'Santiy', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'mp', + description: 'Test Set Once Property with anonymousId', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + description: 'Alias: with property beyond and within exclusion list', + destination: destinationWithSetOnceProperty, + message: { + anonymousId: 'dummyAnnonymousId', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.5', + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.5', + }, + locale: 'en-GB', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + traits: { + address: { + city: 'Disney', + }, + country: 'USA', + email: 'TestSanity@disney.com', + firstName: 'Mickey test', + lastName: 'VarChange', + createdAt: '2020-01-23T08:54:02.362Z', + nationality: 'USA', + random: 'superProp', + }, + page: { + path: '/destinations/mixpanel', + referrer: '', + search: '', + title: '', + url: 'https://docs.rudderstack.com/destinations/mixpanel', + category: 'destination', + initial_referrer: 'https://docs.rudderstack.com', + initial_referring_domain: 'docs.rudderstack.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36', + }, + integrations: { + All: true, + }, + page: { + path: '/destinations/mixpanel', + referrer: '', + search: '', + title: '', + url: 'https://docs.rudderstack.com/destinations/mixpanel', + category: 'destination', + initial_referrer: 'https://docs.rudderstack.com', + initial_referring_domain: 'docs.rudderstack.com', + }, + request_ip: '[::1]:53709', + type: 'identify', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.mixpanel.com/engage/', + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: { + batch: + '[{"$set_once":{"$first_name":"Mickey test","$city":"Disney","nationality":"USA"},"$token":"dummyToken","$distinct_id":"$device:dummyAnnonymousId"}]', + }, + XML: {}, + FORM: {}, + }, + files: {}, + userId: 'dummyAnnonymousId', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.mixpanel.com/engage/', + headers: {}, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: { + batch: + '[{"$set":{"$created":"2020-01-23T08:54:02.362Z","$email":"TestSanity@disney.com","$country_code":"USA","$initial_referrer":"https://docs.rudderstack.com","$initial_referring_domain":"docs.rudderstack.com","random":"superProp","$lastName":"VarChange","$browser":"Chrome","$browser_version":"79.0.3945.117"},"$token":"dummyToken","$distinct_id":"$device:dummyAnnonymousId","$ip":"0.0.0.0","$time":null}]', + }, + XML: {}, + FORM: {}, + }, + files: {}, + userId: 'dummyAnnonymousId', + }, + statusCode: 200, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/new_relic/processor/data.ts b/test/integrations/destinations/new_relic/processor/data.ts new file mode 100644 index 0000000000..7eb4099e3b --- /dev/null +++ b/test/integrations/destinations/new_relic/processor/data.ts @@ -0,0 +1,882 @@ +export const data = [ + { + name: 'new_relic', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'first', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: true, + sendUserIdanonymousId: true, + dataCenter: 'us', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.newrelic.com/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'first', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 123, + timestamp: 1580602989, + eventType: 'rudderstack', + userId: 'identified user id', + anonymousId: 'anon-id-new', + 'traits.trait1': 'new-val', + ip: '14.5.67.21', + 'library.name': 'http', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'second', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 'test', + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: false, + sendUserIdanonymousId: false, + dataCenter: 'us', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.newrelic.com/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'second', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 'test', + timestamp: 1580602989, + eventType: 'rudderstack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'test', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: 'rudder-testing', + sendDeviceContext: false, + sendUserIdanonymousId: false, + dataCenter: 'us', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.newrelic.com/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'test', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 123, + timestamp: 1580602989, + eventType: 'rudder-testing', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 3', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'first', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: true, + sendUserIdanonymousId: true, + dataCenter: 'eu', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.eu01.nr-data.net/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'first', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 123, + timestamp: 1580602989, + eventType: 'rudderstack', + userId: 'identified user id', + anonymousId: 'anon-id-new', + 'traits.trait1': 'new-val', + ip: '14.5.67.21', + 'library.name': 'http', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 4', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'second', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 'test', + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: false, + sendUserIdanonymousId: false, + dataCenter: 'eu', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.eu01.nr-data.net/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'second', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 'test', + timestamp: 1580602989, + eventType: 'rudderstack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 5', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'test', + userId: 'identified user id', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: 'rudder-testing', + sendDeviceContext: false, + sendUserIdanonymousId: true, + dataCenter: 'eu', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.eu01.nr-data.net/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'test', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 123, + timestamp: 1580602989, + eventType: 'rudder-testing', + userId: 'identified user id', + anonymousId: 'anon-id-new', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 6', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'test', + type: 'track', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + properties: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: true, + sendUserIdanonymousId: true, + dataCenter: 'us', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://insights-collector.newrelic.com/v1/accounts/12345/events', + headers: { + 'Api-Key': '11111122702j2a2U2K2C7H', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'test', + abc: '123', + 'key.abc': 123, + 'array[0].abc': 123, + 'array[1].def': 123, + timestamp: 1580602989, + eventType: 'rudderstack', + anonymousId: 'anon-id-new', + 'traits.trait1': 'new-val', + ip: '14.5.67.21', + 'library.name': 'http', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'new_relic', + description: 'Test 7', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'first', + userId: 'identified user id', + type: 'identify', + anonymousId: 'anon-id-new', + context: { + traits: { + trait1: 'new-val', + }, + ip: '14.5.67.21', + library: { + name: 'http', + }, + }, + traits: { + abc: '123', + key: { + abc: 123, + }, + array: [ + { + abc: 123, + }, + { + def: 123, + }, + ], + }, + timestamp: '2020-02-02T00:23:09.544Z', + sentAt: '2020-02-02T00:23:09.544Z', + originalTimestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + accountId: '12345', + insertKey: '11111122702j2a2U2K2C7H', + customEventType: '', + sendDeviceContext: true, + sendUserIdanonymousId: true, + dataCenter: 'us', + }, + Enabled: true, + Transformations: [], + IsProcessorEnabled: true, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + statusCode: 400, + error: + 'message type identify is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type identify is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + implementation: 'cdkV2', + destType: 'NEW_RELIC', + module: 'destination', + feature: 'processor', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/optimizely_fullstack/processor/data.ts b/test/integrations/destinations/optimizely_fullstack/processor/data.ts index 09749178ee..52fbdfe5fe 100644 --- a/test/integrations/destinations/optimizely_fullstack/processor/data.ts +++ b/test/integrations/destinations/optimizely_fullstack/processor/data.ts @@ -55,7 +55,8 @@ export const data = [ 'Data File Url is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Data File Url is not present. Aborting', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -121,7 +122,8 @@ export const data = [ 'Variation ID is not present in the integrations object: Workflow: procWorkflow, Step: validateInputForIdentify, ChildStep: undefined, OriginalError: Variation ID is not present in the integrations object', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -186,7 +188,8 @@ export const data = [ 'Account ID is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Account ID is not present. Aborting', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -251,7 +254,8 @@ export const data = [ 'Campaign ID is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Campaign ID is not present. Aborting', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -316,7 +320,8 @@ export const data = [ 'Experiment ID is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Experiment ID is not present. Aborting', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -388,7 +393,8 @@ export const data = [ "Both 'Track Categorized Pages' and 'Track Named Pages' toggles are disabled in webapp. Please enable at one of them to send page/screen events to Optimizely.: Workflow: procWorkflow, Step: validateInputForPageAndScreen, ChildStep: undefined, OriginalError: Both 'Track Categorized Pages' and 'Track Named Pages' toggles are disabled in webapp. Please enable at one of them to send page/screen events to Optimizely.", statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -467,7 +473,8 @@ export const data = [ "UserId is required for event tracking when the 'Track Known Users' setting is enabled. Please include a 'userId' in your event payload: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: UserId is required for event tracking when the 'Track Known Users' setting is enabled. Please include a 'userId' in your event payload", statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -530,7 +537,8 @@ export const data = [ 'Event is not present. Aborting.: Workflow: procWorkflow, Step: validateInputForTrack, ChildStep: undefined, OriginalError: Event is not present. Aborting.', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -591,15 +599,16 @@ export const data = [ body: [ { error: - '{"message":"Data File Lookup Failed due to {\\"code\\":\\"document_not_found\\",\\"message\\":\\"document_not_found\\"}: Workflow: procWorkflow, Step: dataFile, ChildStep: undefined, OriginalError: Data File Lookup Failed due to {\\"code\\":\\"document_not_found\\",\\"message\\":\\"document_not_found\\"}","destinationResponse":{"code":"document_not_found","message":"document_not_found"}}', + '{"message":"{\\"message\\":\\"Data File Lookup Failed due to {\\\\\\"code\\\\\\":\\\\\\"document_not_found\\\\\\",\\\\\\"message\\\\\\":\\\\\\"document_not_found\\\\\\"}: Workflow: procWorkflow, Step: dataFile, ChildStep: undefined, OriginalError: Data File Lookup Failed due to {\\\\\\"code\\\\\\":\\\\\\"document_not_found\\\\\\",\\\\\\"message\\\\\\":\\\\\\"document_not_found\\\\\\"}\\",\\"destinationResponse\\":{\\"code\\":\\"document_not_found\\",\\"message\\":\\"document_not_found\\"}}","destinationResponse":{"code":"document_not_found","message":"document_not_found"}}', statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'network', + errorType: 'aborted', feature: 'processor', implementation: 'cdkV2', module: 'destination', }, - statusCode: 400, + statusCode: 404, metadata: { jobId: 10, }, @@ -670,7 +679,8 @@ export const data = [ "Event 'product_added' is not present in data file. Make sure event exists in Optimizely.: Workflow: procWorkflow, Step: prepareTrackPayload, ChildStep: optimizelyEvent, OriginalError: Event 'product_added' is not present in data file. Make sure event exists in Optimizely.", statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -1162,7 +1172,8 @@ export const data = [ metadata: { jobId: 15 }, statTags: { destType: 'OPTIMIZELY_FULLSTACK', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', diff --git a/test/integrations/destinations/ortto/processor/data.ts b/test/integrations/destinations/ortto/processor/data.ts index 9c3d00b874..e7c71c7355 100644 --- a/test/integrations/destinations/ortto/processor/data.ts +++ b/test/integrations/destinations/ortto/processor/data.ts @@ -347,7 +347,8 @@ export const data = [ { statTags: { destType: 'ORTTO', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -505,7 +506,8 @@ export const data = [ { statTags: { destType: 'ORTTO', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -667,7 +669,8 @@ export const data = [ { statTags: { destType: 'ORTTO', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -829,7 +832,8 @@ export const data = [ { statTags: { destType: 'ORTTO', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -1216,7 +1220,8 @@ export const data = [ { statTags: { destType: 'ORTTO', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', diff --git a/test/integrations/destinations/pinterest_tag/processor/data.ts b/test/integrations/destinations/pinterest_tag/processor/data.ts index 344d4ff507..17ab83b2e9 100644 --- a/test/integrations/destinations/pinterest_tag/processor/data.ts +++ b/test/integrations/destinations/pinterest_tag/processor/data.ts @@ -44,6 +44,7 @@ export const data = [ order_id: '50314b8e9bcf000000000000', requestIP: '123.0.0.0', optOutType: 'LDP', + clickId: 'dummy_clickId', products: [ { sku: '45790-32', @@ -132,6 +133,7 @@ export const data = [ '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090', ], client_user_agent: 'chrome', + click_id: 'dummy_clickId', ge: ['1b16b1df538ba12dc3f97edbb85caa7050d46c148134290feba80f8236c83db9'], }, custom_data: { @@ -562,7 +564,8 @@ export const data = [ metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -679,7 +682,8 @@ export const data = [ 'It is required at least one of em, hashed_maids or pair of client_ip_address and client_user_agent: Workflow: procWorkflow, Step: validateUserFields, ChildStep: undefined, OriginalError: It is required at least one of em, hashed_maids or pair of client_ip_address and client_user_agent', statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -958,7 +962,8 @@ export const data = [ metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -1077,7 +1082,8 @@ export const data = [ metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -1197,7 +1203,8 @@ export const data = [ 'Action source must be one of app_android, app_ios, web, offline: Workflow: procWorkflow, Step: validateCommonFields, ChildStep: undefined, OriginalError: Action source must be one of app_android, app_ios, web, offline', statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -3234,7 +3241,8 @@ export const data = [ metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -3321,7 +3329,8 @@ export const data = [ metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'configuration', feature: 'processor', implementation: 'cdkV2', module: 'destination', @@ -3417,11 +3426,139 @@ export const data = [ body: [ { metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, + output: { + body: { + JSON: { + event_time: 1597383030, + action_source: 'web', + event_id: '7208bbb6-2c4e-45bb-bf5b-ad426f3593e9', + app_id: '429047995', + user_data: { + em: ['48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08'], + ph: ['d164bbe036663cb5c96835e9ccc6501e9a521127ea62f6359744928ba932413b'], + ln: ['dcf000c2386fb76d22cefc0d118a8511bb75999019cd373df52044bccd1bd251'], + fn: ['9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'], + ct: ['6689106ca7922c30b2fd2c175c85bc7fc2d52cc4941bdd7bb622c6cdc6284a85'], + st: ['3b45022ab36728cdae12e709e945bba267c50ee8a91e6e4388539a8e03a3fdcd'], + zp: ['1a4292e00780e18d00e76fde9850aee5344e939ba593333cd5e4b4aa2cd33b0c'], + country: ['582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf'], + hashed_maids: [ + '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090', + ], + client_user_agent: 'chrome', + }, + custom_data: { + num_items: 0, + contents: [ + { + quantity: 1, + item_price: 'undefined', + }, + ], + currency: 'USD', + value: '27.5', + order_id: '50314b8e9bcf000000000000', + }, + event_name: 'custom event', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.pinterest.com/v5/ad_accounts/accountId123/events', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer conversionToken123', + }, + params: {}, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'pinterest_tag', + description: 'Test 26', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'track', + channel: 'web', + sentAt: '2020-08-14T05:30:30.118Z', + context: { + source: 'test', + userAgent: 'chrome', + traits: { + anonymousId: '50be5c78-6c3f-4b60-be84-97805a316fb1', + email: 'abc@gmail.com', + phone: '+1234589947', + ge: 'male', + db: '19950715', + lastname: 'Rudderlabs', + firstName: 'Test', + address: { city: 'Kolkata', state: 'WB', zip: '700114', country: 'IN' }, + }, + device: { advertisingId: 'abc123' }, + library: { name: 'rudder-sdk-ruby-sync', version: '1.0.6' }, + }, + messageId: '7208bbb6-2c4e-45bb-bf5b-ad426f3593e9', + timestamp: '2020-08-14T05:30:30.118Z', + anonymousId: '50be5c78-6c3f-4b60-be84-97805a316fb1', + integrations: { All: true }, + }, + destination: { + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + ID: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq', + Name: 'PINTEREST_TAG', + Config: { + sendAsTestEvent: false, + tagId: '123456789', + apiVersion: 'newApi', + adAccountId: 'accountId123', + conversionToken: 'conversionToken123', + appId: '429047995', + enhancedMatch: true, + enableDeduplication: true, + deduplicationKey: 'messageId', + sendingUnHashedData: true, + sendAsCustomEvent: false, + customProperties: [{ properties: 'presentclass' }, { properties: 'presentgrade' }], + eventsMapping: [{ from: 'ABC Searched', to: 'WatchVideo' }], + }, + Enabled: true, + Transformations: [], + }, + metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { error: - "custom event is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting: Workflow: procWorkflow, Step: eventNames, ChildStep: undefined, OriginalError: custom event is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting", + 'event_name could not be mapped. Aborting.: Workflow: procWorkflow, Step: validateInputForTrack, ChildStep: undefined, OriginalError: event_name could not be mapped. Aborting.', + metadata: { destintionId: '1pYpzzvcn7AQ2W9GGIAZSsN6Mfq' }, statTags: { destType: 'PINTEREST_TAG', - errorCategory: 'platform', + errorCategory: 'dataValidation', + errorType: 'instrumentation', feature: 'processor', implementation: 'cdkV2', module: 'destination', diff --git a/test/integrations/destinations/pinterest_tag/step/data.ts b/test/integrations/destinations/pinterest_tag/step/data.ts index b5d6f5186f..cbd0b243bb 100644 --- a/test/integrations/destinations/pinterest_tag/step/data.ts +++ b/test/integrations/destinations/pinterest_tag/step/data.ts @@ -3339,17 +3339,58 @@ export const data = [ status: 200, body: [ { - error: - "custom event is not mapped in UI. Make sure to map the event in UI or enable the 'send as custom event' setting", - statTags: { - destType: 'PINTEREST_TAG', - errorCategory: 'dataValidation', - errorType: 'configuration', - feature: 'processor', - implementation: 'native', - module: 'destination', + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.pinterest.com/v5/ad_accounts/accountId123/events', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer conversionToken123', + }, + params: {}, + body: { + JSON: { + event_name: 'custom event', + event_time: 1597383030, + action_source: 'web', + event_id: '7208bbb6-2c4e-45bb-bf5b-ad426f3593e9', + app_id: '429047995', + user_data: { + em: ['48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08'], + ph: ['d164bbe036663cb5c96835e9ccc6501e9a521127ea62f6359744928ba932413b'], + ln: ['dcf000c2386fb76d22cefc0d118a8511bb75999019cd373df52044bccd1bd251'], + fn: ['9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'], + ct: ['6689106ca7922c30b2fd2c175c85bc7fc2d52cc4941bdd7bb622c6cdc6284a85'], + st: ['3b45022ab36728cdae12e709e945bba267c50ee8a91e6e4388539a8e03a3fdcd'], + zp: ['1a4292e00780e18d00e76fde9850aee5344e939ba593333cd5e4b4aa2cd33b0c'], + country: ['582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf'], + hashed_maids: [ + '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090', + ], + client_user_agent: 'chrome', + }, + custom_data: { + currency: 'USD', + value: '27.5', + order_id: '50314b8e9bcf000000000000', + num_items: 0, + contents: [ + { + quantity: 1, + item_price: 'undefined', + }, + ], + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', }, - statusCode: 400, + statusCode: 200, }, ], }, diff --git a/test/integrations/destinations/reddit/delivery/data.ts b/test/integrations/destinations/reddit/delivery/data.ts new file mode 100644 index 0000000000..66c1e2863f --- /dev/null +++ b/test/integrations/destinations/reddit/delivery/data.ts @@ -0,0 +1,174 @@ +export const data = [ + { + name: 'reddit', + description: 'Test 0', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'Purchase', + }, + user: { + aaid: 'c12d34889302d3c656b5699fa9190b51c50d6f62fce57e13bd56b503d66c487a', + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + destResp: { + response: { + message: 'Successfully processed 1 conversion events.', + }, + status: 200, + }, + message: 'Request Processed Successfully', + status: 200, + }, + }, + }, + }, + }, + { + name: 'reddit', + description: 'Test 1', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_gsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'ViewContent', + }, + user: { + aaid: 'c12d34889302d3c656b5699fa9190b51c50d6f62fce57e13bd56b503d66c487a', + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 500, + body: { + output: { + authErrorCategory: 'REFRESH_TOKEN', + destinationResponse: { + response: 'Authorization Required', + status: 401, + }, + message: + "Request failed due to Authorization Required 'during reddit response transformation'", + statTags: { + destType: 'REDDIT', + destinationId: 'Non-determininable', + errorCategory: 'network', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'Non-determininable', + }, + status: 500, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/reddit/network.ts b/test/integrations/destinations/reddit/network.ts new file mode 100644 index 0000000000..7c436e8fb8 --- /dev/null +++ b/test/integrations/destinations/reddit/network.ts @@ -0,0 +1,100 @@ +export const networkCallsData = [ + { + httpReq: { + url: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + data: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'Purchase', + }, + user: { + aaid: 'c12d34889302d3c656b5699fa9190b51c50d6f62fce57e13bd56b503d66c487a', + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + ], + }, + params: { destination: 'reddit' }, + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + method: 'POST', + }, + httpRes: { + data: { + message: 'Successfully processed 1 conversion events.', + }, + status: 200, + statusText: 'OK', + }, + }, + { + httpReq: { + url: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_gsddXXXfsfd', + data: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'ViewContent', + }, + user: { + aaid: 'c12d34889302d3c656b5699fa9190b51c50d6f62fce57e13bd56b503d66c487a', + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + ], + }, + params: { destination: 'reddit' }, + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + method: 'POST', + }, + httpRes: { data: 'Authorization Required', status: 401, statusText: 'Unauthorized' }, + }, +]; diff --git a/test/integrations/destinations/reddit/processor/data.ts b/test/integrations/destinations/reddit/processor/data.ts new file mode 100644 index 0000000000..91da5fbe67 --- /dev/null +++ b/test/integrations/destinations/reddit/processor/data.ts @@ -0,0 +1,1532 @@ +export const data = [ + { + name: 'reddit', + description: 'Track call with order completed event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + device: { + advertisingId: 'asfds7fdsihf734b34j43f', + }, + os: { + name: 'android', + }, + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Order Completed', + userId: 'testuserId1', + properties: { + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + total: 20, + revenue: 15, + shipping: 4, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + products: [ + { + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'Purchase', + }, + user: { + aaid: 'c12d34889302d3c656b5699fa9190b51c50d6f62fce57e13bd56b503d66c487a', + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with product list viewed event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Product List Viewed', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: false, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'ViewContent', + }, + user: { + email: 'testone@gmail.com', + external_id: 'testuserId1', + ip_address: '54.100.200.255', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 0, + products: [ + { + id: '017c6f5d5cf86a4b22432066', + name: 'Just Another Game', + category: 'Games and Entertainment', + }, + { + id: '89ac6f5d5cf86a4b64eac145', + name: 'Wrestling Trump Cards', + category: 'Card Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with product added event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'PRoduct Added ', + userId: 'testuserId1', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'AddToCart', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 5, + products: [ + { + id: '622c6f5d5cf86a4c77358033', + name: 'Cones of Dunshire', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with products searched event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'products searched', + userId: 'testuserId1', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'Search', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 5, + products: [ + { + id: '622c6f5d5cf86a4c77358033', + name: 'Cones of Dunshire', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with products Searched event mapped in UI', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Products Searched', + userId: 'testuserId1', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Products Searched', + to: 'ViewContent', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'ViewContent', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 5, + products: [ + { + id: '622c6f5d5cf86a4c77358033', + name: 'Cones of Dunshire', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with product added to wishlist event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'product added to wishlist', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'AddToWishlist', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 0, + products: [ + { + id: '017c6f5d5cf86a4b22432066', + name: 'Just Another Game', + category: 'Games and Entertainment', + }, + { + id: '89ac6f5d5cf86a4b64eac145', + name: 'Wrestling Trump Cards', + category: 'Card Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with non-standard non-mapped event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Watch Items', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + custom_event_name: 'Watch Items', + tracking_type: 'Custom', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 0, + products: [ + { + id: '017c6f5d5cf86a4b22432066', + name: 'Just Another Game', + category: 'Games and Entertainment', + }, + { + id: '89ac6f5d5cf86a4b64eac145', + name: 'Wrestling Trump Cards', + category: 'Card Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with no accountId in Config', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Watch Items', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Account is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Account is not present. Aborting message.', + statusCode: 400, + statTags: { + destType: 'REDDIT', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + metadata: { + destinationId: 'destId', + secret: { + accessToken: 'dummyAccessToken', + }, + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with no messageType', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Watch Items', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'message Type is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting message.', + statusCode: 400, + statTags: { + destType: 'REDDIT', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + metadata: { + destinationId: 'destId', + secret: { + accessToken: 'dummyAccessToken', + }, + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with no event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + type: 'track', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Event is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Event is not present. Aborting message.', + statusCode: 400, + statTags: { + destType: 'REDDIT', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + metadata: { + destinationId: 'destId', + secret: { + accessToken: 'dummyAccessToken', + }, + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with no timestamp', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + anonymousId: '123456', + type: 'track', + event: 'Watch Items', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Timestamp is not present. Aborting message.: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: Timestamp is not present. Aborting message.', + statusCode: 400, + statTags: { + destType: 'REDDIT', + destinationId: 'destId', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + metadata: { + destinationId: 'destId', + secret: { + accessToken: 'dummyAccessToken', + }, + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'reddit', + description: 'Track call with no accessToken in secret in metadata', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + anonymousId: '123456', + type: 'track', + event: 'Watch Items', + userId: 'testuserId1', + originalTimestamp: '2019-10-14T09:03:17.562Z', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: {}, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: + 'Secret or accessToken is not present in the metadata: Workflow: procWorkflow, Step: buildResponseForProcessTransformation, ChildStep: undefined, OriginalError: Secret or accessToken is not present in the metadata', + statusCode: 500, + statTags: { + destType: 'REDDIT', + destinationId: 'destId', + errorCategory: 'platform', + errorType: 'oAuthSecret', + feature: 'processor', + implementation: 'cdkV2', + module: 'destination', + workspaceId: 'wspId', + }, + metadata: { + destinationId: 'destId', + secret: {}, + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/reddit/router/data.ts b/test/integrations/destinations/reddit/router/data.ts new file mode 100644 index 0000000000..317bb41a14 --- /dev/null +++ b/test/integrations/destinations/reddit/router/data.ts @@ -0,0 +1,502 @@ +export const data = [ + { + name: 'reddit', + description: 'Track Events', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + session_id: '16733896350494', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Order Completed', + userId: 'testuserId1', + properties: { + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + total: 20, + revenue: 15, + shipping: 4, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + products: [ + { + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'Product List Viewed', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + type: 'track', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + event: 'PRoduct Added ', + userId: 'testuserId1', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + destType: 'reddit', + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batchedRequest: { + body: { + JSON: { + events: [ + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'Purchase', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 3, + products: [ + { + id: '123', + name: 'Monopoly', + category: 'Games', + }, + { + id: '345', + name: 'UNO', + category: 'Games', + }, + ], + }, + }, + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'ViewContent', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 0, + products: [ + { + id: '017c6f5d5cf86a4b22432066', + name: 'Just Another Game', + category: 'Games and Entertainment', + }, + { + id: '89ac6f5d5cf86a4b64eac145', + name: 'Wrestling Trump Cards', + category: 'Card Games', + }, + ], + }, + }, + { + event_at: '2019-10-14T09:03:17.562Z', + event_type: { + tracking_type: 'AddToCart', + }, + user: { + email: 'ac144532d9e4efeab19475d9253a879173ea12a3d2238d1cb8a332a7b3a105f2', + external_id: + '7b023241a3132b792a5a33915a5afb3133cbb1e13d72879689bf6504de3b036d', + ip_address: + 'e80bd55a3834b7c2a34ade23c7ecb54d2a49838227080f50716151e765a619db', + user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + screen_dimensions: {}, + }, + event_metadata: { + item_count: 5, + products: [ + { + id: '622c6f5d5cf86a4c77358033', + name: 'Cones of Dunshire', + category: 'Games', + }, + ], + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://ads-api.reddit.com/api/v2.0/conversions/events/a2_fsddXXXfsfd', + headers: { + Authorization: 'Bearer dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + files: {}, + }, + metadata: [ + { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + hashData: true, + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + }, + ], + }, + }, + }, + }, + { + name: 'reddit', + description: 'Track Events with no event name', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + context: { + traits: { + email: 'testone@gmail.com', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + ip: '54.100.200.255', + }, + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + type: 'track', + userId: 'testuserId1', + properties: { + list_id: 'list1', + category: "What's New", + products: [ + { + product_id: '017c6f5d5cf86a4b22432066', + sku: '8732-98', + name: 'Just Another Game', + price: 22, + position: 2, + category: 'Games and Entertainment', + url: 'https://www.myecommercewebsite.com/product', + image_url: 'https://www.myecommercewebsite.com/product/path.jpg', + }, + { + product_id: '89ac6f5d5cf86a4b64eac145', + sku: '1267-01', + name: 'Wrestling Trump Cards', + price: 4, + position: 21, + category: 'Card Games', + }, + ], + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { Config: { cdkV2Enabled: true } }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + }, + ], + destType: 'reddit', + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + metadata: [ + { + destinationId: 'destId', + workspaceId: 'wspId', + secret: { + accessToken: 'dummyAccessToken', + }, + }, + ], + destination: { + Config: { + accountId: 'a2_fsddXXXfsfd', + eventsMapping: [ + { + from: 'Order Completed', + to: 'Purchase', + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + batched: false, + statusCode: 400, + error: 'Event is not present. Aborting message.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'REDDIT', + module: 'destination', + implementation: 'cdkV2', + feature: 'router', + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/salesforce/dataDelivery/data.ts b/test/integrations/destinations/salesforce/dataDelivery/data.ts index 504159cc6f..2f1e04815b 100644 --- a/test/integrations/destinations/salesforce/dataDelivery/data.ts +++ b/test/integrations/destinations/salesforce/dataDelivery/data.ts @@ -128,12 +128,12 @@ export const data = [ errorCode: 'INVALID_SESSION_ID', }, ], - status: 401, rudderJobMetadata: { destInfo: { authKey: '2HezPl1w11opbFSxnLDEgZ7kWTf', }, }, + status: 401, }, statTags: { destType: 'SALESFORCE', diff --git a/test/integrations/destinations/salesforce/processor/data.ts b/test/integrations/destinations/salesforce/processor/data.ts index ad0dbb6843..4ccc8cca79 100644 --- a/test/integrations/destinations/salesforce/processor/data.ts +++ b/test/integrations/destinations/salesforce/processor/data.ts @@ -1381,4 +1381,132 @@ export const data = [ }, }, }, + { + name: 'salesforce', + description: 'Test 10', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + initialAccessToken: '7fiy1FKcO9sohsxq1v6J88sg', + password: 'dummyPassword2', + userName: 'test.c97-qvpd@force.com.test', + sandbox: true, + }, + DestinationDefinition: { + DisplayName: 'Salesforce', + ID: '1T96GHZ0YZ1qQSLULHCoJkow9KC', + Name: 'SALESFORCE', + }, + Enabled: true, + ID: '1ut7LcVW1QC56y2EoTNo7ZwBWSY', + Name: 'Test SF', + Transformations: [], + }, + metadata: { + secret: { + access_token: 'dummyAccessToken', + instance_url: 'http://dummyurl.com', + }, + }, + message: { + anonymousId: '1e7673da-9473-49c6-97f7-da848ecafa76', + channel: 'web', + context: { + mappedToDestination: true, + externalId: [ + { + id: 'a005g0000383kmUAAQ', + type: 'SALESFORCE-custom_object__c', + identifierType: 'Id', + }, + ], + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + ip: '0.0.0.0', + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + traits: { + email: 'john@rs.com', + firstname: 'john doe', + Id: 'some-id', + }, + 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, + }, + messageId: 'f19c35da-e9de-4c6e-b6e5-9e60cccc12c8', + 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', + userId: '1e7673da-9473-49c6-97f7-da848ecafa76', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 200, + metadata: { + secret: { + access_token: 'dummyAccessToken', + instance_url: 'http://dummyurl.com', + }, + }, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'http://dummyurl.com/services/data/v50.0/sobjects/custom_object__c/a005g0000383kmUAAQ?_HttpMethod=PATCH', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummyAccessToken', + }, + params: {}, + body: { + JSON: { + email: 'john@rs.com', + firstname: 'john doe', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/snapchat_conversion/processor/data.ts b/test/integrations/destinations/snapchat_conversion/processor/data.ts index ed38673d95..b0d14208cc 100644 --- a/test/integrations/destinations/snapchat_conversion/processor/data.ts +++ b/test/integrations/destinations/snapchat_conversion/processor/data.ts @@ -4291,6 +4291,315 @@ export const data = [ }, }, }, + { + name: 'snapchat_conversion', + description: 'Test Case for Order Completed event category', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2022-04-22T10:57:58Z', + channel: 'mobile', + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + context: { + traits: { + email: 'test@email.com', + phone: '+91 2111111 ', + }, + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'ga4AppInstanceId', + id: 'f0dd99v4f979fb997ce453373900f891', + }, + ], + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + type: 'track', + event: 'Order Completed', + properties: { + brands: ['brand01', 'brand02'], + products: [ + { + product_id: '123', + price: '14', + quantity: 1, + }, + { + product_id: '124', + price: 14, + quantity: 3, + }, + ], + category: 'shoes', + }, + integrations: { + All: true, + }, + sentAt: '2022-04-22T10:57:58Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: false, + }, + }, + Config: { + apiKey: 'dummyApiKey', + pixelId: 'dummyPixelId', + appId: 'dhfeih44f', + snapAppId: 'hfhdhfd', + }, + }, + metadata: { + jobId: 31, + destinationId: 'd2', + workspaceId: 'w2', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 31, + destinationId: 'd2', + workspaceId: 'w2', + }, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://tr.snapchat.com/v2/conversion', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_type: 'PURCHASE', + item_ids: ['123', '124'], + brands: ['brand01', 'brand02'], + item_category: 'shoes', + price: '56', + hashed_email: '73062d872926c2a556f17b36f50e328ddf9bff9d403939bd14b6c3b7f5a33fc2', + hashed_phone_number: + 'bc77d64d7045fe44795ed926df37231a0cfb6ec6b74588c512790e9f143cc492', + hashed_mobile_ad_id: + 'f9779d734aaee50f16ee0011260bae7048f1d9a128c62b6a661077875701edd2', + hashed_idfv: '54bd0b26a3d39dad90f5149db49b9fd9ba885f8e35d1d94cae69273f5e657b9f', + user_agent: + 'mozilla/5.0 (macintosh; intel mac os x 10_15_2) applewebkit/537.36 (khtml, like gecko) chrome/79.0.3945.88 safari/537.36', + timestamp: '1650625078', + event_conversion_type: 'MOBILE_APP', + snap_app_id: 'hfhdhfd', + app_id: 'dhfeih44f', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'snapchat_conversion', + description: 'Test Case for Order Completed event with both category and item_category', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2022-04-22T10:57:58Z', + channel: 'mobile', + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99090', + context: { + traits: { + email: 'test@email.com', + phone: '+91 2111111 ', + }, + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + device: { + advertisingId: 'T0T0T072-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'ga4AppInstanceId', + id: 'f0dd99v4f979fb997ce453373900f891', + }, + ], + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', + }, + type: 'track', + event: 'Order Completed', + properties: { + brands: ['brand01', 'brand02'], + products: [ + { + product_id: '123', + price: '14', + quantity: 1, + }, + { + product_id: '124', + price: 14, + quantity: 3, + }, + ], + category: 'shoes', + item_category: 'glass', + }, + integrations: { + All: true, + }, + sentAt: '2022-04-22T10:57:58Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: false, + }, + }, + Config: { + apiKey: 'dummyApiKey', + pixelId: 'dummyPixelId', + appId: 'dhfeih44f', + snapAppId: 'hfhdhfd', + }, + }, + metadata: { + jobId: 31, + destinationId: 'd2', + workspaceId: 'w2', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 31, + destinationId: 'd2', + workspaceId: 'w2', + }, + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://tr.snapchat.com/v2/conversion', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event_type: 'PURCHASE', + item_ids: ['123', '124'], + brands: ['brand01', 'brand02'], + item_category: 'glass', + price: '56', + hashed_email: '73062d872926c2a556f17b36f50e328ddf9bff9d403939bd14b6c3b7f5a33fc2', + hashed_phone_number: + 'bc77d64d7045fe44795ed926df37231a0cfb6ec6b74588c512790e9f143cc492', + hashed_mobile_ad_id: + 'f9779d734aaee50f16ee0011260bae7048f1d9a128c62b6a661077875701edd2', + hashed_idfv: '54bd0b26a3d39dad90f5149db49b9fd9ba885f8e35d1d94cae69273f5e657b9f', + user_agent: + 'mozilla/5.0 (macintosh; intel mac os x 10_15_2) applewebkit/537.36 (khtml, like gecko) chrome/79.0.3945.88 safari/537.36', + timestamp: '1650625078', + event_conversion_type: 'MOBILE_APP', + snap_app_id: 'hfhdhfd', + app_id: 'dhfeih44f', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, ].map((tc) => ({ ...tc, mockFns: (_) => { diff --git a/test/integrations/destinations/sprig/processor/data.ts b/test/integrations/destinations/sprig/processor/data.ts new file mode 100644 index 0000000000..6b99e5e13b --- /dev/null +++ b/test/integrations/destinations/sprig/processor/data.ts @@ -0,0 +1,504 @@ +export const data = [ + { + name: 'sprig', + description: 'No message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + channel: 'web', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Ruddelabs', + }, + }, + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 1, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 1, + }, + statusCode: 400, + error: + 'message Type is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message Type is not present. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'SPRIG', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Unsupported message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + groupId: 'group@1', + channel: 'web', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderstack', + }, + }, + traits: {}, + type: 'group', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 2, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 2, + }, + statusCode: 400, + error: + 'message type group is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type group is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'SPRIG', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Missing config', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@1', + channel: 'web', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderstack', + }, + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: {}, + }, + metadata: { + jobId: 3, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 3, + }, + statusCode: 400, + error: + 'API Key is not present. Aborting: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: API Key is not present. Aborting', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'SPRIG', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Identify call without userId', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + anonymousId: 'anon@1', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderlabs', + }, + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 4, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 4, + }, + statusCode: 400, + error: + 'userId is required: Workflow: procWorkflow, Step: validateIdentifyPayload, ChildStep: undefined, OriginalError: userId is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'SPRIG', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Successful identify call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + userId: 'user@1', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderlabs', + }, + }, + type: 'identify', + originalTimestamp: '2023-11-10T14:42:44.724Z', + timestamp: '2023-11-22T10:12:44.75705:30', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 5, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 5, + }, + output: { + method: 'POST', + endpoint: 'https://api.sprig.com/v2/users', + headers: { + accept: 'application/json', + authorization: 'API-Key testApiKey', + 'content-type': 'application/json', + }, + body: { + JSON: { + attributes: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderlabs', + }, + emailAddress: 'test@gmail.com', + userId: 'user@1', + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + files: {}, + params: {}, + type: 'REST', + userId: '', + version: '1', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Track call with empty event name', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + userId: 'user@1', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderlabs', + }, + }, + properties: {}, + type: 'track', + event: '', + originalTimestamp: '2020-11-29T19:11:00.337Z', + timestamp: '2023-11-29T19:11:00.337Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 6, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 6, + }, + statusCode: 400, + error: + 'event name is required: Workflow: procWorkflow, Step: validateTrackPayload, ChildStep: undefined, OriginalError: event name is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'SPRIG', + module: 'destination', + implementation: 'cdkV2', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'sprig', + description: 'Successful track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + userId: 'user@1', + context: { + traits: { + email: 'test@gmail.com', + firstName: 'Test', + lastName: 'Rudderlabs', + }, + }, + properties: {}, + type: 'track', + event: 'signup', + originalTimestamp: '2020-11-29T19:11:00.337Z', + timestamp: '2023-11-29T19:11:00.337Z', + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + apiKey: 'testApiKey', + }, + }, + metadata: { + jobId: 7, + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + jobId: 7, + }, + output: { + method: 'POST', + endpoint: 'https://api.sprig.com/v2/users', + headers: { + accept: 'application/json', + authorization: 'API-Key testApiKey', + 'content-type': 'application/json', + }, + body: { + JSON: { + emailAddress: 'test@gmail.com', + userId: 'user@1', + events: [ + { + event: 'signup', + timestamp: 1701285060337, + }, + ], + }, + XML: {}, + FORM: {}, + JSON_ARRAY: {}, + }, + files: {}, + params: {}, + type: 'REST', + userId: '', + version: '1', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/tiktok_ads/processor/data.ts b/test/integrations/destinations/tiktok_ads/processor/data.ts index 38fec1e1e0..46128f46b8 100644 --- a/test/integrations/destinations/tiktok_ads/processor/data.ts +++ b/test/integrations/destinations/tiktok_ads/processor/data.ts @@ -1,4690 +1,4955 @@ export const data = [ - { - "name": "tiktok_ads", - "description": "Test 0", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 1", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout started", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "InitiateCheckout", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 2", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "Product Added to Wishlist", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "sample rudder test_event_code", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "AddToWishlist", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "test_event_code": "sample rudder test_event_code", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 3", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "Product Added to Wishlist1", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "sample rudder test_event_code", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "statusCode": 400, - "error": "Event name (product added to wishlist1) is not valid, must be mapped to one of standard events", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "destType": "TIKTOK_ADS", - "module": "destination", - "implementation": "native", - "feature": "processor" - } - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 4", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "Product Added to Wishlist", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "sample rudder test_event_code", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "AddToWishlist", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "test_event_code": "sample rudder test_event_code", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 5", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "Product Added to Wishlist", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "sample rudder test_event_code", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "AddToWishlist", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "test_event_code": "sample rudder test_event_code", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 6", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "1234" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "SubscriBe", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "+868987675687", - "email": "sample@sample.com" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": true - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "Subscribe", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "1d96e70d2bf54087e33586457cde2790825bee7b1a3b05d26481cb12ec8e63fd", - "email": "774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa", - "external_id": "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 7", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "payment info entered", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "AddPaymentInfo", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 8", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "statusCode": 400, - "error": "Event name is required", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "destType": "TIKTOK_ADS", - "module": "destination", - "implementation": "native", - "feature": "processor" - } - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 9", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "statusCode": 400, - "error": "Event type is required", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "destType": "TIKTOK_ADS", - "module": "destination", - "implementation": "native", - "feature": "processor" - } - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 10", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "type": "track", - "event": "payment info entered", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "AddPaymentInfo", - "event_id": "1616318632825_357", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 11", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "submitform", - "properties": { - "eventId": "16163186328257", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "SubmitForm", - "event_id": "16163186328257", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 12", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "submitform", - "properties": { - "eventId": "16163186328257", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131" - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "SubmitForm", - "event_id": "16163186328257", - "timestamp": "2020-09-17T19:49:27Z", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 13", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "contact", - "properties": { - "eventId": "16163186328257", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "Contact", - "event_id": "16163186328257", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 14", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "identify", - "event": "contact", - "properties": { - "eventId": "16163186328257", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "statusCode": 400, - "error": "Event type identify is not supported", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "destType": "TIKTOK_ADS", - "module": "destination", - "implementation": "native", - "feature": "processor" - } - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 15", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 16", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "order completed", - "properties": { - "eventId": "1616318632825_357", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "PlaceAnOrder", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 17", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "traits": { - "email": "user@sample.com", - "phone": "+919912345678" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "SubscriBe", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "TEST0000000011", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "+918987674657", - "email": "sample@rudder.com" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": true - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "Subscribe", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "test_event_code": "TEST0000000011", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "1b6abcebb79b2208929967160ba291656f3fcd4f00e93b6a846c1e56c0e177c6", - "email": "02e47a94635c1ffd6f6a69fe2c7a92dbfbb9d5e2ebddb54810520b34989b66a7", - "external_id": "f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 18", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "traits": { - "email": "user@sample.com", - "phone": "+919912345678" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "locale": "en-US", - "ip": "13.57.97.131", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "SubscriBe", - "properties": { - "eventId": "1616318632825_357", - "testEventCode": "TEST0000000011", - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "", - "email": "" - } - }, - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": true - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "Subscribe", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "test_event_code": "TEST0000000011", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "241102c24fa8a642e3d1346a31fbce3dd312563c015ae577a2253cb8652581eb", - "email": "a344da1fac6201ed1c1f20a07e1b55bb896a5ac0abd269c1e9daf1afbbffca3b", - "external_id": "f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 19", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "ad": { - "callback": "999ATXSfe" - }, - "page": { - "url": "http://rudder.mywebsite.com/purchase", - "referrer": "http://rudder.mywebsite.com" - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "999ATXSfe" - }, - "page": { - "url": "http://rudder.mywebsite.com/purchase", - "referrer": "http://rudder.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 20", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "abc", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false, - "eventsToStandard": [ - { - "from": "abc", - "to": "download" - }, - { - "from": "abc", - "to": "search" - }, - { - "from": "def", - "to": "search" - } - ] - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "download", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - }, - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "search", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 21", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "abc", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false, - "eventsToStandard": [ - { - "from": "def", - "to": "download" - } - ] - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "statusCode": 400, - "error": "Event name (abc) is not valid, must be mapped to one of standard events", - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "destType": "TIKTOK_ADS", - "module": "destination", - "implementation": "native", - "feature": "processor" - } - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 22", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "abc", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false, - "eventsToStandard": [ - { - "from": "abc", - "to": "download" - }, - { - "from": "def", - "to": "download" - } - ] - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "download", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 23", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "abc", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "+371234567890123", - "email": "sample@sample.com" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": true, - "eventsToStandard": [ - { - "from": "abc", - "to": "download" - }, - { - "from": "def", - "to": "download" - } - ] - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "download", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "6080191ec608e10062e9257702cbca694cfe1bfa53944ba5701119d8f8b99ad6", - "email": "774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa", - "external_id": "f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 24", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "abc", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "+3712345678", - "email": "sample@sample.com" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": true, - "eventsToStandard": [ - { - "from": "abc", - "to": "download" - }, - { - "from": "def", - "to": "download" - } - ] - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "download", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "6e6c1bb39126b3ecf537e62847909b1372a1a22de9b28d85960e12c78f322035", - "email": "774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa", - "external_id": "f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 25", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "products": [ - { - "product_id": 123, - "sku": "G-32", - "name": "Monopoly", - "price": 14, - "quantity": 1, - "category": "Games", - "url": "https://www.website.com/product/path", - "image_url": "https://www.website.com/product/path.jpg" - }, - { - "product_id": "345", - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "contents": [ - { - "price": 8, - "quantity": 2, - "content_type": "socks", - "content_id": "1077218" - }, - { - "price": 30, - "quantity": 1, - "content_type": "dress", - "content_id": "1197218" - } - ], - "currency": "USD", - "value": 46 - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 26", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "products": [ - { - "product_id": 123, - "sku": "G-32", - "name": "Monopoly", - "price": 14, - "quantity": 1, - "contentType": "product_group", - "category": "Games", - "url": "https://www.website.com/product/path", - "image_url": "https://www.website.com/product/path.jpg" - }, - { - "product_id": 345, - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "contentType": "product_group", - "quantity": 2 - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "currency": "USD", - "value": 46, - "contents": [ - { - "content_type": "product_group", - "content_id": "123", - "content_category": "Games", - "content_name": "Monopoly", - "price": 14, - "quantity": 1 - }, - { - "content_type": "product_group", - "content_id": "345", - "content_name": "UNO", - "price": 3.45, - "quantity": 2 - } - ] - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 27", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "eventId": "1616318632825_357", - "products": [ - { - "contentType": "product_group", - "product_id": "123", - "sku": "G-32", - "name": "Monopoly", - "price": 14, - "quantity": 1, - "category": "Games", - "url": "https://www.website.com/product/path", - "image_url": "https://www.website.com/product/path.jpg" - }, - { - "contentType": "product_group", - "product_id": "345", - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "currency": "USD", - "value": 46, - "contents": [ - { - "content_type": "product_group", - "content_id": "123", - "content_category": "Games", - "content_name": "Monopoly", - "price": 14, - "quantity": 1 - }, - { - "content_type": "product_group", - "content_id": "345", - "content_category": "Games", - "content_name": "UNO", - "price": 3.45, - "quantity": 2 - } - ] - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - }, - { - "name": "tiktok_ads", - "description": "Test 28", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.0" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" - }, - "userAgent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion", - "ip": "13.57.97.131", - "locale": "en-US", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "externalId": [ - { - "type": "tiktokExternalId", - "id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - } - ] - }, - "messageId": "84e26acc-56a5-4835-8233-591137fca468", - "session_id": "3049dc4c-5a95-4ccd-a3e7-d74a7e411f22", - "originalTimestamp": "2019-10-14T09:03:17.562Z", - "timestamp": "2020-09-17T19:49:27Z", - "type": "track", - "event": "checkout step completed", - "properties": { - "category": "Urban", - "status": "processed", - "name": "games", - "contentType": "product_group", - "productId": "qqw21221341234", - "eventId": "1616318632825_357", - "products": [ - { - "product_id": "123", - "sku": "G-32", - "name": "Monopoly", - "price": 14, - "quantity": 1, - "category": "Games", - "url": "https://www.website.com/product/path", - "image_url": "https://www.website.com/product/path.jpg" - }, - { - "product_id": "345", - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ], - "currency": "USD", - "value": 46, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f" - } - } - }, - "integrations": { - "All": true - }, - "sentAt": "2019-10-14T09:03:22.563Z" - }, - "destination": { - "Config": { - "accessToken": "dummyAccessToken", - "pixelCode": "A1T8T4UYGVIQA8ORZMX9", - "hashUserProperties": false - } - } - } - ] - } - }, - "output": { - "response": { - "status": 200, - "body": [ - { - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://business-api.tiktok.com/open_api/v1.3/pixel/track/", - "headers": { - "Access-Token": "dummyAccessToken", - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "pixel_code": "A1T8T4UYGVIQA8ORZMX9", - "event": "CompletePayment", - "event_id": "1616318632825_357", - "timestamp": "2020-09-17T19:49:27Z", - "properties": { - "content_category": "Urban", - "status": "processed", - "content_name": "games", - "content_id": "qqw21221341234", - "content_type": "product_group", - "currency": "USD", - "value": 46, - "contents": [ - { - "content_type": "product_group", - "content_id": "123", - "content_category": "Games", - "content_name": "Monopoly", - "price": 14, - "quantity": 1 - }, - { - "content_type": "product_group", - "content_id": "345", - "content_category": "Games", - "content_name": "UNO", - "price": 3.45, - "quantity": 2 - } - ] - }, - "context": { - "ad": { - "callback": "123ATXSfe" - }, - "page": { - "url": "http://demo.mywebsite.com/purchase", - "referrer": "http://demo.mywebsite.com" - }, - "user": { - "phone_number": "2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea", - "email": "dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f", - "external_id": "f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc" - }, - "ip": "13.57.97.131", - "user_agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion" - }, - "partner_name": "RudderStack" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "" - }, - "statusCode": 200 - } - ] - } - } - } -] \ No newline at end of file + { + name: 'tiktok_ads', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + context: { + ad: { + callback: '123ATXSfe', + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + ad: { + callback: 'dummyclickId', + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout started', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'InitiateCheckout', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'Product Added to Wishlist', + properties: { + eventId: '1616318632825_357', + testEventCode: 'sample rudder test_event_code', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'AddToWishlist', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + test_event_code: 'sample rudder test_event_code', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 3', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'Product Added to Wishlist1', + properties: { + eventId: '1616318632825_357', + testEventCode: 'sample rudder test_event_code', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Event name (product added to wishlist1) is not valid, must be mapped to one of standard events', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 4', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'Product Added to Wishlist', + properties: { + eventId: '1616318632825_357', + testEventCode: 'sample rudder test_event_code', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'AddToWishlist', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + test_event_code: 'sample rudder test_event_code', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 5', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'Product Added to Wishlist', + properties: { + eventId: '1616318632825_357', + testEventCode: 'sample rudder test_event_code', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'AddToWishlist', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + test_event_code: 'sample rudder test_event_code', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 6', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: '1234', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'SubscriBe', + properties: { + eventId: '1616318632825_357', + testEventCode: '', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: '+868987675687', + email: 'sample@sample.com', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: true, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'Subscribe', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '1d96e70d2bf54087e33586457cde2790825bee7b1a3b05d26481cb12ec8e63fd', + email: '774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa', + external_id: + '03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 7', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'payment info entered', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'AddPaymentInfo', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 8', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Event name is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 9', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Event type is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 10', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + type: 'track', + event: 'payment info entered', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'AddPaymentInfo', + event_id: '1616318632825_357', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 11', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'submitform', + properties: { + eventId: '16163186328257', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'SubmitForm', + event_id: '16163186328257', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 12', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'submitform', + properties: { + eventId: '16163186328257', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'SubmitForm', + event_id: '16163186328257', + timestamp: '2020-09-17T19:49:27Z', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 13', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'contact', + properties: { + eventId: '16163186328257', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'Contact', + event_id: '16163186328257', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 14', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'identify', + event: 'contact', + properties: { + eventId: '16163186328257', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Event type identify is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 15', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 16', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'order completed', + properties: { + eventId: '1616318632825_357', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'PlaceAnOrder', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 17', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + email: 'user@sample.com', + phone: '+919912345678', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'SubscriBe', + properties: { + eventId: '1616318632825_357', + testEventCode: 'TEST0000000011', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: '+918987674657', + email: 'sample@rudder.com', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: true, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'Subscribe', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + test_event_code: 'TEST0000000011', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '1b6abcebb79b2208929967160ba291656f3fcd4f00e93b6a846c1e56c0e177c6', + email: '02e47a94635c1ffd6f6a69fe2c7a92dbfbb9d5e2ebddb54810520b34989b66a7', + external_id: + 'f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 18', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + email: 'user@sample.com', + phone: '+919912345678', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + locale: 'en-US', + ip: '13.57.97.131', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'SubscriBe', + properties: { + eventId: '1616318632825_357', + testEventCode: 'TEST0000000011', + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: '', + email: '', + }, + }, + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: true, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'Subscribe', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + test_event_code: 'TEST0000000011', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '241102c24fa8a642e3d1346a31fbce3dd312563c015ae577a2253cb8652581eb', + email: 'a344da1fac6201ed1c1f20a07e1b55bb896a5ac0abd269c1e9daf1afbbffca3b', + external_id: + 'f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 19', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + page: { + url: 'http://rudder.mywebsite.com/purchase', + referrer: 'http://rudder.mywebsite.com', + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://rudder.mywebsite.com/purchase', + referrer: 'http://rudder.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 20', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + eventsToStandard: [ + { + from: 'abc', + to: 'download', + }, + { + from: 'abc', + to: 'search', + }, + { + from: 'def', + to: 'search', + }, + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'download', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'search', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 21', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + eventsToStandard: [ + { + from: 'def', + to: 'download', + }, + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Event name (abc) is not valid, must be mapped to one of standard events', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 22', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + eventsToStandard: [ + { + from: 'abc', + to: 'download', + }, + { + from: 'def', + to: 'download', + }, + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'download', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 23', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: '+371234567890123', + email: 'sample@sample.com', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: true, + eventsToStandard: [ + { + from: 'abc', + to: 'download', + }, + { + from: 'def', + to: 'download', + }, + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'download', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '6080191ec608e10062e9257702cbca694cfe1bfa53944ba5701119d8f8b99ad6', + email: '774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa', + external_id: + 'f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 24', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'abc', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: '+3712345678', + email: 'sample@sample.com', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: true, + eventsToStandard: [ + { + from: 'abc', + to: 'download', + }, + { + from: 'def', + to: 'download', + }, + ], + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'download', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '6e6c1bb39126b3ecf537e62847909b1372a1a22de9b28d85960e12c78f322035', + email: '774efc08cebab8c50c0f0eb2d3a2d2e560872a64f6c1617314c4f03b1c3d4dfa', + external_id: + 'f0f3ec74bbef8580d7de80624dea93c05d828c748715199fe71bc7f5a67aa8b3', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 25', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + products: [ + { + product_id: 123, + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 26', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + products: [ + { + product_id: 123, + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + contentType: 'product_group', + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: 345, + sku: 'F-32', + name: 'UNO', + price: 3.45, + contentType: 'product_group', + quantity: 2, + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + currency: 'USD', + value: 46, + contents: [ + { + content_type: 'product_group', + content_id: '123', + content_category: 'Games', + content_name: 'Monopoly', + price: 14, + quantity: 1, + }, + { + content_type: 'product_group', + content_id: '345', + content_name: 'UNO', + price: 3.45, + quantity: 2, + }, + ], + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 27', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + eventId: '1616318632825_357', + products: [ + { + contentType: 'product_group', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + contentType: 'product_group', + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + currency: 'USD', + value: 46, + contents: [ + { + content_type: 'product_group', + content_id: '123', + content_category: 'Games', + content_name: 'Monopoly', + price: 14, + quantity: 1, + }, + { + content_type: 'product_group', + content_id: '345', + content_category: 'Games', + content_name: 'UNO', + price: 3.45, + quantity: 2, + }, + ], + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 28', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'checkout step completed', + properties: { + category: 'Urban', + status: 'processed', + name: 'games', + contentType: 'product_group', + productId: 'qqw21221341234', + eventId: '1616318632825_357', + products: [ + { + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { + product_id: '345', + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + currency: 'USD', + value: 46, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'CompletePayment', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + content_category: 'Urban', + status: 'processed', + content_name: 'games', + content_id: 'qqw21221341234', + content_type: 'product_group', + currency: 'USD', + value: 46, + contents: [ + { + content_type: 'product_group', + content_id: '123', + content_category: 'Games', + content_name: 'Monopoly', + price: 14, + quantity: 1, + }, + { + content_type: 'product_group', + content_id: '345', + content_category: 'Games', + content_name: 'UNO', + price: 3.45, + quantity: 2, + }, + ], + }, + context: { + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 29 -> custom_event Pass', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'custom_event', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + context: { + ad: { + callback: '123ATXSfe', + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + sendCustomEvents: true, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/pixel/track/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + pixel_code: 'A1T8T4UYGVIQA8ORZMX9', + event: 'custom_event', + event_id: '1616318632825_357', + timestamp: '2020-09-17T19:49:27Z', + properties: { + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + currency: 'USD', + value: 46, + }, + context: { + ad: { + callback: 'dummyclickId', + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + external_id: + 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ip: '13.57.97.131', + user_agent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + }, + partner_name: 'RudderStack', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'tiktok_ads', + description: 'Test 30 -> custom_event Failure case for flag set as false', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion', + ip: '13.57.97.131', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + externalId: [ + { + type: 'tiktokExternalId', + id: 'f0e388f53921a51f0bb0fc8a2944109ec188b59172935d8f23020b1614cc44bc', + }, + ], + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + timestamp: '2020-09-17T19:49:27Z', + type: 'track', + event: 'custom_event', + properties: { + eventId: '1616318632825_357', + contents: [ + { + price: 8, + quantity: 2, + content_type: 'socks', + content_id: '1077218', + }, + { + price: 30, + quantity: 1, + content_type: 'dress', + content_id: '1197218', + }, + ], + clickId: 'dummyclickId', + currency: 'USD', + value: 46, + context: { + ad: { + callback: '123ATXSfe', + }, + page: { + url: 'http://demo.mywebsite.com/purchase', + referrer: 'http://demo.mywebsite.com', + }, + user: { + phone_number: + '2f9d2b4df907e5c9a7b3434351b55700167b998a83dc479b825096486ffcf4ea', + email: 'dd6ff77f54e2106661089bae4d40cdb600979bf7edc9eb65c0942ba55c7c2d7f', + }, + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + destination: { + Config: { + accessToken: 'dummyAccessToken', + pixelCode: 'A1T8T4UYGVIQA8ORZMX9', + hashUserProperties: false, + sendCustomEvents: false, + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'Event name (custom_event) is not valid, must be mapped to one of standard events', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'TIKTOK_ADS', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/tiktok_ads/router/data.ts b/test/integrations/destinations/tiktok_ads/router/data.ts index 60bb5628ca..a8c233c7a8 100644 --- a/test/integrations/destinations/tiktok_ads/router/data.ts +++ b/test/integrations/destinations/tiktok_ads/router/data.ts @@ -52,6 +52,7 @@ export const data = [ event: 'checkout step completed', properties: { eventId: '1616318632825_357', + clickId: 'dummyClickId', contents: [ { price: 8, @@ -69,9 +70,6 @@ export const data = [ currency: 'USD', value: 46.0, context: { - ad: { - callback: '123ATXSfe', - }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -141,9 +139,6 @@ export const data = [ properties: { eventId: '1616318632825_357', context: { - ad: { - callback: '123ATXSfe', - }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -229,9 +224,6 @@ export const data = [ properties: { eventId: '1616318632825_357', context: { - ad: { - callback: '123ATXSfe', - }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -320,9 +312,6 @@ export const data = [ properties: { eventId: '1616318632825_357', context: { - ad: { - callback: '123ATXSfe', - }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -421,7 +410,7 @@ export const data = [ }, context: { ad: { - callback: '123ATXSfe', + callback: 'dummyClickId', }, page: { url: 'http://demo.mywebsite.com/purchase', @@ -446,9 +435,6 @@ export const data = [ type: 'track', timestamp: '2020-09-17T19:49:27Z', context: { - ad: { - callback: '123ATXSfe', - }, ip: '13.57.97.131', page: { url: 'http://demo.mywebsite.com/purchase', @@ -490,9 +476,6 @@ export const data = [ type: 'track', timestamp: '2020-09-17T19:49:27Z', context: { - ad: { - callback: '123ATXSfe', - }, ip: '13.57.97.131', page: { url: 'http://demo.mywebsite.com/purchase', @@ -534,9 +517,6 @@ export const data = [ type: 'track', timestamp: '2020-09-17T19:49:27Z', context: { - ad: { - callback: '123ATXSfe', - }, ip: '13.57.97.131', page: { url: 'http://demo.mywebsite.com/purchase', @@ -662,9 +642,6 @@ export const data = [ eventId: '1616318632825_357', testEventCode: 'sample rudder test_event_code', context: { - ad: { - callback: '123ATXSfe', - }, page: { url: 'http://demo.mywebsite.com/purchase', referrer: 'http://demo.mywebsite.com', @@ -729,9 +706,6 @@ export const data = [ FORM: {}, JSON: { context: { - ad: { - callback: '123ATXSfe', - }, ip: '13.57.97.131', page: { referrer: 'http://demo.mywebsite.com', diff --git a/test/integrations/destinations/tiktok_audience/processor/data.ts b/test/integrations/destinations/tiktok_audience/processor/data.ts new file mode 100644 index 0000000000..a715aa2f72 --- /dev/null +++ b/test/integrations/destinations/tiktok_audience/processor/data.ts @@ -0,0 +1,854 @@ +export const data = [ + { + "name": "tiktok_audience", + "description": "Test 1: Containing SHA256 traits only", + "feature": "processor", + "module": "destination", + "version": "v0", + "input": { + "request": { + "body": [ + { + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "EMAIL_SHA256": "alex@email.com" + }, + { + "EMAIL_SHA256": "amy@abc.com" + }, + { + "EMAIL_SHA256": "van@abc.com" + } + ], + "remove": [ + { + "EMAIL_SHA256": "alex@email.com" + }, + { + "EMAIL_SHA256": "amy@abc.com" + }, + { + "EMAIL_SHA256": "van@abc.com" + } + ] + } + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "externalId": [ + { + "type": "TIKTOK_AUDIENCE-23856594064540489", + "identifierType": "EMAIL_SHA256" + } + ], + "destinationFields": "EMAIL_SHA256" + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "destination": { + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "isHashRequired": true, + "registerDeviceOrBrowserApiKey": true, + "apiKey": "intercomApiKey", + "appId": "9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0", + "collectContext": false + } + } + } + ] + } + }, + "output": { + "response": { + "status": 200, + "body": [ + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "add" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + }, + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "delete" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + } + ] + } + } + }, + { + "name": "tiktok_audience", + "description": "Test 2: Containing SHA256 and MD5 traits", + "feature": "processor", + "module": "destination", + "version": "v0", + "input": { + "request": { + "body": [ + { + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "EMAIL_SHA256": "alex@email.com", + "AAID_MD5": "1234567" + }, + { + "EMAIL_SHA256": "amy@abc.com", + "AAID_MD5": "1234568" + }, + { + "EMAIL_SHA256": "van@abc.com", + "AAID_MD5": "1234569" + } + ], + "remove": [ + { + "EMAIL_SHA256": "alex@email.com", + "AAID_MD5": "1234570" + }, + { + "EMAIL_SHA256": "amy@abc.com", + "AAID_MD5": "1234571" + }, + { + "EMAIL_SHA256": "van@abc.com", + "AAID_MD5": "1234572" + } + ] + } + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "externalId": [ + { + "type": "TIKTOK_AUDIENCE-23856594064540489", + "identifierType": "EMAIL_SHA256" + } + ], + "destinationFields": "EMAIL_SHA256, AAID_MD5" + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "destination": { + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "isHashRequired": true, + "registerDeviceOrBrowserApiKey": true, + "apiKey": "intercomApiKey", + "appId": "9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0", + "collectContext": false + } + } + } + ] + } + }, + "output": { + "response": { + "status": 200, + "body": [ + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "fcea920f7412b5da7be0cf42b8c93759", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "fe743d8d97aa7dfc6c93ccdc2e749513", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "e36a2f90240e9e84483504fd4a704452", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256", + "AAID_MD5" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "add" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + }, + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "c1abd65fea29d573ddef1bce925e3276", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "7298110702a080dfc6903f13333eb04a", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "d9cb68b1fd3b9d32abc5f4cab8b42b68", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256", + "AAID_MD5" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "delete" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + } + ] + } + } + }, + { + "name": "tiktok_audience", + "description": "Test 3: Containing all possible traits", + "feature": "processor", + "module": "destination", + "version": "v0", + "input": { + "request": { + "body": [ + { + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "EMAIL_SHA256": "alex@email.com", + "PHONE_SHA256": "+129988776655", + "IDFA_SHA256": "1234lkasfjdalj12321", + "AAID_SHA256": "000999OOOQQQQ", + "AAID_MD5": "000999OOOQQQQ", + "IDFA_MD5": "1234lkasfjdalj12321" + }, + { + "EMAIL_SHA256": "amy@abc.com", + "PHONE_SHA256": "+129988776677", + "IDFA_SHA256": "1234lkasfjdalj114455", + "AAID_SHA256": "000999OOOPPPP", + "AAID_MD5": "000999OOOPPPP", + "IDFA_MD5": "1234lkasfjdalj114455" + } + ] + } + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "externalId": [ + { + "type": "TIKTOK_AUDIENCE-23856594064540489", + "identifierType": "EMAIL_SHA256" + } + ], + "destinationFields": "EMAIL_SHA256, PHONE_SHA256, IDFA_SHA256, AAID_SHA256, AAID_MD, IDFA_MD5" + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "destination": { + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "isHashRequired": true, + "registerDeviceOrBrowserApiKey": true, + "apiKey": "intercomApiKey", + "appId": "9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0", + "collectContext": false + } + } + } + ] + } + }, + "output": { + "response": { + "status": 200, + "body": [ + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "31e78a3bf9ce2b43316f64fe883a531d6266938091e94e2f2480272481163dee", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "0259f595f7172c8dd692a5c37b4d296939555f862aae8adb964391bdb65006ab", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "b06fbe7a29f33576a792ba3df3c9bf838cd26ea88cf574285fa60dc0234a8485", + "audience_ids": [ + "23856594064540489" + ] + }, + {}, + { + "id": "32ee3d063320815a13e0058c2498ff76", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "fb40adc7debbf40e7b45b0a4a91886785dff1a28809276f95f1c44f7045f9b4d", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "e6bbdf34c5f3472f31b2923a26811560a599233f3dea4c9971595c3bb7b1e8dc", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "661125f7d337811256c5b55996b22c89047804dcec494db72659e4be71e03091", + "audience_ids": [ + "23856594064540489" + ] + }, + {}, + { + "id": "94162773066d6ae88b2658dc58ca2317", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256", + "PHONE_SHA256", + "IDFA_SHA256", + "AAID_SHA256", + "AAID_MD", + "IDFA_MD5" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "add" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + } + ] + } + } + }, + { + "name": "tiktok_audience", + "description": "Test 4: Considering some null values", + "feature": "processor", + "module": "destination", + "version": "v0", + "input": { + "request": { + "body": [ + { + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "EMAIL_SHA256": "alex@email.com", + "PHONE_SHA256": "+129988776655", + "AAID_MD5": "000999OOOQQQQ", + "IDFA_MD5": "1234lkasfjdalj12321" + }, + { + "EMAIL_SHA256": "amy@abc.com", + "AAID_SHA256": "000999OOOPPPP", + "AAID_MD5": "000999OOOPPPP", + "IDFA_MD5": "1234lkasfjdalj114455" + } + ] + } + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "externalId": [ + { + "type": "TIKTOK_AUDIENCE-23856594064540489", + "identifierType": "EMAIL_SHA256" + } + ], + "destinationFields": "EMAIL_SHA256, PHONE_SHA256, IDFA_SHA256, AAID_SHA256, AAID_MD, IDFA_MD5" + }, + "timestamp": "2020-02-02T00:23:09.544Z" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "destination": { + "DestinationDefinition": { + "Config": { + "cdkV2Enabled": true + } + }, + "Config": { + "isHashRequired": true, + "registerDeviceOrBrowserApiKey": true, + "apiKey": "intercomApiKey", + "appId": "9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0", + "collectContext": false + } + } + } + ] + } + }, + "output": { + "response": { + "status": 200, + "body": [ + { + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://business-api.tiktok.com/open_api/v1.3/segment/mapping/", + "headers": { + "Access-Token": "dummyAccessToken", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "batch_data": [ + [ + { + "id": "ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b", + "audience_ids": [ + "23856594064540489" + ] + }, + { + "id": "31e78a3bf9ce2b43316f64fe883a531d6266938091e94e2f2480272481163dee", + "audience_ids": [ + "23856594064540489" + ] + }, + {}, + {}, + {}, + { + "id": "32ee3d063320815a13e0058c2498ff76", + "audience_ids": [ + "23856594064540489" + ] + } + ], + [ + { + "id": "49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579", + "audience_ids": [ + "23856594064540489" + ] + }, + {}, + {}, + { + "id": "661125f7d337811256c5b55996b22c89047804dcec494db72659e4be71e03091", + "audience_ids": [ + "23856594064540489" + ] + }, + {}, + { + "id": "94162773066d6ae88b2658dc58ca2317", + "audience_ids": [ + "23856594064540489" + ] + } + ] + ], + "id_schema": [ + "EMAIL_SHA256", + "PHONE_SHA256", + "IDFA_SHA256", + "AAID_SHA256", + "AAID_MD", + "IDFA_MD5" + ], + "advertiser_ids": [ + "dummyAdverTiserID" + ], + "action": "add" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "" + }, + "metadata": { + "jobId": 1, + "secret": { + "accessToken": "dummyAccessToken", + "advertiserIds": [ + "dummyAdverTiserID" + ] + } + }, + "statusCode": 200 + } + ] + } + } + } +] \ No newline at end of file diff --git a/test/integrations/destinations/tiktok_audience/router/data.ts b/test/integrations/destinations/tiktok_audience/router/data.ts new file mode 100644 index 0000000000..c8a8b93d30 --- /dev/null +++ b/test/integrations/destinations/tiktok_audience/router/data.ts @@ -0,0 +1,833 @@ +export const data = [ + { + name: 'tiktok_audience', + description: 'Multiple jobs with different metadata', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + userId: 'user 1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + EMAIL_SHA256: 'alex@email.com', + }, + { + EMAIL_SHA256: 'amy@abc.com', + }, + { + EMAIL_SHA256: 'van@abc.com', + }, + ], + remove: [ + { + EMAIL_SHA256: 'alex@email.com', + }, + { + EMAIL_SHA256: 'amy@abc.com', + }, + { + EMAIL_SHA256: 'van@abc.com', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + externalId: [ + { + type: 'TIKTOK_AUDIENCE-23856594064540489', + identifierType: 'EMAIL_SHA256', + }, + ], + destinationFields: 'EMAIL_SHA256', + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 1, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + }, + { + message: { + userId: 'user 1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + EMAIL_SHA256: 'alex@email.com', + AAID_MD5: '1234567', + }, + { + EMAIL_SHA256: 'amy@abc.com', + AAID_MD5: '1234568', + }, + { + EMAIL_SHA256: 'van@abc.com', + AAID_MD5: '1234569', + }, + ], + remove: [ + { + EMAIL_SHA256: 'alex@email.com', + AAID_MD5: '1234570', + }, + { + EMAIL_SHA256: 'amy@abc.com', + AAID_MD5: '1234571', + }, + { + EMAIL_SHA256: 'van@abc.com', + AAID_MD5: '1234572', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + externalId: [ + { + type: 'TIKTOK_AUDIENCE-23856594064540489', + identifierType: 'EMAIL_SHA256', + }, + ], + destinationFields: 'EMAIL_SHA256, AAID_MD5', + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 2, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + }, + { + message: { + userId: 'user 1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + EMAIL_SHA256: 'alex@email.com', + PHONE_SHA256: '+129988776655', + IDFA_SHA256: '1234lkasfjdalj12321', + AAID_SHA256: '000999OOOQQQQ', + AAID_MD5: '000999OOOQQQQ', + IDFA_MD5: '1234lkasfjdalj12321', + }, + { + EMAIL_SHA256: 'amy@abc.com', + PHONE_SHA256: '+129988776677', + IDFA_SHA256: '1234lkasfjdalj114455', + AAID_SHA256: '000999OOOPPPP', + AAID_MD5: '000999OOOPPPP', + IDFA_MD5: '1234lkasfjdalj114455', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + externalId: [ + { + type: 'TIKTOK_AUDIENCE-23856594064540489', + identifierType: 'EMAIL_SHA256', + }, + ], + destinationFields: + 'EMAIL_SHA256, PHONE_SHA256, IDFA_SHA256, AAID_SHA256, AAID_MD, IDFA_MD5', + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 3, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + }, + { + message: { + userId: 'user 1', + type: 'audiencelist', + properties: { + listData: { + add: [ + { + EMAIL_SHA256: 'alex@email.com', + PHONE_SHA256: '+129988776655', + AAID_MD5: '000999OOOQQQQ', + IDFA_MD5: '1234lkasfjdalj12321', + }, + { + EMAIL_SHA256: 'amy@abc.com', + AAID_SHA256: '000999OOOPPPP', + AAID_MD5: '000999OOOPPPP', + IDFA_MD5: '1234lkasfjdalj114455', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + externalId: [ + { + type: 'TIKTOK_AUDIENCE-23856594064540489', + identifierType: 'EMAIL_SHA256', + }, + ], + destinationFields: + 'EMAIL_SHA256, PHONE_SHA256, IDFA_SHA256, AAID_SHA256, AAID_MD, IDFA_MD5', + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 4, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + }, + { + message: { + userId: 'user 1', + properties: { + listData: { + add: [ + { + EMAIL_SHA256: 'alex@email.com', + PHONE_SHA256: '+129988776655', + AAID_MD5: '000999OOOQQQQ', + IDFA_MD5: '1234lkasfjdalj12321', + }, + { + EMAIL_SHA256: 'amy@abc.com', + AAID_SHA256: '000999OOOPPPP', + AAID_MD5: '000999OOOPPPP', + IDFA_MD5: '1234lkasfjdalj114455', + }, + ], + }, + }, + context: { + ip: '14.5.67.21', + library: { + name: 'http', + }, + externalId: [ + { + type: 'TIKTOK_AUDIENCE-23856594064540489', + identifierType: 'EMAIL_SHA256', + }, + ], + destinationFields: + 'EMAIL_SHA256, PHONE_SHA256, IDFA_SHA256, AAID_SHA256, AAID_MD, IDFA_MD5', + }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + metadata: { + jobId: 1524545, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + }, + ], + destType: 'tiktok_audience', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + error: 'message Type is not present. Aborting message.', + batched: false, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + metadata: [ + { + jobId: 1524545, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + ], + statTags: { + destType: 'TIKTOK_AUDIENCE', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'router', + implementation: 'cdkV2', + module: 'destination', + }, + statusCode: 400, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: ['EMAIL_SHA256'], + advertiser_ids: ['dummyAdverTiserID'], + action: 'add', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: ['EMAIL_SHA256'], + advertiser_ids: ['dummyAdverTiserID'], + action: 'delete', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + batched: true, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + metadata: [ + { + jobId: 1, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + ], + statusCode: 200, + }, + { + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + { + id: 'fcea920f7412b5da7be0cf42b8c93759', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + { + id: 'fe743d8d97aa7dfc6c93ccdc2e749513', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c', + audience_ids: ['23856594064540489'], + }, + { + id: 'e36a2f90240e9e84483504fd4a704452', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: ['EMAIL_SHA256', 'AAID_MD5'], + advertiser_ids: ['dummyAdverTiserID'], + action: 'add', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + { + id: 'c1abd65fea29d573ddef1bce925e3276', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + { + id: '7298110702a080dfc6903f13333eb04a', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '2048acfa84a01121060ca2fc8a673a76d427176dc37224d4408c21973bd90e5c', + audience_ids: ['23856594064540489'], + }, + { + id: 'd9cb68b1fd3b9d32abc5f4cab8b42b68', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: ['EMAIL_SHA256', 'AAID_MD5'], + advertiser_ids: ['dummyAdverTiserID'], + action: 'delete', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + ], + batched: true, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + metadata: [ + { + jobId: 2, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + ], + statusCode: 200, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + { + id: '31e78a3bf9ce2b43316f64fe883a531d6266938091e94e2f2480272481163dee', + audience_ids: ['23856594064540489'], + }, + { + id: '0259f595f7172c8dd692a5c37b4d296939555f862aae8adb964391bdb65006ab', + audience_ids: ['23856594064540489'], + }, + { + id: 'b06fbe7a29f33576a792ba3df3c9bf838cd26ea88cf574285fa60dc0234a8485', + audience_ids: ['23856594064540489'], + }, + {}, + { + id: '32ee3d063320815a13e0058c2498ff76', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + { + id: 'fb40adc7debbf40e7b45b0a4a91886785dff1a28809276f95f1c44f7045f9b4d', + audience_ids: ['23856594064540489'], + }, + { + id: 'e6bbdf34c5f3472f31b2923a26811560a599233f3dea4c9971595c3bb7b1e8dc', + audience_ids: ['23856594064540489'], + }, + { + id: '661125f7d337811256c5b55996b22c89047804dcec494db72659e4be71e03091', + audience_ids: ['23856594064540489'], + }, + {}, + { + id: '94162773066d6ae88b2658dc58ca2317', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: [ + 'EMAIL_SHA256', + 'PHONE_SHA256', + 'IDFA_SHA256', + 'AAID_SHA256', + 'AAID_MD', + 'IDFA_MD5', + ], + advertiser_ids: ['dummyAdverTiserID'], + action: 'add', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + batched: true, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + metadata: [ + { + jobId: 3, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + ], + statusCode: 200, + }, + { + batchedRequest: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://business-api.tiktok.com/open_api/v1.3/segment/mapping/', + headers: { + 'Access-Token': 'dummyAccessToken', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + batch_data: [ + [ + { + id: 'ac0f1baec38a9ef3cfcb56db981df7d9bab2568c7f53ef3776d1c059ec58e72b', + audience_ids: ['23856594064540489'], + }, + { + id: '31e78a3bf9ce2b43316f64fe883a531d6266938091e94e2f2480272481163dee', + audience_ids: ['23856594064540489'], + }, + {}, + {}, + {}, + { + id: '32ee3d063320815a13e0058c2498ff76', + audience_ids: ['23856594064540489'], + }, + ], + [ + { + id: '49eaeca26c878f268ad33af8cfa8194ca5b8b8e448b1c775bf9153a2de734579', + audience_ids: ['23856594064540489'], + }, + {}, + {}, + { + id: '661125f7d337811256c5b55996b22c89047804dcec494db72659e4be71e03091', + audience_ids: ['23856594064540489'], + }, + {}, + { + id: '94162773066d6ae88b2658dc58ca2317', + audience_ids: ['23856594064540489'], + }, + ], + ], + id_schema: [ + 'EMAIL_SHA256', + 'PHONE_SHA256', + 'IDFA_SHA256', + 'AAID_SHA256', + 'AAID_MD', + 'IDFA_MD5', + ], + advertiser_ids: ['dummyAdverTiserID'], + action: 'add', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + batched: true, + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + isHashRequired: true, + registerDeviceOrBrowserApiKey: true, + apiKey: 'intercomApiKey', + appId: '9e9cdea1-78fa-4829-a9b2-5d7f7e96d1a0', + collectContext: false, + }, + }, + metadata: [ + { + jobId: 4, + secret: { + accessToken: 'dummyAccessToken', + advertiserIds: ['dummyAdverTiserID'], + }, + }, + ], + statusCode: 200, + }, + ], + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/userlist/processor/data.ts b/test/integrations/destinations/userlist/processor/data.ts new file mode 100644 index 0000000000..f07006b186 --- /dev/null +++ b/test/integrations/destinations/userlist/processor/data.ts @@ -0,0 +1,894 @@ +export const data = [ + { + name: 'userlist', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + anonymousId: '123456', + email: 'test@rudderstack.com', + address: { + city: 'kolkata', + country: 'India', + postalCode: 712136, + state: 'WB', + street: '', + }, + ip: '0.0.0.0', + age: 26, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + user_properties: { + prop1: 'val1', + prop2: 'val2', + }, + type: 'identify', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + userId: '123456', + integrations: { + All: true, + }, + traits: { + anonymousId: 'anon-id', + email: 'test@gmail.com', + address: { + city: 'NY', + country: 'USA', + postalCode: 712136, + state: 'CA', + street: '', + }, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + JSON_ARRAY: {}, + JSON: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + anonymousId: '123456', + email: 'test@rudderstack.com', + address: { + city: 'kolkata', + country: 'India', + postalCode: 712136, + state: 'WB', + street: '', + }, + ip: '0.0.0.0', + age: 26, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + user_properties: { + prop1: 'val1', + prop2: 'val2', + }, + type: 'identify', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + userId: '123456', + integrations: { + All: true, + }, + traits: { + anonymousId: 'anon-id', + email: 'test@gmail.com', + address: { + city: 'NY', + country: 'USA', + postalCode: 712136, + state: 'CA', + street: '', + }, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + FORM: {}, + }, + files: {}, + endpoint: 'https://incoming.userlist.com/rudderstack/events', + headers: { + Authorization: 'Push userlist-push-key', + 'Content-Type': 'application/json', + }, + version: '1', + params: {}, + type: 'REST', + method: 'POST', + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'userlist', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.5', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'test@rudderstack.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.5', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 0.8999999761581421, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + test: 'other value', + }, + page: { + path: '/html/sajal.html', + referrer: '', + search: + '?utm_source=google&utm_medium=medium&utm_term=keyword&utm_content=some%20content&utm_campaign=some%20campaign&utm_test=other%20value', + title: '', + url: 'http://localhost:9116/html/sajal.html?utm_source=google&utm_medium=medium&utm_term=keyword&utm_content=some%20content&utm_campaign=some%20campaign&utm_test=other%20value', + }, + }, + type: 'group', + messageId: 'e5034df0-a404-47b4-a463-76df99934fea', + originalTimestamp: '2020-10-20T07:54:58.983Z', + anonymousId: 'my-anonymous-id-new', + userId: 'sampleusrRudder3', + integrations: { + All: true, + }, + groupId: 'Sample_groupId23', + traits: { + KEY_3: { + CHILD_KEY_92: 'value_95', + CHILD_KEY_102: 'value_103', + }, + KEY_2: { + CHILD_KEY_92: 'value_95', + CHILD_KEY_102: 'value_103', + }, + name_trait: 'Company', + value_trait: ['Comapny-ABC'], + }, + sentAt: '2020-10-20T07:54:58.983Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + JSON_ARRAY: {}, + JSON: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.5', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'test@rudderstack.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.5', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36', + locale: 'en-US', + os: { + name: '', + version: '', + }, + screen: { + density: 0.8999999761581421, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + test: 'other value', + }, + page: { + path: '/html/sajal.html', + referrer: '', + search: + '?utm_source=google&utm_medium=medium&utm_term=keyword&utm_content=some%20content&utm_campaign=some%20campaign&utm_test=other%20value', + title: '', + url: 'http://localhost:9116/html/sajal.html?utm_source=google&utm_medium=medium&utm_term=keyword&utm_content=some%20content&utm_campaign=some%20campaign&utm_test=other%20value', + }, + }, + type: 'group', + messageId: 'e5034df0-a404-47b4-a463-76df99934fea', + originalTimestamp: '2020-10-20T07:54:58.983Z', + anonymousId: 'my-anonymous-id-new', + userId: 'sampleusrRudder3', + integrations: { + All: true, + }, + groupId: 'Sample_groupId23', + traits: { + KEY_3: { + CHILD_KEY_92: 'value_95', + CHILD_KEY_102: 'value_103', + }, + KEY_2: { + CHILD_KEY_92: 'value_95', + CHILD_KEY_102: 'value_103', + }, + name_trait: 'Company', + value_trait: ['Comapny-ABC'], + }, + sentAt: '2020-10-20T07:54:58.983Z', + }, + FORM: {}, + }, + files: {}, + endpoint: 'https://incoming.userlist.com/rudderstack/events', + headers: { + Authorization: 'Push userlist-push-key', + 'Content-Type': 'application/json', + }, + version: '1', + params: {}, + type: 'REST', + method: 'POST', + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'userlist', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + email: 'test@rudderstack.com', + anonymousId: '12345', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + type: 'track', + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2019-10-14T11:15:18.300Z', + anonymousId: '00000000000000000000000000', + userId: '12345', + event: 'test track event', + properties: { + user_actual_role: 'system_admin', + user_actual_id: 12345, + user_time_spent: 50000, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T11:15:53.296Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + JSON_ARRAY: {}, + JSON: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + email: 'test@rudderstack.com', + anonymousId: '12345', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + type: 'track', + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2019-10-14T11:15:18.300Z', + anonymousId: '00000000000000000000000000', + userId: '12345', + event: 'test track event', + properties: { + user_actual_role: 'system_admin', + user_actual_id: 12345, + user_time_spent: 50000, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T11:15:53.296Z', + }, + FORM: {}, + }, + files: {}, + endpoint: 'https://incoming.userlist.com/rudderstack/events', + headers: { + Authorization: 'Push userlist-push-key', + 'Content-Type': 'application/json', + }, + version: '1', + params: {}, + type: 'REST', + method: 'POST', + userId: '', + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'userlist', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + anonymousId: '123456', + email: 'test@rudderstack.com', + address: { + city: 'kolkata', + country: 'India', + postalCode: 712136, + state: 'WB', + street: '', + }, + ip: '0.0.0.0', + age: 26, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + user_properties: { + prop1: 'val1', + prop2: 'val2', + }, + type: 'identify', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + integrations: { + All: true, + }, + traits: { + anonymousId: 'anon-id', + email: 'test@gmail.com', + address: { + city: 'NY', + country: 'USA', + postalCode: 712136, + state: 'CA', + street: '', + }, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'userId is required: Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: userId is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'USERLIST', + module: 'destination', + implementation: 'cdkV2', + destinationId: 'destId', + workspaceId: 'wspId', + feature: 'processor', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'userlist', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + anonymousId: '123456', + email: 'test@rudderstack.com', + address: { + city: 'kolkata', + country: 'India', + postalCode: 712136, + state: 'WB', + street: '', + }, + ip: '0.0.0.0', + age: 26, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + user_properties: { + prop1: 'val1', + prop2: 'val2', + }, + type: 'identify', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + integrations: { + All: true, + }, + traits: { + anonymousId: 'anon-id', + email: 'test@gmail.com', + address: { + city: 'NY', + country: 'USA', + postalCode: 712136, + state: 'CA', + street: '', + }, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'userId is required: Workflow: procWorkflow, Step: preparePayload, ChildStep: undefined, OriginalError: userId is required', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'USERLIST', + module: 'destination', + implementation: 'cdkV2', + destinationId: 'destId', + workspaceId: 'wspId', + feature: 'processor', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'userlist', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + Config: { + pushKey: 'userlist-push-key', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: { + anonymousId: '123456', + email: 'test@rudderstack.com', + address: { + city: 'kolkata', + country: 'India', + postalCode: 712136, + state: 'WB', + street: '', + }, + ip: '0.0.0.0', + age: 26, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + user_properties: { + prop1: 'val1', + prop2: 'val2', + }, + type: 'page', + messageId: '84e26acc-56a5-4835-8233-591137fca468', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: '123456', + integrations: { + All: true, + }, + traits: { + anonymousId: 'anon-id', + email: 'test@gmail.com', + address: { + city: 'NY', + country: 'USA', + postalCode: 712136, + state: 'CA', + street: '', + }, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'message type page is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type page is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'USERLIST', + module: 'destination', + implementation: 'cdkV2', + destinationId: 'destId', + workspaceId: 'wspId', + feature: 'processor', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/vitally/processor/data.ts b/test/integrations/destinations/vitally/processor/data.ts new file mode 100644 index 0000000000..2c3fdd3297 --- /dev/null +++ b/test/integrations/destinations/vitally/processor/data.ts @@ -0,0 +1,300 @@ +export const data = [ + { + name: 'vitally', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKeyVitally: 'abc123', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + event: 'this is a track event', + type: 'track', + properties: { + thing: 'amazing!', + }, + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + event: 'this is a track event', + type: 'track', + properties: { + thing: 'amazing!', + }, + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + }, + endpoint: 'https://api.vitally.io/rudderstack', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + userId: '', + headers: { + authorization: 'Basic abc123', + 'content-type': 'application/json', + }, + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'vitally', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKeyVitally: 'abc123', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + type: 'identify', + traits: { + name: 'Johnny Appleseed', + }, + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + type: 'identify', + traits: { + name: 'Johnny Appleseed', + }, + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + }, + endpoint: 'https://api.vitally.io/rudderstack', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + userId: '', + headers: { + authorization: 'Basic abc123', + 'content-type': 'application/json', + }, + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + { + name: 'vitally', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKeyVitally: 'abc123', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + type: 'group', + groupId: '5de17322-934e-11ed-a1eb-0242ac120002', + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON_ARRAY: {}, + XML: {}, + JSON: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + type: 'group', + groupId: '5de17322-934e-11ed-a1eb-0242ac120002', + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + }, + endpoint: 'https://api.vitally.io/rudderstack', + files: {}, + params: {}, + type: 'REST', + version: '1', + method: 'POST', + userId: '', + headers: { + authorization: 'Basic abc123', + 'content-type': 'application/json', + }, + }, + statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, + + { + name: 'vitally', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKeyVitally: 'abc123', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + message: { + userId: '0220c056-934e-11ed-a1eb-0242ac120002', + type: 'page', + groupId: '5de17322-934e-11ed-a1eb-0242ac120002', + originalTimestamp: '2023-01-13T09:03:17.562Z', + sentAt: '2023-01-13T09:03:17.562Z', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + 'message type page is not supported: Workflow: procWorkflow, Step: validateInput, ChildStep: undefined, OriginalError: message type page is not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'VITALLY', + module: 'destination', + implementation: 'cdkV2', + destinationId: 'destId', + workspaceId: 'wspId', + feature: 'processor', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/webhook/processor/data.ts b/test/integrations/destinations/webhook/processor/data.ts index d02fa58227..dbe83a79a5 100644 --- a/test/integrations/destinations/webhook/processor/data.ts +++ b/test/integrations/destinations/webhook/processor/data.ts @@ -18,15 +18,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -93,14 +103,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -110,98 +134,115 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { - timestamp: '2019-09-01T15:46:51.693229+05:30', - user_properties: { - total_payments: 0, - internetReachability: 'ReachableViaLocalAreaNetwork', - level: 6, - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - coin_balance: 9466052, - player_total_shields: 0, - isLowEndDevice: false, - game_fps: 30, - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - graphicsQuality: 'HD', - current_module_name: 'CasinoGameModule', - player_total_battles: 0, - lifetime_gem_balance: 0, - gem_balance: 0, - fb_profile: '0', - start_date: '2019-08-01', - versionSessionCount: 2, - game_name: 'FireEagleSlots', - }, - integrations: { All: true }, - event: 'spin_result', - message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { device: { - model: 'Redmi 6', - manufacturer: 'Xiaomi', id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', name: 'xiaomi', }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - address: { city: 'Dhaka', country: 'Bangladesh' }, }, - os: { version: '8.1.0', name: 'android' }, - network: { carrier: 'Banglalink' }, }, - type: 'track', + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - jackpot_win_type: 'Silver', - coin_balance: 9466052, - bet_level: 1, - ishighroller: 'False', - tournament_id: 'T1561970819', + additional_bet_index: 0, battle_id: 'N/A', bet_amount: 9, - fb_profile: '0', - player_total_shields: 0, - is_turbo: 'False', - player_total_battles: 0, + bet_level: 1, bet_multiplier: 1, - start_date: '2019-08-01', - versionSessionCount: 2, - graphicsQuality: 'HD', - is_auto_spin: 'False', + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', days_in_game: 0, - additional_bet_index: 0, - isLowEndDevice: 'False', - game_fps: 30, extra_param: 'N/A', - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - current_module_name: 'CasinoGameModule', - game_id: 'fireEagleBase', + fb_profile: '0', featureGameType: 'N/A', + game_fps: 30, + game_id: 'fireEagleBase', + game_name: 'FireEagleSlots', gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', internetReachability: 'ReachableViaLocalAreaNetwork', - total_payments: 0, + isLowEndDevice: 'False', + is_auto_spin: 'False', + is_turbo: 'False', + isf: 'False', + ishighroller: 'False', + jackpot_win_amount: 90, + jackpot_win_type: 'Silver', level: 6, - win_amount: 0, + lifetime_gem_balance: 0, no_of_spin: 1, + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + tournament_id: 'T1561970819', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + user_properties: { + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', + fb_profile: '0', + game_fps: 30, game_name: 'FireEagleSlots', - jackpot_win_amount: 90, + gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + internetReachability: 'ReachableViaLocalAreaNetwork', + isLowEndDevice: false, + level: 6, lifetime_gem_balance: 0, - isf: 'False', + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, }, }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'http://6b0e6a60.ngrok.io', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json', test2: 'value2' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -228,15 +269,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -299,10 +350,22 @@ export const data = [ versionSessionCount: 2, }, }, - destination: { Config: { webhookUrl: 'https://6b0e6a60.ngrok.io/n' } }, + destination: { + Config: { + webhookUrl: 'https://6b0e6a60.ngrok.io/n', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], - method: 'POST', }, }, output: { @@ -312,98 +375,114 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { - timestamp: '2019-09-01T15:46:51.693229+05:30', - user_properties: { - total_payments: 0, - internetReachability: 'ReachableViaLocalAreaNetwork', - level: 6, - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - coin_balance: 9466052, - player_total_shields: 0, - isLowEndDevice: false, - game_fps: 30, - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - graphicsQuality: 'HD', - current_module_name: 'CasinoGameModule', - player_total_battles: 0, - lifetime_gem_balance: 0, - gem_balance: 0, - fb_profile: '0', - start_date: '2019-08-01', - versionSessionCount: 2, - game_name: 'FireEagleSlots', - }, - integrations: { All: true }, - event: 'spin_result', - message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { device: { - model: 'Redmi 6', - manufacturer: 'Xiaomi', id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', name: 'xiaomi', }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - address: { city: 'Dhaka', country: 'Bangladesh' }, }, - os: { version: '8.1.0', name: 'android' }, - network: { carrier: 'Banglalink' }, }, - type: 'track', + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - jackpot_win_type: 'Silver', - coin_balance: 9466052, - bet_level: 1, - ishighroller: 'False', - tournament_id: 'T1561970819', + additional_bet_index: 0, battle_id: 'N/A', bet_amount: 9, - fb_profile: '0', - player_total_shields: 0, - is_turbo: 'False', - player_total_battles: 0, + bet_level: 1, bet_multiplier: 1, - start_date: '2019-08-01', - versionSessionCount: 2, - graphicsQuality: 'HD', - is_auto_spin: 'False', + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', days_in_game: 0, - additional_bet_index: 0, - isLowEndDevice: 'False', - game_fps: 30, extra_param: 'N/A', - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - current_module_name: 'CasinoGameModule', - game_id: 'fireEagleBase', + fb_profile: '0', featureGameType: 'N/A', + game_fps: 30, + game_id: 'fireEagleBase', + game_name: 'FireEagleSlots', gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', internetReachability: 'ReachableViaLocalAreaNetwork', - total_payments: 0, + isLowEndDevice: 'False', + is_auto_spin: 'False', + is_turbo: 'False', + isf: 'False', + ishighroller: 'False', + jackpot_win_amount: 90, + jackpot_win_type: 'Silver', level: 6, - win_amount: 0, + lifetime_gem_balance: 0, no_of_spin: 1, + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + tournament_id: 'T1561970819', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + user_properties: { + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', + fb_profile: '0', + game_fps: 30, game_name: 'FireEagleSlots', - jackpot_win_amount: 90, + gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + internetReachability: 'ReachableViaLocalAreaNetwork', + isLowEndDevice: false, + level: 6, lifetime_gem_balance: 0, - isf: 'False', + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, }, }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'https://6b0e6a60.ngrok.io/n', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'POST', + endpoint: 'https://6b0e6a60.ngrok.io/n', + headers: { + 'content-type': 'application/json', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -430,15 +509,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -501,10 +590,22 @@ export const data = [ versionSessionCount: 2, }, }, - destination: { Config: { webhookUrl: 'https://6b0e6a60.' } }, + destination: { + Config: { + webhookUrl: 'https://6b0e6a60.', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], - method: 'POST', }, }, output: { @@ -514,98 +615,114 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { - timestamp: '2019-09-01T15:46:51.693229+05:30', - user_properties: { - total_payments: 0, - internetReachability: 'ReachableViaLocalAreaNetwork', - level: 6, - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - coin_balance: 9466052, - player_total_shields: 0, - isLowEndDevice: false, - game_fps: 30, - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - graphicsQuality: 'HD', - current_module_name: 'CasinoGameModule', - player_total_battles: 0, - lifetime_gem_balance: 0, - gem_balance: 0, - fb_profile: '0', - start_date: '2019-08-01', - versionSessionCount: 2, - game_name: 'FireEagleSlots', - }, - integrations: { All: true }, - event: 'spin_result', - message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { device: { - model: 'Redmi 6', - manufacturer: 'Xiaomi', id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', name: 'xiaomi', }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - address: { city: 'Dhaka', country: 'Bangladesh' }, }, - os: { version: '8.1.0', name: 'android' }, - network: { carrier: 'Banglalink' }, }, - type: 'track', + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - jackpot_win_type: 'Silver', - coin_balance: 9466052, - bet_level: 1, - ishighroller: 'False', - tournament_id: 'T1561970819', + additional_bet_index: 0, battle_id: 'N/A', bet_amount: 9, - fb_profile: '0', - player_total_shields: 0, - is_turbo: 'False', - player_total_battles: 0, + bet_level: 1, bet_multiplier: 1, - start_date: '2019-08-01', - versionSessionCount: 2, - graphicsQuality: 'HD', - is_auto_spin: 'False', + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', days_in_game: 0, - additional_bet_index: 0, - isLowEndDevice: 'False', - game_fps: 30, extra_param: 'N/A', - idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', - current_module_name: 'CasinoGameModule', - game_id: 'fireEagleBase', + fb_profile: '0', featureGameType: 'N/A', + game_fps: 30, + game_id: 'fireEagleBase', + game_name: 'FireEagleSlots', gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', internetReachability: 'ReachableViaLocalAreaNetwork', - total_payments: 0, + isLowEndDevice: 'False', + is_auto_spin: 'False', + is_turbo: 'False', + isf: 'False', + ishighroller: 'False', + jackpot_win_amount: 90, + jackpot_win_type: 'Silver', level: 6, - win_amount: 0, + lifetime_gem_balance: 0, no_of_spin: 1, + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + tournament_id: 'T1561970819', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + user_properties: { + coin_balance: 9466052, + current_module_name: 'CasinoGameModule', + fb_profile: '0', + game_fps: 30, game_name: 'FireEagleSlots', - jackpot_win_amount: 90, + gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + internetReachability: 'ReachableViaLocalAreaNetwork', + isLowEndDevice: false, + level: 6, lifetime_gem_balance: 0, - isf: 'False', + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, }, }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'https://6b0e6a60.', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'POST', + endpoint: 'https://6b0e6a60.', + headers: { + 'content-type': 'application/json', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -632,17 +749,35 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', - properties: { k1: 'v1', k2: { k3: 'c3', k4: { k5: 'c5' } } }, + properties: { + k1: 'v1', + k2: { + k3: 'c3', + k4: { + k5: 'c5', + }, + }, + }, timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, @@ -650,12 +785,25 @@ export const data = [ Config: { webhookUrl: 'https://6b0e6a60.', webhookMethod: 'GET', - headers: [{ from: 'X-customHeader', to: 'customHeaderVal' }], + headers: [ + { + from: 'X-customHeader', + to: 'customHeaderVal', + }, + ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -664,15 +812,30 @@ export const data = [ body: [ { output: { + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, version: '1', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'GET', endpoint: 'https://6b0e6a60.', - headers: { 'x-customheader': 'customHeaderVal' }, - params: { k1: 'v1', 'k2.k3': 'c3', 'k2.k4.k5': 'c5' }, - body: { JSON: {}, XML: {}, JSON_ARRAY: {}, FORM: {} }, + headers: { + 'x-customheader': 'customHeaderVal', + }, + params: { + k1: 'v1', + 'k2.k3': 'c3', + 'k2.k4.k5': 'c5', + }, files: {}, - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -699,24 +862,55 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', - properties: { k1: 'v1', k2: { k3: 'c3', k4: { k5: 'c5' } } }, + properties: { + k1: 'v1', + k2: { + k3: 'c3', + k4: { + k5: 'c5', + }, + }, + }, timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, - destination: { Config: { webhookUrl: 'https://6b0e6a60.', webhookMethod: 'GET' } }, + destination: { + Config: { + webhookUrl: 'https://6b0e6a60.', + webhookMethod: 'GET', + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], - method: 'POST', }, }, output: { @@ -725,15 +919,28 @@ export const data = [ body: [ { output: { + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, version: '1', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'GET', endpoint: 'https://6b0e6a60.', headers: {}, - params: { k1: 'v1', 'k2.k3': 'c3', 'k2.k4.k5': 'c5' }, - body: { JSON: {}, XML: {}, JSON_ARRAY: {}, FORM: {} }, + params: { + k1: 'v1', + 'k2.k3': 'c3', + 'k2.k4.k5': 'c5', + }, files: {}, - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -760,15 +967,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -816,14 +1033,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', header: [ - { from: 'test1', to: 'value1' }, - { from: 'test2', to: 'value2' }, + { + from: 'test1', + to: 'value1', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -832,12 +1063,6 @@ export const data = [ body: [ { output: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'http://6b0e6a60.ngrok.io', - headers: { 'content-type': 'application/json' }, - params: {}, body: { JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', @@ -848,16 +1073,26 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, ip: '127.0.0.1', }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -901,12 +1136,24 @@ export const data = [ type: 'track', request_ip: '127.0.0.1', }, - XML: {}, JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, + version: '1', userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', + method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/json', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -933,15 +1180,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -989,14 +1246,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: 'Content-Type', to: 'application/xml' }, - { from: 'test2', to: 'value2' }, + { + from: 'Content-Type', + to: 'application/xml', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1005,12 +1276,6 @@ export const data = [ body: [ { output: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'http://6b0e6a60.ngrok.io', - headers: { 'content-type': 'application/xml', test2: 'value2' }, - params: {}, body: { JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', @@ -1021,16 +1286,26 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, ip: '127.0.0.1', }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1074,12 +1349,25 @@ export const data = [ type: 'track', request_ip: '127.0.0.1', }, - XML: {}, JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, + version: '1', userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', + method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/xml', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1100,7 +1388,9 @@ export const data = [ message: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1147,14 +1437,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: 'Content-Type', to: 'application/xml' }, - { from: 'test2', to: 'value2' }, + { + from: 'Content-Type', + to: 'application/xml', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1163,17 +1467,13 @@ export const data = [ body: [ { output: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'http://6b0e6a60.ngrok.io', - headers: { 'content-type': 'application/xml', test2: 'value2' }, - params: {}, body: { JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1216,12 +1516,25 @@ export const data = [ timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, - XML: {}, JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, + version: '1', userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', + method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/xml', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1248,15 +1561,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1269,7 +1592,9 @@ export const data = [ header: { dynamic_header_key_string: 'dynamic_header_value_string', dynamic_header_key_num: 10, - dynamic_header_key_object: { k1: 'v1' }, + dynamic_header_key_object: { + k1: 'v1', + }, }, appendPath: '/product/search?string=value', }, @@ -1277,14 +1602,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1294,8 +1633,6 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -1305,15 +1642,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1324,20 +1671,26 @@ export const data = [ timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'http://6b0e6a60.ngrok.io/product/search?string=value', + version: '1', userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', + method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io/product/search?string=value', headers: { 'content-type': 'application/json', test2: 'value2', dynamic_header_key_string: 'dynamic_header_value_string', }, - version: '1', params: {}, - type: 'REST', - method: 'POST', + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1364,15 +1717,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1388,14 +1751,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1405,8 +1782,6 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -1416,15 +1791,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1435,16 +1820,25 @@ export const data = [ timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'https://www.google.com', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json', test2: 'value2' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'POST', + endpoint: 'https://www.google.com', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1471,15 +1865,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1496,14 +1900,28 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1513,8 +1931,6 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -1524,15 +1940,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1543,16 +1969,25 @@ export const data = [ timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'https://www.google.com/?searchTerms=cats', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json', test2: 'value2' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'POST', + endpoint: 'https://www.google.com/?searchTerms=cats', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1579,15 +2014,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1605,14 +2050,28 @@ export const data = [ webhookUrl: 'http://6b0e6a60.ngrok.io', webhookMethod: 'PUT', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1622,8 +2081,6 @@ export const data = [ { output: { body: { - XML: {}, - JSON_ARRAY: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -1633,15 +2090,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1652,16 +2119,25 @@ export const data = [ timestamp: '2019-09-01T15:46:51.693229+05:30', type: 'track', }, + JSON_ARRAY: {}, + XML: {}, FORM: {}, }, - files: {}, - endpoint: 'https://www.google.com/?searchTerms=cats', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { 'content-type': 'application/json', test2: 'value2' }, version: '1', - params: {}, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', type: 'REST', method: 'PUT', + endpoint: 'https://www.google.com/?searchTerms=cats', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, + params: {}, + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1688,15 +2164,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1714,14 +2200,28 @@ export const data = [ webhookUrl: 'http://6b0e6a60.ngrok.io', webhookMethod: 'DELETE', headers: [ - { from: '', to: '' }, - { from: 'test2', to: 'value2' }, + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, }, ], - method: 'POST', }, }, output: { @@ -1730,20 +2230,31 @@ export const data = [ body: [ { output: { - body: { XML: {}, JSON_ARRAY: {}, JSON: {}, FORM: {} }, - files: {}, - endpoint: 'https://www.google.com/?searchTerms=cats', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - headers: { test2: 'value2' }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, version: '1', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', + method: 'DELETE', + endpoint: 'https://www.google.com/?searchTerms=cats', + headers: { + test2: 'value2', + }, params: { additional_bet_index: 0, battle_id: 'N/A', featureGameType: 'N/A', win_amount: 0, }, - type: 'REST', - method: 'DELETE', + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1770,15 +2281,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1845,12 +2366,25 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', webhookMethod: 'POST', - headers: [{ from: 'test2', to: 'value2' }], + headers: [ + { + from: 'test2', + to: 'value2', + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, }, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], - method: 'POST', }, }, output: { @@ -1860,7 +2394,6 @@ export const data = [ { output: { body: { - FORM: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -1870,15 +2403,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -1943,15 +2486,23 @@ export const data = [ }, JSON_ARRAY: {}, XML: {}, + FORM: {}, }, - endpoint: 'http://6b0e6a60.ngrok.io', - files: {}, - headers: { 'content-type': 'application/json', test2: 'value2' }, + version: '1', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', method: 'POST', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, params: {}, - type: 'REST', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - version: '1', + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, @@ -1978,15 +2529,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -2053,12 +2614,25 @@ export const data = [ Config: { webhookUrl: 'http://6b0e6a60.ngrok.io', webhookMethod: 'PATCH', - headers: [{ from: 'test2', to: 'value2' }], + headers: [ + { + from: 'test2', + to: 'value2', + }, + ], + }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, }, }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], - method: 'POST', }, }, output: { @@ -2068,7 +2642,6 @@ export const data = [ { output: { body: { - FORM: {}, JSON: { anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', context: { @@ -2078,15 +2651,25 @@ export const data = [ model: 'Redmi 6', name: 'xiaomi', }, - network: { carrier: 'Banglalink' }, - os: { name: 'android', version: '8.1.0' }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, traits: { - address: { city: 'Dhaka', country: 'Bangladesh' }, + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, }, event: 'spin_result', - integrations: { All: true }, + integrations: { + All: true, + }, message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', properties: { additional_bet_index: 0, @@ -2151,15 +2734,23 @@ export const data = [ }, JSON_ARRAY: {}, XML: {}, + FORM: {}, }, - endpoint: 'http://6b0e6a60.ngrok.io', - files: {}, - headers: { 'content-type': 'application/json', test2: 'value2' }, + version: '1', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + type: 'REST', method: 'PATCH', + endpoint: 'http://6b0e6a60.ngrok.io', + headers: { + 'content-type': 'application/json', + test2: 'value2', + }, params: {}, - type: 'REST', - userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', - version: '1', + files: {}, + }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', }, statusCode: 200, }, diff --git a/test/integrations/destinations/webhook/router/data.ts b/test/integrations/destinations/webhook/router/data.ts index e9c4f8701a..291fc5ffba 100644 --- a/test/integrations/destinations/webhook/router/data.ts +++ b/test/integrations/destinations/webhook/router/data.ts @@ -117,6 +117,11 @@ export const data = [ }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, }, }, { @@ -217,6 +222,11 @@ export const data = [ Config: { webhookUrl: 'https://6b0e6a60.ngrok.io/n', }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, }, }, ], @@ -360,6 +370,11 @@ export const data = [ }, ], }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, }, }, { @@ -481,6 +496,11 @@ export const data = [ Config: { webhookUrl: 'https://6b0e6a60.ngrok.io/n', }, + DestinationDefinition: { + Config: { + cdkV2Enabled: true, + }, + }, }, }, ], diff --git a/test/integrations/destinations/zapier/data.ts b/test/integrations/destinations/zapier/data.ts index 6dbabd26d8..122ffd2d1d 100644 --- a/test/integrations/destinations/zapier/data.ts +++ b/test/integrations/destinations/zapier/data.ts @@ -41,10 +41,14 @@ export const data = [ originalTimestamp: '2020-04-17T14:42:44.724Z', sentAt: '2020-04-17T14:42:44.724Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, }, Config: { @@ -116,6 +120,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -163,10 +171,14 @@ export const data = [ originalTimestamp: '2020-04-17T14:42:44.724Z', sentAt: '2020-04-17T14:42:44.724Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, }, Config: { @@ -247,6 +259,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -294,10 +310,14 @@ export const data = [ originalTimestamp: '2020-04-17T14:42:44.724Z', sentAt: '2020-04-17T14:42:44.724Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, }, Config: { @@ -387,6 +407,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -434,10 +458,14 @@ export const data = [ originalTimestamp: '2020-04-17T14:42:44.724Z', sentAt: '2020-04-17T14:42:44.724Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, }, Config: { @@ -527,6 +555,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, @@ -574,10 +606,14 @@ export const data = [ originalTimestamp: '2020-04-17T14:42:44.724Z', sentAt: '2020-04-17T14:42:44.724Z', }, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, destination: { DestinationDefinition: { Config: { - cdkEnabled: true, + cdkV2Enabled: true, }, }, Config: { @@ -658,6 +694,10 @@ export const data = [ userId: '', }, statusCode: 200, + metadata: { + destinationId: 'destId', + workspaceId: 'wspId', + }, }, ], }, diff --git a/test/integrations/sources/revenuecat/data.ts b/test/integrations/sources/revenuecat/data.ts new file mode 100644 index 0000000000..4963781763 --- /dev/null +++ b/test/integrations/sources/revenuecat/data.ts @@ -0,0 +1,286 @@ +export const data = [ + { + name: 'revenuecat', + description: 'Simple track call', + module: 'source', + version: 'v0', + input: { + request: { + body: [ + { + api_version: '1.0', + event: { + aliases: [ + 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + '389ad6dd-bb40-4c03-9471-1353da2d55ec', + ], + app_user_id: 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + commission_percentage: null, + country_code: 'US', + currency: null, + entitlement_id: null, + entitlement_ids: null, + environment: 'SANDBOX', + event_timestamp_ms: 1698617217232, + expiration_at_ms: 1698624417232, + id: '8CF0CD6C-CAF3-41FB-968A-661938235AF0', + is_family_share: null, + offer_code: null, + original_app_user_id: 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + original_transaction_id: null, + period_type: 'NORMAL', + presented_offering_id: null, + price: null, + price_in_purchased_currency: null, + product_id: 'test_product', + purchased_at_ms: 1698617217232, + store: 'APP_STORE', + subscriber_attributes: { + $displayName: { + updated_at_ms: 1698617217232, + value: 'Mister Mistoffelees', + }, + $email: { + updated_at_ms: 1698617217232, + value: 'tuxedo@revenuecat.com', + }, + $phoneNumber: { + updated_at_ms: 1698617217232, + value: '+19795551234', + }, + my_custom_attribute_1: { + updated_at_ms: 1698617217232, + value: 'catnip', + }, + }, + takehome_percentage: null, + tax_percentage: null, + transaction_id: null, + type: 'TEST', + }, + }, + ], + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + batch: [ + { + context: { + library: { + name: 'unknown', + version: 'unknown', + }, + integration: { + name: 'RevenueCat', + }, + externalId: [ + { + type: 'revenuecatAppUserId', + id: 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + }, + ], + }, + integrations: { + RevenueCat: false, + }, + type: 'track', + properties: { + aliases: [ + 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + '389ad6dd-bb40-4c03-9471-1353da2d55ec', + ], + appUserId: 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + commissionPercentage: null, + countryCode: 'US', + currency: null, + entitlementId: null, + entitlementIds: null, + environment: 'SANDBOX', + eventTimestampMs: 1698617217232, + expirationAtMs: 1698624417232, + id: '8CF0CD6C-CAF3-41FB-968A-661938235AF0', + isFamilyShare: null, + offerCode: null, + originalAppUserId: 'f8e14f51-0c76-49ba-8d67-c229f1875dd9', + originalTransactionId: null, + periodType: 'NORMAL', + presentedOfferingId: null, + price: null, + priceInPurchasedCurrency: null, + productId: 'test_product', + purchasedAtMs: 1698617217232, + store: 'APP_STORE', + subscriberAttributes: { + $displayName: { + updated_at_ms: 1698617217232, + value: 'Mister Mistoffelees', + }, + $email: { + updated_at_ms: 1698617217232, + value: 'tuxedo@revenuecat.com', + }, + $phoneNumber: { + updated_at_ms: 1698617217232, + value: '+19795551234', + }, + my_custom_attribute_1: { + updated_at_ms: 1698617217232, + value: 'catnip', + }, + }, + takehomePercentage: null, + taxPercentage: null, + transactionId: null, + type: 'TEST', + }, + event: 'TEST', + messageId: '8CF0CD6C-CAF3-41FB-968A-661938235AF0', + originalTimestamp: '2023-10-29T22:06:57.232Z', + sentAt: '2023-10-29T22:06:57.232Z', + }, + ], + }, + }, + ], + }, + }, + }, + { + name: 'revenuecat', + description: 'Initial purchase event', + module: 'source', + version: 'v0', + input: { + request: { + body: [ + { + api_version: '1.0', + event: { + aliases: ['yourCustomerAliasedID', 'yourCustomerAliasedID'], + app_id: 'yourAppID', + app_user_id: 'yourCustomerAppUserID', + commission_percentage: 0.3, + country_code: 'US', + currency: 'USD', + entitlement_id: 'pro_cat', + entitlement_ids: ['pro_cat'], + environment: 'PRODUCTION', + event_timestamp_ms: 1591121855319, + expiration_at_ms: 1591726653000, + id: 'UniqueIdentifierOfEvent', + is_family_share: false, + offer_code: 'free_month', + original_app_user_id: 'OriginalAppUserID', + original_transaction_id: '1530648507000', + period_type: 'NORMAL', + presented_offering_id: 'OfferingID', + price: 2.49, + price_in_purchased_currency: 2.49, + product_id: 'onemonth_no_trial', + purchased_at_ms: 1591121853000, + store: 'APP_STORE', + subscriber_attributes: { + '$Favorite Cat': { + updated_at_ms: 1581121853000, + value: 'Garfield', + }, + }, + takehome_percentage: 0.7, + tax_percentage: 0.3, + transaction_id: '170000869511114', + type: 'INITIAL_PURCHASE', + }, + }, + ], + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + batch: [ + { + context: { + library: { + name: 'unknown', + version: 'unknown', + }, + integration: { + name: 'RevenueCat', + }, + externalId: [ + { + type: 'revenuecatAppUserId', + id: 'yourCustomerAppUserID', + }, + ], + }, + integrations: { + RevenueCat: false, + }, + type: 'track', + properties: { + aliases: ['yourCustomerAliasedID', 'yourCustomerAliasedID'], + appId: 'yourAppID', + appUserId: 'yourCustomerAppUserID', + commissionPercentage: 0.3, + countryCode: 'US', + currency: 'USD', + entitlementId: 'pro_cat', + entitlementIds: ['pro_cat'], + environment: 'PRODUCTION', + eventTimestampMs: 1591121855319, + expirationAtMs: 1591726653000, + id: 'UniqueIdentifierOfEvent', + isFamilyShare: false, + offerCode: 'free_month', + originalAppUserId: 'OriginalAppUserID', + originalTransactionId: '1530648507000', + periodType: 'NORMAL', + presentedOfferingId: 'OfferingID', + price: 2.49, + priceInPurchasedCurrency: 2.49, + productId: 'onemonth_no_trial', + purchasedAtMs: 1591121853000, + store: 'APP_STORE', + subscriberAttributes: { + '$Favorite Cat': { + updated_at_ms: 1581121853000, + value: 'Garfield', + }, + }, + takehomePercentage: 0.7, + taxPercentage: 0.3, + transactionId: '170000869511114', + type: 'INITIAL_PURCHASE', + }, + event: 'INITIAL_PURCHASE', + messageId: 'UniqueIdentifierOfEvent', + originalTimestamp: '2020-06-02T18:17:35.319Z', + sentAt: '2020-06-02T18:17:35.319Z', + }, + ], + }, + }, + ], + }, + }, + }, +];