diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 3b6aedbc8119..000000000000 --- a/.deepsource.toml +++ /dev/null @@ -1,14 +0,0 @@ -version = 1 - -[[analyzers]] -name = "javascript" -enabled = true - -test_patterns = [ - "__tests__/*" -] - -exclude_patterns = [ - "node_modules/*", - "__mocks__/*" -] diff --git a/.dockerignore b/.dockerignore index f724f315bd91..a2d5d94a6d38 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ * !src -!features.json !Makefile !jest*.js !benchmark diff --git a/.eslintignore b/.eslintignore index 6f3387817222..8381c96050d7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,18 +1,22 @@ node_modules/ .husky/ reports/ +test/ +benchmark/ +dist/ +**/warehouse/ +**/lambda/ +**/openfaas/ *.md *.test.js -test/**/*.js +*.test.ts src/util/lodash-es-core.js **/ivm*.js **/custom*.js -**/warehouse/ -**/lambda/ -**/openfaas/ src/util/url-search-params.min.js src/logger.js src/util/eventValidations.js **/trackingPlan* src/v0/destinations/personalize/scripts/ test/integrations/destinations/testTypes.d.ts +*.config*.js diff --git a/.eslintrc.json b/.eslintrc.json index 9ac99d3ce6fc..c1c83bbcf5df 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,12 +5,21 @@ "jest": true, "commonjs": true }, - "extends": ["airbnb-base", "prettier", "plugin:json/recommended"], - "plugins": ["unicorn"], + "extends": [ + "airbnb-base", + "airbnb-typescript/base", + "plugin:sonarjs/recommended", + "prettier", + "plugin:json/recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["@typescript-eslint", "unicorn"], "globals": {}, + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, - "sourceType": "module" + "sourceType": "module", + "project": "./tsconfig.json" }, "rules": { "unicorn/filename-case": [ @@ -19,7 +28,7 @@ ], "unicorn/no-instanceof-array": "error", "unicorn/no-static-only-class": "error", - "unicorn/consistent-destructuring": "error", + "unicorn/consistent-destructuring": "off", "unicorn/better-regex": "error", "unicorn/no-for-loop": "error", "unicorn/prefer-array-some": "error", @@ -32,6 +41,28 @@ "unicorn/no-useless-length-check": "error", "unicorn/prefer-export-from": "error", "import/no-dynamic-require": "warn", - "no-param-reassign": "warn" + "no-param-reassign": "warn", + "sonarjs/prefer-immediate-return": "off", + "sonarjs/no-nested-template-literals": "off", + "sonarjs/max-switch-cases": "off", + "sonarjs/no-small-switch": "warn", + "sonarjs/cognitive-complexity": ["error", 60], + "@typescript-eslint/no-var-requires": "off", + "global-require": "off", + "@typescript-eslint/naming-convention": "off", + "@typescript-eslint/ban-types": "off", + "class-methods-use-this": "off", + "@typescript-eslint/return-await": "off", + "import/prefer-default-export": "off", + "sonarjs/no-ignored-return": "off", + "no-new": "off", + "@typescript-eslint/no-shadow": "off", + "@typescript-eslint/no-loop-func": "off", + "sonarjs/no-same-line-conditional": "off", + "no-restricted-syntax": "off", + "sonarjs/no-duplicate-string": "off", + "sonarjs/no-identical-functions": "off", + "no-prototype-builtins": "off", + "@typescript-eslint/dot-notation": "warn" } } diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3c337aafbabb..d8cdf2f6c095 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,7 +4,6 @@ about: Create a report to help us improve title: 'BUG: ' labels: '' assignees: ItsSudip, krishna2020, sandeepdsvs, shrouti1507 - --- **Describe the bug** diff --git a/.github/workflows/build-pr-artifacts.yml b/.github/workflows/build-pr-artifacts.yml index d393f96acfd4..b317192429a6 100644 --- a/.github/workflows/build-pr-artifacts.yml +++ b/.github/workflows/build-pr-artifacts.yml @@ -168,7 +168,7 @@ jobs: GIT_COMMIT_SHA=${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - + # Temp fix # https://github.com/docker/build-push-action/issues/252 # https://github.com/moby/buildkit/issues/1896 diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 42ef06fd410e..64455dbec6d0 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -73,6 +73,8 @@ jobs: run: | echo "Current version: $CURRENT_VERSION_VALUE" echo "New version: $NEW_VERSION_VALUE" + npx replace $CURRENT_VERSION_VALUE $NEW_VERSION_VALUE sonar-project.properties + git add sonar-project.properties npm run release -- -a --skip.tag --no-verify git push diff --git a/.github/workflows/prepare-for-dev-deploy.yml b/.github/workflows/prepare-for-dev-deploy.yml index 1ceda5948348..784779eefd29 100644 --- a/.github/workflows/prepare-for-dev-deploy.yml +++ b/.github/workflows/prepare-for-dev-deploy.yml @@ -147,4 +147,3 @@ jobs: build-args: | version=${{ steps.gen_tag_name.outputs.tag_name }} GIT_COMMIT_SHA=${{ github.sha }} - diff --git a/.github/workflows/prepare-for-prod-deploy.yml b/.github/workflows/prepare-for-prod-deploy.yml index c3832bf0d5b3..ab616c4976b3 100644 --- a/.github/workflows/prepare-for-prod-deploy.yml +++ b/.github/workflows/prepare-for-prod-deploy.yml @@ -189,7 +189,7 @@ jobs: create-pull-request: name: Update Helm Charts For Production and Create Pull Request runs-on: ubuntu-latest - needs: [ build-transformer-image, build-user-transformer-image ] + needs: [build-transformer-image, build-user-transformer-image] env: TAG_NAME: ${{ needs.build-transformer-image.outputs.tag_name }} UT_TAG_NAME: ${{ needs.build-user-transformer-image.outputs.tag_name }} @@ -241,4 +241,3 @@ jobs: git push -u origin shared-transformer-$TAG_NAME hub pull-request -m "chore: upgrade shared transformers to $TAG_NAME" - diff --git a/.github/workflows/prepare-for-prod-rollback.yml b/.github/workflows/prepare-for-prod-rollback.yml index 2b2a861d8e21..3a2a60abc43e 100644 --- a/.github/workflows/prepare-for-prod-rollback.yml +++ b/.github/workflows/prepare-for-prod-rollback.yml @@ -55,5 +55,5 @@ jobs: git commit -m "chore: rollback shared transformers to ${{ steps.target-version.outputs.tag_name }}" git push -u origin shared-transformer-rollback-${{ steps.target-version.outputs.tag_name }} - + hub pull-request -m "chore: rollback shared transformers to ${{ steps.target-version.outputs.tag_name }}" diff --git a/.github/workflows/prepare-for-staging-deploy.yml b/.github/workflows/prepare-for-staging-deploy.yml index a43b59e7ad51..7921fd4283a8 100644 --- a/.github/workflows/prepare-for-staging-deploy.yml +++ b/.github/workflows/prepare-for-staging-deploy.yml @@ -181,7 +181,7 @@ jobs: create-pull-request: name: Update Helm Charts For Staging and Create Pull Request runs-on: ubuntu-latest - needs: [ build-transformer-image, build-user-transformer-image ] + needs: [build-transformer-image, build-user-transformer-image] env: TAG_NAME: ${{ needs.build-transformer-image.outputs.tag_name }} UT_TAG_NAME: ${{ needs.build-user-transformer-image.outputs.tag_name }} @@ -231,7 +231,3 @@ jobs: git push -u origin $BRANCH_NAME hub pull-request -m "chore: upgrade staging env transformers to \"$TAG_NAME\"" fi - - - - diff --git a/.github/workflows/publish-new-release.yml b/.github/workflows/publish-new-release.yml index ee6f41d40410..c58d54ad24b9 100644 --- a/.github/workflows/publish-new-release.yml +++ b/.github/workflows/publish-new-release.yml @@ -119,4 +119,3 @@ jobs: } ] } - diff --git a/.github/workflows/report-code-coverage.yml b/.github/workflows/report-code-coverage.yml index 7fc2ad672158..74a67560f2cc 100644 --- a/.github/workflows/report-code-coverage.yml +++ b/.github/workflows/report-code-coverage.yml @@ -25,9 +25,28 @@ jobs: run: npm ci - name: Run Tests - run: npm run test:ci + run: | + npm run test:ci + + - name: Run Lint Checks + run: | + npm run check:lint + npm run lint:fix - name: Upload Coverage Reports to Codecov uses: codecov/codecov-action@v3.1.3 with: directory: ./reports/coverage + + - name: Fix filesystem paths in generated reports + if: always() + run: | + sed -i 's+home/runner/work/rudder-transformer/rudder-transformer+/github/workspace+g' reports/coverage/lcov.info + sed -i 's+/home/runner/work/rudder-transformer/rudder-transformer+/github/workspace+g' reports/eslint.json + + - name: SonarCloud Scan + if: always() + uses: SonarSource/sonarcloud-github-action@v1.8 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index 451e2fdaa928..6edf0b39bb05 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ node_modules npm-debug.log reports/* -dist \ No newline at end of file +.eslintcache +dist + diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9c3cdaa7c6..878a8d76596b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ 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.26.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.25.0...v1.26.0) (2023-05-05) + + +### Features + +* intercom group support ([#2089](https://github.com/rudderlabs/rudder-transformer/issues/2089)) ([8185f28](https://github.com/rudderlabs/rudder-transformer/commit/8185f288f8b6c0822f6aea8bf080d6b2b9ef2691)) + + +### Bug Fixes + +* allow null values to be passed in Braze for standard properties ([#2111](https://github.com/rudderlabs/rudder-transformer/issues/2111)) ([10d037a](https://github.com/rudderlabs/rudder-transformer/commit/10d037a17aae9ff0e60be1276120a2a1fa6c6a86)) +* call to lower case only when message.type is defined ([#2109](https://github.com/rudderlabs/rudder-transformer/issues/2109)) ([71c1e7a](https://github.com/rudderlabs/rudder-transformer/commit/71c1e7aea8c14904660908eabf2eabb060315410)) +* remove skip verify flag ([#2114](https://github.com/rudderlabs/rudder-transformer/issues/2114)) ([c4b0a69](https://github.com/rudderlabs/rudder-transformer/commit/c4b0a695442bb30c280c7301a10aea773f610e4f)) + ## [1.25.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.24.0...v1.25.0) (2023-05-02) diff --git a/CODEOWNERS b/CODEOWNERS index e017fc53e32a..d8dbed405330 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,6 +3,6 @@ __tests__/ @rudderlabs/integrations __mocks__/ @rudderlabs/integrations v0/ @rudderlabs/integrations cdk/ @rudderlabs/integrations -features.json/ @rudderlabs/integrations +src/features.json @rudderlabs/integrations constants/ @rudderlabs/integrations warehouse/ @rudderlabs/warehouse diff --git a/commitlint.config.js b/commitlint.config.js index 7ff4e06d600d..8ade7fe18484 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,6 +1,6 @@ module.exports = { extends: ['@commitlint/config-conventional'], rules: { - 'type-enum': () => [2, 'always', ['fix', 'feat', 'chore', 'refactor', 'docs', 'test']] - } + 'type-enum': () => [2, 'always', ['fix', 'feat', 'chore', 'refactor', 'docs', 'test']], + }, }; diff --git a/github-release.config.js b/github-release.config.js index f899cac8861b..df269d8a02b5 100644 --- a/github-release.config.js +++ b/github-release.config.js @@ -1,5 +1,5 @@ module.exports = { - gitRawCommitsOpts: { - merges: null - } -} + gitRawCommitsOpts: { + merges: null, + }, +}; diff --git a/jest.config.js b/jest.config.js index 95c861c07008..321693d52618 100644 --- a/jest.config.js +++ b/jest.config.js @@ -92,7 +92,18 @@ module.exports = { // projects: null, // Use this configuration option to add custom reporters to Jest - // reporters: undefined, + reporters: [ + 'default', + [ + 'jest-sonar', + { + outputDirectory: 'reports/sonar', + outputName: 'results-report.xml', + reportedFilePath: 'relative', + relativeRootDir: './', + }, + ], + ], // Automatically reset mock state between every test // resetMocks: false, diff --git a/package-lock.json b/package-lock.json index 0800262aad2e..db2f331f1f42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.25.0", + "version": "1.26.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3360,6 +3360,12 @@ "pretty-format": "^29.0.0" } }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -3393,6 +3399,12 @@ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==" }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -3412,6 +3424,142 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, + "@typescript-eslint/eslint-plugin": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", + "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.2", + "@typescript-eslint/type-utils": "5.59.2", + "@typescript-eslint/utils": "5.59.2", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", + "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.59.2", + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/typescript-estree": "5.59.2", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", + "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", + "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/visitor-keys": "5.59.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", + "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "eslint-visitor-keys": "^3.3.0" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", + "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/visitor-keys": "5.59.2" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", + "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "dev": true + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", + "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "eslint-visitor-keys": "^3.3.0" + } + } + } + }, + "@typescript-eslint/type-utils": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", + "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/utils": "5.59.2", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", + "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", + "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/visitor-keys": "5.59.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", + "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "eslint-visitor-keys": "^3.3.0" + } + } + } + }, "@typescript-eslint/types": { "version": "5.56.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", @@ -3433,6 +3581,71 @@ "tsutils": "^3.21.0" } }, + "@typescript-eslint/utils": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", + "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.2", + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/typescript-estree": "5.59.2", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", + "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", + "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/visitor-keys": "5.59.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", + "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, "@typescript-eslint/visitor-keys": { "version": "5.56.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", @@ -6725,6 +6938,12 @@ "tapable": "^2.2.0" } }, + "entities": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", + "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -7024,6 +7243,15 @@ } } }, + "eslint-config-airbnb-typescript": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz", + "integrity": "sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^15.0.0" + } + }, "eslint-config-prettier": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", @@ -7229,6 +7457,12 @@ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "dev": true }, + "eslint-plugin-sonarjs": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.19.0.tgz", + "integrity": "sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==", + "dev": true + }, "eslint-plugin-unicorn": { "version": "46.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-46.0.0.tgz", @@ -9841,6 +10075,16 @@ "semver": "^7.3.5" } }, + "jest-sonar": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/jest-sonar/-/jest-sonar-0.2.15.tgz", + "integrity": "sha512-hJSM9AIAbhTjhalduCYuOmZA+9VmNUZR+Ccm35iLQjlMS7k6NK8OLJMRJGS2mqwzd8akZmHbcyK4TkUz4ZG1Pg==", + "dev": true, + "requires": { + "entities": "4.3.0", + "strip-ansi": "6.0.1" + } + }, "jest-util": { "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", @@ -11048,6 +11292,12 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -12088,9 +12338,9 @@ "dev": true }, "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", "requires": { "side-channel": "^1.0.4" } diff --git a/package.json b/package.json index 450e8ab1cfc4..e7a6cb2de502 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.25.0", + "version": "1.26.0", "description": "", "homepage": "https://github.com/rudderlabs/rudder-transformer#readme", "bugs": { @@ -21,7 +21,6 @@ "format": "prettier --write .", "lint": "eslint . || exit 0", "lint:fix": "eslint . --fix", - "lint:check": "eslint --ext .js,.json . --fix; exit 0", "lint:fix:json": "eslint --ext .json --fix .", "check:merge": "npm run verify || exit 1; codecov", "start": "node ./dist/src/index.js", @@ -37,11 +36,13 @@ "test:silent": "npm run test -- --silent", "test:benchmark": "node benchmark/index.js", "test:integration": "jest -c jest.config.integration.js --detectOpenHandles", - "pre-commit": "npm run test:silent && npx lint-staged", + "test:integration:silent": "jest -c jest.config.integration.js --detectOpenHandles --silent", + "pre-commit": "npm run test:silent && npm run test:integration:silent && npx lint-staged", "commit-msg": "commitlint --edit", "prepare": "husky install", "release": "npx standard-version", - "release:github": "DEBUG=conventional-github-releaser npx conventional-github-releaser -p angular --config github-release.config.js" + "release:github": "DEBUG=conventional-github-releaser npx conventional-github-releaser -p angular --config github-release.config.js", + "check:lint": "eslint . -f json -o reports/eslint.json || exit 0" }, "dependencies": { "@amplitude/ua-parser-js": "0.7.24", @@ -90,6 +91,7 @@ "parse-static-imports": "^1.1.0", "pprof": "^3.2.0", "prom-client": "^14.2.0", + "qs": "^6.11.1", "rudder-transformer-cdk": "^1.4.5", "rudder-workflow-engine": "^0.4.5", "set-value": "^4.1.0", @@ -106,6 +108,8 @@ "@commitlint/config-conventional": "^17.4.4", "@digitalroute/cz-conventional-changelog-for-jira": "^8.0.0", "@types/jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", "acorn": "^8.8.2", "benchmark-suite": "^0.1.8", "commander": "^10.0.0", @@ -115,6 +119,7 @@ "eslint": "^8.36.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-json": "^3.1.0", @@ -122,11 +127,13 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-sonarjs": "^0.19.0", "eslint-plugin-unicorn": "^46.0.0", "http-terminator": "^3.2.0", "husky": "^8.0.3", "jest": "^29.5.0", "jest-date-mock": "^1.0.8", + "jest-sonar": "^0.2.15", "jest-when": "^3.5.2", "lint-staged": "^13.2.0", "madge": "^6.0.0", @@ -140,7 +147,7 @@ "typescript": "^5.0.3" }, "lint-staged": { - "*.{js,ts}": "eslint --fix", + "*.{js,ts}": "eslint --cache --fix", "*.{json,js,ts,md}": "prettier --write" }, "config": { diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000000..e620e4d7ac7e --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,35 @@ +sonar.log.level=INFO +sonar.verbose=false +sonar.qualitygate.wait=false + +# Project details +sonar.projectKey=rudderlabs_rudder-transformer +sonar.organization=rudderlabs +sonar.projectName=rudder-transformer +sonar.projectVersion=1.19.0 + +# Meta-data for the project +sonar.links.scm=https://github.com/rudderlabs/rudder-transformer +sonar.links.issue=https://github.com/rudderlabs/rudder-transformer/issues + +# Path to reports +sonar.javascript.lcov.reportPaths=reports/coverage/lcov.info +sonar.testExecutionReportPaths=reports/sonar/results-report.xml +sonar.eslint.reportPaths=reports/eslint.json + +# Path to sources +sonar.sources=src,benchmark +sonar.inclusions=**/*.js +sonar.exclusions=**/*.json,**/*.html,**/*.png,**/*.jpg,**/*.gif,**/*.svg,**/*.yml,src/util/libExtractor.js,src/util/url-search-params.min.js,src/util/lodash-es-core.js + +# Path to tests +sonar.tests=test +sonar.test.inclusions=**/*.test.js +sonar.test.exclusions=**/*.json,**/*.html,**/*.png,**/*.jpg,**/*.gif,**/*.svg +sonar.coverage.exclusions=test/**/*,**/*.json,**/*.html,**/*.png,**/*.jpg,**/*.gif,**/*.svg + +# Source encoding +sonar.sourceEncoding=UTF-8 + +# Exclusions for copy-paste detection +sonar.cpd.exclusions=test/**/* diff --git a/src/.nvmrc b/src/.nvmrc deleted file mode 100644 index 049c407af78c..000000000000 --- a/src/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -14.21.1 diff --git a/src/adapters/utils/networkUtils.js b/src/adapters/utils/networkUtils.js index 85eca88630e3..4329c5c67ab8 100644 --- a/src/adapters/utils/networkUtils.js +++ b/src/adapters/utils/networkUtils.js @@ -77,12 +77,10 @@ const getDynamicErrorType = (statusCode) => { if (isHttpStatusRetryable(statusCode)) { return tags.ERROR_TYPES.RETRYABLE; } - switch (statusCode) { - case 429: - return tags.ERROR_TYPES.THROTTLED; - default: - return tags.ERROR_TYPES.ABORTED; + if (statusCode === 429) { + return tags.ERROR_TYPES.THROTTLED; } + return tags.ERROR_TYPES.ABORTED; }; const parseDestResponse = (destResponse, destination = '') => { diff --git a/src/cdk/v1/autopilot/transform.js b/src/cdk/v1/autopilot/transform.js index ba099102b529..613b985c0d58 100644 --- a/src/cdk/v1/autopilot/transform.js +++ b/src/cdk/v1/autopilot/transform.js @@ -40,6 +40,7 @@ function trackPostMapper(event, mappedPayload, rudderContext) { const contactIdOrEmail = Utils.getFieldValueFromMessage(message, 'email'); if (contactIdOrEmail) { + // eslint-disable-next-line no-param-reassign rudderContext.endpoint = `https://api2.autopilothq.com/v1/trigger/${destination.Config.triggerId}/contact/${contactIdOrEmail}`; } else { throw new InstrumentationError('Email is required for track calls'); diff --git a/src/cdk/v1/handler.js b/src/cdk/v1/handler.js index 74bf5892923a..cf3f0c48375a 100644 --- a/src/cdk/v1/handler.js +++ b/src/cdk/v1/handler.js @@ -56,17 +56,11 @@ function getErrorInfo(err) { default: break; } - - switch (err.statTags.scope) { - case TRANSFORMER_METRIC.MEASUREMENT_TYPE.EXCEPTION.SCOPE: - errInstance = new TransformationError( - `Unknown error occurred. Original error: ${err.message}`, - ); - break; - default: - break; + if (err.statTags.scope === TRANSFORMER_METRIC.MEASUREMENT_TYPE.EXCEPTION.SCOPE) { + errInstance = new TransformationError( + `Unknown error occurred. Original error: ${err.message}`, + ); } - if (errInstance) { return generateErrorObject(errInstance, defTags); } diff --git a/src/cdk/v1/kochava/transform.js b/src/cdk/v1/kochava/transform.js index d0fdb4b5f945..504981aa6a4f 100644 --- a/src/cdk/v1/kochava/transform.js +++ b/src/cdk/v1/kochava/transform.js @@ -10,6 +10,7 @@ const eventNameMapping = { }; function processExtraPayloadParams(event, mappedPayload) { + const clonedMappedPayload = { ...mappedPayload }; const { message } = event; let eventName = message.event; const eventData = message.properties || {}; @@ -64,12 +65,12 @@ function processExtraPayloadParams(event, mappedPayload) { device_ua: message.context?.userAgent || '', currency: eventData?.currency || 'USD', }; - mappedPayload.data = { ...mappedPayload.data, ...extraParams }; + clonedMappedPayload.data = { ...clonedMappedPayload.data, ...extraParams }; // Note: "defaultValue" cannot be empty string hence had to manually set it here since kochava requires it if (Utils.getValueFromMessage(message, 'context.os.version') === '') { - mappedPayload.data.os_version = ''; + clonedMappedPayload.data.os_version = ''; } - return mappedPayload; + return clonedMappedPayload; } module.exports = { diff --git a/src/cdk/v1/new_relic/transform.js b/src/cdk/v1/new_relic/transform.js index b8fa0cd13b34..4c4a4bab8888 100644 --- a/src/cdk/v1/new_relic/transform.js +++ b/src/cdk/v1/new_relic/transform.js @@ -85,14 +85,10 @@ function commonPostMapper(event, mappedPayload, rudderContext) { } // Upon users choice for data center, we are updating the endpoint accordingly - switch (destConfig.dataCenter) { - case 'eu': - rudderContext.endpoint = `https://insights-collector.eu01.nr-data.net/v1/accounts/${destConfig.accountId}/events`; - break; - default: - rudderContext.endpoint = `https://insights-collector.newrelic.com/v1/accounts/${destConfig.accountId}/events`; - break; - } + rudderContext.endpoint = + destConfig.dataCenter === 'eu' + ? `https://insights-collector.eu01.nr-data.net/v1/accounts/${destConfig.accountId}/events` + : `https://insights-collector.newrelic.com/v1/accounts/${destConfig.accountId}/events`; rudderContext.insertKey = destConfig.insertKey; diff --git a/src/cdk/v1/vitally/config.yaml b/src/cdk/v1/vitally/config.yaml index 5ac724da8fcc..c7edbacca2f5 100644 --- a/src/cdk/v1/vitally/config.yaml +++ b/src/cdk/v1/vitally/config.yaml @@ -9,7 +9,7 @@ message: response: format: JSON method: POST - endpoint: "https://api.vitally.io/rudderstack" + endpoint: 'https://api.vitally.io/rudderstack' headers: - authorization: "Basic {{ destConfig.apiKeyVitally }}" - content-type: "application/json" + authorization: 'Basic {{ destConfig.apiKeyVitally }}' + content-type: 'application/json' diff --git a/src/cdk/v1/zapier/transform.js b/src/cdk/v1/zapier/transform.js index 799f457b6e8f..d99c3af31529 100644 --- a/src/cdk/v1/zapier/transform.js +++ b/src/cdk/v1/zapier/transform.js @@ -1,3 +1,4 @@ +/* eslint-disable no-param-reassign */ const { getHashFromArray } = require('../../../v0/util'); function commonPostMapper(event, mappedPayload, rudderContext) { diff --git a/src/cdk/v2/bindings/default.js b/src/cdk/v2/bindings/default.js index ff69dac6ffd8..07c548e888ce 100644 --- a/src/cdk/v2/bindings/default.js +++ b/src/cdk/v2/bindings/default.js @@ -12,9 +12,7 @@ function isValidEventType(event) { if (!eventType || typeof eventType !== 'string') return false; const sanitizedEventType = eventType.trim().toLowerCase(); - if (!SUPPORTED_EVENT_TYPES.includes(sanitizedEventType)) return false; - - return true; + return SUPPORTED_EVENT_TYPES.includes(sanitizedEventType); } function assert(val, message) { diff --git a/src/cdk/v2/destinations/webhook/procWorkflow.yaml b/src/cdk/v2/destinations/webhook/procWorkflow.yaml index 9eb41acebf19..7095161a6b30 100644 --- a/src/cdk/v2/destinations/webhook/procWorkflow.yaml +++ b/src/cdk/v2/destinations/webhook/procWorkflow.yaml @@ -22,26 +22,26 @@ steps: $.assertConfig(.destination.Config.webhookUrl, "Invalid URL in destination config"); - name: deduceMethod template: | - $.context.method = .destination.Config.webhookMethod ?? 'POST'; + $.context.method = .destination.Config.webhookMethod ?? 'POST'; - name: buildHeaderBlock template: | - let defaultHeaders = $.context.method in ['POST', 'PUT', 'PATCH'] ? {"content-type": "application/json"} : {} - let configHeaders = $.getHashFromArray(.destination.Config.headers) - let messageHeader = typeof .message.header === "object" ? Object.assign(...Object.entries(.message.header).{typeof .[1] === 'string'}[].({[.[0]]: .[1]})[]) : {} - $.context.finalHeaders = { - ...defaultHeaders, - ...configHeaders, - ...messageHeader - } + let defaultHeaders = $.context.method in ['POST', 'PUT', 'PATCH'] ? {"content-type": "application/json"} : {} + let configHeaders = $.getHashFromArray(.destination.Config.headers) + let messageHeader = typeof .message.header === "object" ? Object.assign(...Object.entries(.message.header).{typeof .[1] === 'string'}[].({[.[0]]: .[1]})[]) : {} + $.context.finalHeaders = { + ...defaultHeaders, + ...configHeaders, + ...messageHeader + } - name: deduceEndPoint template: | - let integrationsObjects = $.getIntegrationsObj(.message, "webhook"); - let defaultEndpoint = .destination.Config.webhookUrl; - let messageAppendPath = .message.appendPath ?? integrationsObjects.appendPath ?? ""; - - $.context.finalEndpoint = .message.fullPath ?? integrationsObjects.fullPath ?? defaultEndpoint; - $.context.finalEndpoint = $.context.finalEndpoint + messageAppendPath; + let integrationsObjects = $.getIntegrationsObj(.message, "webhook"); + let defaultEndpoint = .destination.Config.webhookUrl; + let messageAppendPath = .message.appendPath ?? integrationsObjects.appendPath ?? ""; + + $.context.finalEndpoint = .message.fullPath ?? integrationsObjects.fullPath ?? defaultEndpoint; + $.context.finalEndpoint = $.context.finalEndpoint + messageAppendPath; - name: prepareContext template: | $.context.params = {} @@ -62,20 +62,19 @@ steps: $.context.payload = $.removeUndefinedAndNullValues(payload) - name: buildResponseForProcessTransformation template: | - $.context.payload.({ - "body": { - "JSON": ., - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "version": "1", - "userId": ^.message.anonymousId, - "type": "REST", - "method": $.context.method, - "endpoint": $.context.finalEndpoint, - "headers": $.context.finalHeaders, - "params": $.context.params, - "files": {} - }) - \ No newline at end of file + $.context.payload.({ + "body": { + "JSON": ., + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "version": "1", + "userId": ^.message.anonymousId, + "type": "REST", + "method": $.context.method, + "endpoint": $.context.finalEndpoint, + "headers": $.context.finalHeaders, + "params": $.context.params, + "files": {} + }) diff --git a/src/cdk/v2/destinations/webhook/rtWorkflow.yaml b/src/cdk/v2/destinations/webhook/rtWorkflow.yaml index 122dbe4d5140..335293b6dbc4 100644 --- a/src/cdk/v2/destinations/webhook/rtWorkflow.yaml +++ b/src/cdk/v2/destinations/webhook/rtWorkflow.yaml @@ -1,6 +1,6 @@ bindings: -- name: handleRtTfSingleEventError - path: ../../../../v0/util/index + - name: handleRtTfSingleEventError + path: ../../../../v0/util/index steps: - name: validateInput @@ -29,4 +29,3 @@ steps: - name: finalPayload template: | [...$.outputs.failedEvents, ...$.outputs.successfulEvents] - diff --git a/src/cdk/v2/handler.js b/src/cdk/v2/handler.js index 6d0e678c6218..bba2c02fd170 100644 --- a/src/cdk/v2/handler.js +++ b/src/cdk/v2/handler.js @@ -51,7 +51,7 @@ async function process(workflowEngine, parsedEvent) { async function processCdkV2Workflow(destType, parsedEvent, feature, bindings = {}) { try { const workflowEngine = await getCachedWorkflowEngine(destType, feature, bindings); - return process(workflowEngine, parsedEvent); + return await process(workflowEngine, parsedEvent); } catch (error) { throw getErrorInfo(error, isCdkV2Destination(parsedEvent), defTags); } diff --git a/src/controllers/bulkUpload.ts b/src/controllers/bulkUpload.ts index 7fc20b7e3d0f..80fb9b9dd00e 100644 --- a/src/controllers/bulkUpload.ts +++ b/src/controllers/bulkUpload.ts @@ -2,26 +2,20 @@ import { client as errNotificationClient } from '../util/errorNotifier'; import logger from '../logger'; // TODO: To be refactored and redisgned -const getDestFileUploadHandler = (version, dest) => { - return require(`../${version}/destinations/${dest}/fileUpload`); -}; -const getPollStatusHandler = (version, dest) => { - return require(`../${version}/destinations/${dest}/poll`); -}; -const getJobStatusHandler = (version, dest) => { - return require(`../${version}/destinations/${dest}/fetchJobStatus`); -}; +const getDestFileUploadHandler = (version, dest) => + require(`../${version}/destinations/${dest}/fileUpload`); +const getPollStatusHandler = (version, dest) => require(`../${version}/destinations/${dest}/poll`); +const getJobStatusHandler = (version, dest) => + require(`../${version}/destinations/${dest}/fetchJobStatus`); -const getCommonMetadata = (ctx) => { +const getCommonMetadata = (ctx) => // TODO: Parse information such as // cluster, namespace, etc information // from the request - return { + ({ namespace: 'Unknown', cluster: 'Unknown', - }; -}; - + }); export const fileUpload = async (ctx) => { logger.debug( 'Native(Bulk-Upload): Request to transformer:: /fileUpload route', diff --git a/src/controllers/delivery.ts b/src/controllers/delivery.ts index 84ec7186b9fc..d9a514d96169 100644 --- a/src/controllers/delivery.ts +++ b/src/controllers/delivery.ts @@ -12,8 +12,8 @@ export default class DeliveryController { public static async deliverToDestination(ctx: Context) { logger.debug('Native(Delivery):: Request to transformer::', JSON.stringify(ctx.request.body)); let deliveryResponse: DeliveryResponse; - let requestMetadata = MiscService.getRequestMetadata(ctx); - let event = ctx.request.body as ProcessorTransformationOutput; + const requestMetadata = MiscService.getRequestMetadata(ctx); + const event = ctx.request.body as ProcessorTransformationOutput; const { destination }: { destination: string } = ctx.params; const integrationService = ServiceSelector.getNativeDestinationService(); try { diff --git a/src/controllers/destination.ts b/src/controllers/destination.ts index d7f85db1d5fa..158d6119d0cb 100644 --- a/src/controllers/destination.ts +++ b/src/controllers/destination.ts @@ -23,7 +23,7 @@ export default class DestinationController { JSON.stringify(ctx.request.body), ); let resplist: ProcessorTransformationResponse[]; - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); let events = ctx.request.body as ProcessorTransformationRequest[]; const metaTags = MiscService.getMetaTags(events[0].metadata); const { version, destination }: { version: string; destination: string } = ctx.params; @@ -91,14 +91,14 @@ export default class DestinationController { 'Native(Router-Transform):: Requst to transformer::', JSON.stringify(ctx.request.body), ); - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); const routerRequest = ctx.request.body as RouterTransformationRequest; const destination = routerRequest.destType; let events = routerRequest.input; const metaTags = MiscService.getMetaTags(events[0].metadata); stats.histogram('dest_transform_input_events', events.length, { destination, - version: "v0", + version: 'v0', ...metaTags, }); const integrationService = ServiceSelector.getDestinationService(events); @@ -119,9 +119,7 @@ export default class DestinationController { events[0].metadata.workspaceId, tags.FEATURES.ROUTER, ); - metaTO.metadatas = events.map((ev) => { - return ev.metadata; - }); + metaTO.metadatas = events.map((ev) => ev.metadata); const errResp = PostTransformationDestinationService.handleRouterTransformFailureEvents( error, metaTO, @@ -131,7 +129,7 @@ export default class DestinationController { ControllerUtility.postProcess(ctx); stats.histogram('dest_transform_output_events', ctx.body?.output?.length, { destination, - version: "v0", + version: 'v0', ...metaTags, }); logger.debug( @@ -146,7 +144,7 @@ export default class DestinationController { 'Native(Process-Transform-Batch):: Requst to transformer::', JSON.stringify(ctx.request.body), ); - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); const routerRequest = ctx.request.body as RouterTransformationRequest; const destination = routerRequest.destType; let events = routerRequest.input; @@ -167,9 +165,7 @@ export default class DestinationController { events[0].metadata.workspaceId, tags.FEATURES.BATCH, ); - metaTO.metadatas = events.map((ev) => { - return ev.metadata; - }); + metaTO.metadatas = events.map((ev) => ev.metadata); const errResp = PostTransformationDestinationService.handleBatchTransformFailureEvents( error, metaTO, diff --git a/src/controllers/eventTest.ts b/src/controllers/eventTest.ts index 16ae52a3cfbd..6faf047d70f0 100644 --- a/src/controllers/eventTest.ts +++ b/src/controllers/eventTest.ts @@ -3,6 +3,7 @@ import EventTesterService from '../services/eventTest/eventTester'; export default class EventTestController { private static API_VERSION = '1'; + public static async testEvent(ctx: Context) { const { version, destination }: { version: string; destination: string } = ctx.params as any; const { events }: { events: any } = ctx.request.body as any; diff --git a/src/controllers/profile.ts b/src/controllers/profile.ts index 232208256cff..5f2dce4fe668 100644 --- a/src/controllers/profile.ts +++ b/src/controllers/profile.ts @@ -2,6 +2,7 @@ import { Context } from 'koa'; import MiscService from '../services/misc'; import ProfileService from '../services/profile'; import ControllerUtility from './util'; + export default class ProfileController { /** * Example usage of API @@ -29,7 +30,7 @@ export default class ProfileController { }' */ public static async profile(ctx: Context) { - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); const format = ctx.request.query.format as string; const { credBucketDetails } = ctx.request.body as any; const response = await ProfileService.profile(credBucketDetails, format); diff --git a/src/controllers/source.ts b/src/controllers/source.ts index 1dcb8bc66ed5..a413426cc748 100644 --- a/src/controllers/source.ts +++ b/src/controllers/source.ts @@ -11,7 +11,7 @@ export default class SourceController { 'Native(Source-Transform):: Request to transformer::', JSON.stringify(ctx.request.body), ); - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); const events = ctx.request.body as Object[]; const { version, source }: { version: string; source: string } = ctx.params; const integrationService = ServiceSelector.getNativeSourceService(); diff --git a/src/controllers/userTransform.ts b/src/controllers/userTransform.ts index 1fa4ddce35a7..8d25c3d10432 100644 --- a/src/controllers/userTransform.ts +++ b/src/controllers/userTransform.ts @@ -4,7 +4,11 @@ import { ProcessorTransformationRequest, UserTransformationServiceResponse } fro import { compileUserLibrary } from '../util/ivmFactory'; import UserTransformService from '../services/userTransform'; import logger from '../logger'; -import { setupUserTransformHandler, extractLibraries, validateCode } from '../util/customTransformer'; +import { + setupUserTransformHandler, + extractLibraries, + validateCode, +} from '../util/customTransformer'; import ControllerUtility from './util'; export default class UserTransformController { @@ -13,7 +17,7 @@ export default class UserTransformController { '(User transform - router:/customTransform ):: Request to transformer', JSON.stringify(ctx.request.body), ); - let requestMetadata = MiscService.getRequestMetadata(ctx); + const requestMetadata = MiscService.getRequestMetadata(ctx); const events = ctx.request.body as ProcessorTransformationRequest[]; const processedRespone: UserTransformationServiceResponse = await UserTransformService.transformRoutine(events); diff --git a/src/controllers/util/index.ts b/src/controllers/util/index.ts index 1b12bf7c866b..29979241bb5d 100644 --- a/src/controllers/util/index.ts +++ b/src/controllers/util/index.ts @@ -3,12 +3,12 @@ import { API_VERSION } from '../../routes/utils/constants'; import { isHttpStatusSuccess } from '../../v0/util'; export default class ControllerUtility { - public static postProcess(ctx: Context, status: number = 200) { + public static postProcess(ctx: Context, status = 200) { ctx.set('apiVersion', API_VERSION); ctx.status = status; } - public static deliveryPostProcess(ctx: Context, status: number = 200) { + public static deliveryPostProcess(ctx: Context, status = 200) { ctx.set('apiVersion', API_VERSION); ctx.status = isHttpStatusSuccess(status) ? 200 : status; } diff --git a/features.json b/src/features.json similarity index 100% rename from features.json rename to src/features.json diff --git a/src/helpers/fetchHandlers.ts b/src/helpers/fetchHandlers.ts index f3d68d919f78..96a74e528d92 100644 --- a/src/helpers/fetchHandlers.ts +++ b/src/helpers/fetchHandlers.ts @@ -2,7 +2,9 @@ import MiscService from '../services/misc'; export default class FetchHandler { private static sourceHandlerMap: Map = new Map(); + private static destHandlerMap: Map = new Map(); + private static deletionHandlerMap: Map = new Map(); public static getDestHandler(dest: string, version: string) { @@ -29,10 +31,10 @@ export default class FetchHandler { public static getDeletionHandler(dest: string, version: string) { let deletionHandler: any; - if(this.deletionHandlerMap.has(dest)) { + if (this.deletionHandlerMap.has(dest)) { deletionHandler = this.deletionHandlerMap.get(dest); } else { - deletionHandler = MiscService.getDeletionHandler(dest,version); + deletionHandler = MiscService.getDeletionHandler(dest, version); this.deletionHandlerMap.set(dest, deletionHandler); } return deletionHandler; diff --git a/src/index.ts b/src/index.ts index d996819d5b20..3f7ac5ba54cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,17 +1,18 @@ import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import gracefulShutdown from 'http-graceful-shutdown'; -import logger from './logger'; import dotenv from 'dotenv'; +import logger from './logger'; import cluster from './util/cluster'; import { router } from './versionedRouter'; -const { RedisDB } = require('./util/redisConnector'); import { testRouter } from './testRouter'; import { metricsRouter } from './routes/metricsRouter'; import { addStatMiddleware, addRequestSizeMiddleware } from './middleware'; import { logProcessInfo } from './util/utils'; import { applicationRoutes } from './routes'; +const { RedisDB } = require('./util/redisConnector'); + dotenv.config(); const clusterEnabled = process.env.CLUSTER_ENABLED !== 'false'; const useUpdatedRoutes = process.env.ENABLE_NEW_ROUTES !== 'false'; diff --git a/src/interfaces/DestinationService.ts b/src/interfaces/DestinationService.ts index abf7ca2f3f6b..b1cae047f8c0 100644 --- a/src/interfaces/DestinationService.ts +++ b/src/interfaces/DestinationService.ts @@ -11,8 +11,7 @@ import { } from '../types/index'; export default interface DestinationService { - - getName():string + getName(): string; init(): void; diff --git a/src/middlewares/routeActivation.ts b/src/middlewares/routeActivation.ts index 2c305a28bf31..bf457b2faa6d 100644 --- a/src/middlewares/routeActivation.ts +++ b/src/middlewares/routeActivation.ts @@ -13,7 +13,7 @@ const deliveryTestModeEnabled = const transformerTestModeEnabled = process.env.TRANSFORMER_TEST_MODE ? process.env.TRANSFORMER_TEST_MODE.toLowerCase() === 'true' : false; -const areFunctionsEnabled = process.env.ENABLE_FUNCTIONS === 'false' ? false : true; +const areFunctionsEnabled = process.env.ENABLE_FUNCTIONS !== 'false'; const destinationFilterList = process.env.DESTINATION_FILTER_LIST?.toLocaleLowerCase(); const sourceFilteList = process.env.SOURCE_FILTER_LIST?.toLocaleLowerCase(); const deliveryFilterList = process.env.DESTINATION_DELIVERY_FILTER_LIST?.toLocaleLowerCase(); @@ -22,11 +22,10 @@ export default class RouteActivationMiddleware { private static executeActivationRule(ctx: Context, next: Next, shouldActivate: boolean) { if (shouldActivate) { return next(); - } else { - ctx.status = 404; - ctx.body = 'RouteActivationMiddleware route is disabled'; - return ctx; } + ctx.status = 404; + ctx.body = 'RouteActivationMiddleware route is disabled'; + return ctx; } private static shouldActivateRoute(integration: string, filterList: string | undefined) { diff --git a/src/routes/misc.ts b/src/routes/misc.ts index db45e223c98d..12ee09b8a932 100644 --- a/src/routes/misc.ts +++ b/src/routes/misc.ts @@ -1,6 +1,7 @@ import Router from '@koa/router'; import ProfileController from '../controllers/profile'; import MiscController from '../controllers/misc'; + const router = new Router(); router.post('/heapdump', ProfileController.profile); diff --git a/src/services/comparator.ts b/src/services/comparator.ts index 6809708f02fa..ae6e1bcf5704 100644 --- a/src/services/comparator.ts +++ b/src/services/comparator.ts @@ -16,10 +16,12 @@ import tags from '../v0/util/tags'; import stats from '../util/stats'; import logger from '../logger'; import { CommonUtils } from '../util/common'; + const NS_PER_SEC = 1e9; export default class ComparatorService implements IntegrationDestinationService { secondaryService: IntegrationDestinationService; + primaryService: IntegrationDestinationService; constructor( @@ -79,8 +81,8 @@ export default class ComparatorService implements IntegrationDestinationService return; } - for (let index = 0; index < primaryResplist.length; index++) { - const objectDiff = CommonUtils.objectDiff(primaryResplist[index], secondaryResplist[index]); + for (const [index, element] of primaryResplist.entries()) { + const objectDiff = CommonUtils.objectDiff(element, secondaryResplist[index]); if (Object.keys(objectDiff).length > 0) { logger.error( `[LIVE_COMPARE_TEST] failed for destinationId=${destinationId}, destType=${destination}, feature=${feature}, diff_keys=${JSON.stringify( @@ -127,8 +129,8 @@ export default class ComparatorService implements IntegrationDestinationService } let hasComparisonFailed = false; - for (let index = 0; index < primaryResplist.length; index++) { - const objectDiff = CommonUtils.objectDiff(primaryResplist[index], secondaryResplist[index]); + for (const [index, element] of primaryResplist.entries()) { + const objectDiff = CommonUtils.objectDiff(element, secondaryResplist[index]); if (Object.keys(objectDiff).length > 0) { stats.counter('compare_test_failed_count', 1, { destinationId, diff --git a/src/services/delivertTest/deliveryTest.ts b/src/services/delivertTest/deliveryTest.ts index 2b38b5fd561a..051b67b5685c 100644 --- a/src/services/delivertTest/deliveryTest.ts +++ b/src/services/delivertTest/deliveryTest.ts @@ -32,7 +32,7 @@ export default class DeliveryTestService { routerDestReqPayload.data = routerDataVal; const proxyDataVal = new URLSearchParams(); - proxyDestReqPayload.data.forEach(function (value, key) { + proxyDestReqPayload.data.forEach((value, key) => { const encodeAsterisk = (x) => x.replace(/\*/g, '%2A'); // Router encodes `*` as well proxyDataVal.append(encodeAsterisk(key), encodeAsterisk(value)); diff --git a/src/services/destination/cdkV1Integration.ts b/src/services/destination/cdkV1Integration.ts index f25cebc35ead..7c300f28cb44 100644 --- a/src/services/destination/cdkV1Integration.ts +++ b/src/services/destination/cdkV1Integration.ts @@ -1,4 +1,5 @@ import { ConfigFactory, Executor } from 'rudder-transformer-cdk'; +import path from 'path'; import IntegrationDestinationService from '../../interfaces/DestinationService'; import { DeliveryResponse, @@ -15,7 +16,6 @@ import { import { TransformationError } from '../../v0/util/errorTypes'; import DestinationPostTransformationService from './postTransformation'; import tags from '../../v0/util/tags'; -import path from 'path'; export default class CDKV1DestinationService implements IntegrationDestinationService { public init() { @@ -59,7 +59,7 @@ export default class CDKV1DestinationService implements IntegrationDestinationSe const respList: ProcessorTransformationResponse[][] = await Promise.all( events.map(async (event) => { try { - let transformedPayloads: any = await Executor.execute(event as any, tfConfig); + const transformedPayloads: any = await Executor.execute(event as any, tfConfig); // We are not passing destinationHandler to post processor as we don't have post processing in CDK flows return DestinationPostTransformationService.handleProcessorTransformSucessEvents( event, diff --git a/src/services/destination/cdkV2Integration.ts b/src/services/destination/cdkV2Integration.ts index 5f03ba029e00..106603ea0d16 100644 --- a/src/services/destination/cdkV2Integration.ts +++ b/src/services/destination/cdkV2Integration.ts @@ -54,8 +54,13 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe const respList: ProcessorTransformationResponse[][] = await Promise.all( events.map(async (event) => { try { - let transformedPayloads: ProcessorTransformationOutput | ProcessorTransformationOutput[] = - await processCdkV2Workflow(destinationType, event, tags.FEATURES.PROCESSOR); + const transformedPayloads: + | ProcessorTransformationOutput + | ProcessorTransformationOutput[] = await processCdkV2Workflow( + destinationType, + event, + tags.FEATURES.PROCESSOR, + ); // We are not passing destination handler for CDK flows return DestinationPostTransformationService.handleProcessorTransformSucessEvents( event, @@ -110,9 +115,7 @@ export default class CDKV2DestinationService implements IntegrationDestinationSe metaTO, ); } catch (error: any) { - metaTO.metadatas = destInputArray.map((input) => { - return input.metadata; - }); + metaTO.metadatas = destInputArray.map((input) => input.metadata); const erroredResp = DestinationPostTransformationService.handleRouterTransformFailureEvents( error, diff --git a/src/services/destination/nativeIntegration.ts b/src/services/destination/nativeIntegration.ts index 9272c9d9a9a2..e1611084b673 100644 --- a/src/services/destination/nativeIntegration.ts +++ b/src/services/destination/nativeIntegration.ts @@ -54,8 +54,9 @@ export default class NativeIntegrationDestinationService implements IntegrationD const respList: ProcessorTransformationResponse[][] = await Promise.all( events.map(async (event) => { try { - let transformedPayloads: ProcessorTransformationOutput | ProcessorTransformationOutput[] = - await destHandler.process(event); + const transformedPayloads: + | ProcessorTransformationOutput + | ProcessorTransformationOutput[] = await destHandler.process(event); return DestinationPostTransformationService.handleProcessorTransformSucessEvents( event, transformedPayloads, @@ -110,9 +111,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD metaTO, ); } catch (error: any) { - metaTO.metadatas = destInputArray.map((input) => { - return input.metadata; - }); + metaTO.metadatas = destInputArray.map((input) => input.metadata); const errorResp = DestinationPostTransformationService.handleRouterTransformFailureEvents( error, metaTO, @@ -150,9 +149,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD destEvents[0].metadata.workspaceId, tags.FEATURES.BATCH, ); - metaTO.metadatas = events.map((event) => { - return event.metadata; - }); + metaTO.metadatas = events.map((event) => event.metadata); const errResp = DestinationPostTransformationService.handleBatchTransformFailureEvents( error, metaTO, diff --git a/src/services/destination/postTransformation.ts b/src/services/destination/postTransformation.ts index bafc1c9a4a6e..5d035785aa3d 100644 --- a/src/services/destination/postTransformation.ts +++ b/src/services/destination/postTransformation.ts @@ -64,7 +64,7 @@ export default class DestinationPostTransformationService { destHandler: any, metaTO: MetaTransferObject, ): RouterTransformationResponse[] { - let resultantPayloads: RouterTransformationResponse[] = cloneDeep(transformedPayloads); + const resultantPayloads: RouterTransformationResponse[] = cloneDeep(transformedPayloads); resultantPayloads.forEach((resultantPayload) => { if (resultantPayload.batchedRequest && resultantPayload.batchedRequest.userId) { resultantPayload.batchedRequest.userId = `${resultantPayload.batchedRequest.userId}`; @@ -142,7 +142,7 @@ export default class DestinationPostTransformationService { metaTO: MetaTransferObject, ): UserDeletionResponse { const errObj = generateErrorObject(error, metaTO.errorDetails); - //TODO: Add stat tags here + // TODO: Add stat tags here const resp = { statusCode: errObj.status, error: errObj.message, diff --git a/src/services/destination/preTransformation.ts b/src/services/destination/preTransformation.ts index 4ce29407d8eb..61ca20f7fe01 100644 --- a/src/services/destination/preTransformation.ts +++ b/src/services/destination/preTransformation.ts @@ -8,10 +8,12 @@ export default class PreTransformationDestinationService { ctx: Context, ) { const reqParams = ctx.request.query; - events = events.map((event: ProcessorTransformationRequest | RouterTransformationRequestData) => { - event.request = { query: reqParams }; - return event; - }); + events = events.map( + (event: ProcessorTransformationRequest | RouterTransformationRequestData) => { + event.request = { query: reqParams }; + return event; + }, + ); return events; } } diff --git a/src/services/misc.ts b/src/services/misc.ts index 33154e1e684d..3274c745f0a5 100644 --- a/src/services/misc.ts +++ b/src/services/misc.ts @@ -56,7 +56,7 @@ export default class MiscService { } public static getFetaures() { - const obj = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../features.json'), 'utf8')); + const obj = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../features.json'), 'utf8')); return JSON.stringify(obj); } } diff --git a/src/services/profile.ts b/src/services/profile.ts index 069ec13e7cf5..e4c6bbe18038 100644 --- a/src/services/profile.ts +++ b/src/services/profile.ts @@ -105,16 +105,14 @@ export default class ProfileService { } logger.info('After pipeline'); } else if (credBucketDetails.sendTo) { - switch (credBucketDetails.sendTo) { - case 'aws': - data = await this.uploadToAWS(credBucketDetails, fileName, snapshotReadableStream); - break; - default: - throw new Error( - `un-supported cloud provider, only these are supported currently(${supportedCloudProvidersForDumpStorage.join( - ', ', - )}) `, - ); + if (credBucketDetails.sendTo === 'aws') { + data = await this.uploadToAWS(credBucketDetails, fileName, snapshotReadableStream); + } else { + throw new Error( + `un-supported cloud provider, only these are supported currently(${supportedCloudProvidersForDumpStorage.join( + ', ', + )}) `, + ); } } // snapshotReadableStream.destroy(); diff --git a/src/services/source/nativeIntegration.ts b/src/services/source/nativeIntegration.ts index 20cbee608ea9..e654940feceb 100644 --- a/src/services/source/nativeIntegration.ts +++ b/src/services/source/nativeIntegration.ts @@ -23,6 +23,7 @@ export default class NativeIntegrationSourceService implements IntegrationSource } as MetaTransferObject; return metaTO; } + public async sourceTransformRoutine( sourceEvents: Object[], sourceType: string, diff --git a/src/services/source/postTransformation.ts b/src/services/source/postTransformation.ts index 1ec4ddce237d..603f1b1c0a95 100644 --- a/src/services/source/postTransformation.ts +++ b/src/services/source/postTransformation.ts @@ -25,10 +25,10 @@ export default class PostTransformationSourceService { // We will not return array for events not meant for gateway if (Object.prototype.hasOwnProperty.call(events, 'outputToSource')) { return events as SourceTransformationResponse; - } else if (Array.isArray(events)) { + } + if (Array.isArray(events)) { return { output: { batch: events } } as SourceTransformationResponse; - } else { - return { output: { batch: [events] } } as SourceTransformationResponse; } + return { output: { batch: [events] } } as SourceTransformationResponse; } } diff --git a/src/services/userTransform.ts b/src/services/userTransform.ts index 69f7e7c53cc4..3de8c995fcc7 100644 --- a/src/services/userTransform.ts +++ b/src/services/userTransform.ts @@ -27,8 +27,8 @@ export default class UserTransformService { stats.counter('user_transform_function_group_size', Object.entries(groupedEvents).length, {}); stats.counter('user_transform_input_events', events.length, {}); - const transformedEvents:any[] = []; - let librariesVersionIDs:any[] = []; + const transformedEvents: any[] = []; + let librariesVersionIDs: any[] = []; if (events[0].libraries) { librariesVersionIDs = events[0].libraries.map( (library: UserTransformationLibrary) => library.VersionID, @@ -40,9 +40,7 @@ export default class UserTransformService { const eventsToProcess = destEvents as ProcessorTransformationRequest[]; const transformationVersionId = eventsToProcess[0]?.destination?.Transformations[0]?.VersionID; - const messageIds = eventsToProcess.map((ev) => { - return ev.metadata?.messageId; - }); + const messageIds = eventsToProcess.map((ev) => ev.metadata?.messageId); const commonMetadata = { sourceId: eventsToProcess[0]?.metadata?.sourceId, @@ -52,7 +50,7 @@ export default class UserTransformService { }; const metaTags = - eventsToProcess.length && eventsToProcess[0].metadata + eventsToProcess.length > 0 && eventsToProcess[0].metadata ? getMetadata(eventsToProcess[0].metadata) : {}; @@ -66,14 +64,16 @@ export default class UserTransformService { } as ProcessorTransformationResponse); stats.counter('user_transform_errors', eventsToProcess.length, { transformationVersionId, - type: "NoVersionId", + type: 'NoVersionId', ...metaTags, }); return transformedEvents; } const userFuncStartTime = new Date(); try { - stats.counter('user_transform_function_input_events', eventsToProcess.length, { ...metaTags }); + stats.counter('user_transform_function_input_events', eventsToProcess.length, { + ...metaTags, + }); const destTransformedEvents: UserTransformationResponse[] = await userTransformHandler()( eventsToProcess, transformationVersionId, @@ -116,17 +116,18 @@ export default class UserTransformService { status = error.statusCode; } transformedEvents.push( - ...eventsToProcess.map((e) => { - return { - statusCode: status, - metadata: e.metadata, - error: errorString, - } as ProcessorTransformationResponse; - }), + ...eventsToProcess.map( + (e) => + ({ + statusCode: status, + metadata: e.metadata, + error: errorString, + } as ProcessorTransformationResponse), + ), ); stats.counter('user_transform_errors', eventsToProcess.length, { transformationVersionId, - type: "UnknownError", + type: 'UnknownError', status, ...metaTags, }); @@ -140,7 +141,7 @@ export default class UserTransformService { stats.counter('user_transform_requests', 1, {}); stats.counter('user_transform_output_events', transformedEvents.length, {}); return transformedEvents; - }) + }), ); const flattenedResponses: ProcessorTransformationResponse[] = responses.flat(); @@ -151,7 +152,7 @@ export default class UserTransformService { } public static async testTransformRoutine(events, trRevCode, libraryVersionIDs) { - let response: any = {}; + const response: any = {}; try { if (!trRevCode || !trRevCode.code || !trRevCode.codeVersion) { throw new Error('Invalid Request. Missing parameters in transformation code block'); diff --git a/src/testRouter.js b/src/testRouter.js index 42e4836d858d..5c9d56e78d58 100644 --- a/src/testRouter.js +++ b/src/testRouter.js @@ -6,13 +6,14 @@ const fs = require('fs'); const path = require('path'); const Router = require('@koa/router'); const { sendToDestination, userTransformHandler } = require('./routerUtils'); +const { JSON_MIME_TYPE } = require('./v0/util/constant'); const version = 'v0'; const API_VERSION = '1'; const isSupportedContentType = (contentType) => { let supported = false; - const SUPPORTED_CONTENT_TYPES = ['application/xml', 'application/json', 'text']; + const SUPPORTED_CONTENT_TYPES = ['application/xml', JSON_MIME_TYPE, 'text']; if (contentType) { SUPPORTED_CONTENT_TYPES.some((type) => { if (contentType.toLowerCase().includes(type)) { @@ -50,6 +51,129 @@ const transformDestination = (dest) => { return transformedObj; }; +const processUserTransform = async (events, ev, libraries) => { + let librariesVersionIDs = []; + if (libraries) { + librariesVersionIDs = events[0].libraries.map((library) => library.versionId); + } + const transformationVersionId = + ev.destination && + ev.destination.Transformations && + ev.destination.Transformations[0] && + ev.destination.Transformations[0].versionId; + + let errorFound = false; + let transformedPayload; + let updatedMessage; + + if (transformationVersionId) { + try { + const destTransformedEvents = await userTransformHandler()( + [ev], + transformationVersionId, + librariesVersionIDs, + ); + const userTransformedEvent = destTransformedEvents[0]; + if (userTransformedEvent.error) { + throw new Error(userTransformedEvent.error); + } + + transformedPayload = userTransformedEvent.transformedEvent; + updatedMessage = userTransformedEvent.transformedEvent; + } catch (err) { + errorFound = true; + transformedPayload = { + error: err.message || JSON.stringify(err), + }; + } + } else { + transformedPayload = { + error: 'Transformation VersionID not found', + }; + } + return { transformedPayload, errorFound, updatedMessage }; +}; + +const processDestTransform = async (ev, utErrFound, dest) => { + let transformedPayload; + let errorFound = utErrFound; + if (!utErrFound) { + try { + const desthandler = getDestHandler(version, dest); + const transformedOutput = await desthandler.process(ev); + if (Array.isArray(transformedOutput)) { + transformedPayload = transformedOutput; + } else { + transformedPayload = [transformedOutput]; + } + } catch (err) { + errorFound = true; + transformedPayload = { + error: err.message || JSON.stringify(err), + }; + } + } else { + transformedPayload = { + error: 'error encountered in user_transformation stage. Aborting.', + }; + } + return { transformedPayload, errorFound }; +}; + +const sendEventToDestination = async (curResponse, dest, errorFound) => { + let response = curResponse; + // send event to destination only after transformation + if (!errorFound) { + const destResponses = []; + const destResponseStatuses = []; + + const transformedPayloads = curResponse.dest_transformed_payload; + // eslint-disable-next-line no-restricted-syntax + for (const payload of transformedPayloads) { + // eslint-disable-next-line no-await-in-loop + const parsedResponse = await sendToDestination(dest, payload); + + let contentType = ''; + let destResp = ''; + if (parsedResponse.headers) { + contentType = parsedResponse.headers['content-type']; + if (isSupportedContentType(contentType)) { + destResp = parsedResponse.response; + } + } else if (parsedResponse.networkFailure) { + destResp = parsedResponse.response; + } + + destResponses.push(destResp); + destResponseStatuses.push(parsedResponse.status); + + // TODO: Use updated handleResponseTransform function + // Removing the below part, because transformerStatus is not + // currently being returned by test api response + + // call response transform here + // const ctxMock = { + // request: { + // body: parsedResponse + // } + // }; + // handleResponseTransform(version, dest, ctxMock); + // const { output } = ctxMock.body; + // transformerStatuses.push(output.status); + } + response = { + ...curResponse, + destination_response: destResponses, + destination_response_status: destResponseStatuses, + }; + } else { + response.destination_response = { + error: 'error encountered in dest_transformation stage. Aborting.', + }; + } + return response; +}; + const handleTestEvent = async (ctx, dest) => { try { const { events } = ctx.request.body; @@ -71,117 +195,23 @@ const handleTestEvent = async (ctx, dest) => { let errorFound = false; if (stage.user_transform) { - let librariesVersionIDs = []; - if (libraries) { - librariesVersionIDs = events[0].libraries.map((library) => library.versionId); - } - const transformationVersionId = - ev.destination && - ev.destination.Transformations && - ev.destination.Transformations[0] && - ev.destination.Transformations[0].versionId; - - if (transformationVersionId) { - try { - const destTransformedEvents = await userTransformHandler()( - [ev], - transformationVersionId, - librariesVersionIDs, - ); - const userTransformedEvent = destTransformedEvents[0]; - if (userTransformedEvent.error) { - throw new Error(userTransformedEvent.error); - } - - response.user_transformed_payload = userTransformedEvent.transformedEvent; - ev.message = userTransformedEvent.transformedEvent; - } catch (err) { - errorFound = true; - response.user_transformed_payload = { - error: err.message || JSON.stringify(err), - }; - } - } else { - response.user_transformed_payload = { - error: 'Transformation VersionID not found', - }; - } + const utOutput = await processUserTransform(events, ev, libraries); + errorFound = utOutput.errorFound; + response.user_transformed_payload = utOutput.transformedPayload; + if (utOutput.updatedMessage) ev.message = utOutput.updatedMessage; } if (stage.dest_transform) { - if (!errorFound) { - try { - const desthandler = getDestHandler(version, dest); - const transformedOutput = await desthandler.process(ev); - if (Array.isArray(transformedOutput)) { - response.dest_transformed_payload = transformedOutput; - } else { - response.dest_transformed_payload = [transformedOutput]; - } - } catch (err) { - errorFound = true; - response.dest_transformed_payload = { - error: err.message || JSON.stringify(err), - }; - } - } else { - response.dest_transformed_payload = { - error: 'error encountered in user_transformation stage. Aborting.', - }; - } + const dtOutput = await processDestTransform(ev, errorFound, dest); + response.dest_transformed_payload = dtOutput.transformedPayload; + errorFound = dtOutput.errorFound; } + // const transformerStatuses = []; if (stage.dest_transform && stage.send_to_destination) { - // send event to destination only after transformation - if (!errorFound) { - const destResponses = []; - const destResponseStatuses = []; - - const transformedPayloads = response.dest_transformed_payload; - // eslint-disable-next-line no-restricted-syntax - for (const payload of transformedPayloads) { - // eslint-disable-next-line no-await-in-loop - const parsedResponse = await sendToDestination(dest, payload); - - let contentType = ''; - let response = ''; - if (parsedResponse.headers) { - contentType = parsedResponse.headers['content-type']; - if (isSupportedContentType(contentType)) { - response = parsedResponse.response; - } - } else if (parsedResponse.networkFailure) { - response = parsedResponse.response; - } - - destResponses.push(response); - destResponseStatuses.push(parsedResponse.status); - - // TODO: Use updated handleResponseTransform function - // Removing the below part, because transformerStatus is not - // currently being returned by test api response - - // call response transform here - // const ctxMock = { - // request: { - // body: parsedResponse - // } - // }; - // handleResponseTransform(version, dest, ctxMock); - // const { output } = ctxMock.body; - // transformerStatuses.push(output.status); - } - response = { - ...response, - destination_response: destResponses, - destination_response_status: destResponseStatuses, - }; - } else { - response.destination_response = { - error: 'error encountered in dest_transformation stage. Aborting.', - }; - } + response = await sendEventToDestination(response, dest, errorFound); } + respList.push(response); }), ); diff --git a/src/types/index.ts b/src/types/index.ts index 9bbce6c790ed..543dc040ab86 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -236,5 +236,5 @@ export { UserDeletionRequest, UserDeletionResponse, Destination, - ComparatorInput + ComparatorInput, }; diff --git a/src/util/customTransformer-v1.js b/src/util/customTransformer-v1.js index fced5b0a21ba..fac33ebd2a57 100644 --- a/src/util/customTransformer-v1.js +++ b/src/util/customTransformer-v1.js @@ -81,7 +81,7 @@ async function userTransformHandlerV1( stats.counter('events_to_process', events.length, tags); const isolateStartWallTime = calculateMsFromIvmTime(isolatevm.isolateStartWallTime); const isolateStartCPUTime = calculateMsFromIvmTime(isolatevm.isolateStartCPUTime); - + const invokeTime = new Date(); let transformedEvents; // Destroy isolatevm in case of execution errors diff --git a/src/util/customTransformer.js b/src/util/customTransformer.js index c98aee131cec..9cd5e9f72027 100644 --- a/src/util/customTransformer.js +++ b/src/util/customTransformer.js @@ -9,7 +9,14 @@ const stats = require('./stats'); const ISOLATE_VM_MEMORY = parseInt(process.env.ISOLATE_VM_MEMORY || '128', 10); -async function runUserTransform(events, code, secrets, eventsMetadata, versionId, testMode = false) { +async function runUserTransform( + events, + code, + secrets, + eventsMetadata, + versionId, + testMode = false, +) { const tags = { transformerVersionId: versionId, identifier: 'v0', diff --git a/src/util/dynamicConfigParser.ts b/src/util/dynamicConfigParser.ts index 64ecf685de4f..fc4a02bc8463 100644 --- a/src/util/dynamicConfigParser.ts +++ b/src/util/dynamicConfigParser.ts @@ -14,7 +14,7 @@ export class DynamicConfigParser { // " {{message.traits.key || \"email\" }} " // " {{ message.traits.key || 1233 }} " const defFormat = - /^\s*\{\{\s*(?[a-zA-Z_]([a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*)+)+\s*\|\|\s*(?.*)\s*\}\}\s*$/; + /^\s*{{\s*(?[A-Z_a-z](\w*\.[A-Z_a-z]\w*)+)+\s*\|\|\s*(?.*)\s*}}\s*$/; const matResult = value.match(defFormat); if (matResult) { // Support "event.." alias for "message.." @@ -57,7 +57,9 @@ export class DynamicConfigParser { return value; } - private static getDynamicConfig(event: ProcessorTransformationRequest | RouterTransformationRequestData) { + private static getDynamicConfig( + event: ProcessorTransformationRequest | RouterTransformationRequestData, + ) { const resultantEvent = cloneDeep(event); const { Config } = event.destination; resultantEvent.destination.Config = this.configureVal(Config, event); @@ -67,9 +69,10 @@ export class DynamicConfigParser { public static process( events: ProcessorTransformationRequest[] | RouterTransformationRequestData[], ) { - const eventRespArr = events.map((e: ProcessorTransformationRequest | RouterTransformationRequestData) => { - return this.getDynamicConfig(e); - }); + const eventRespArr = events.map( + (e: ProcessorTransformationRequest | RouterTransformationRequestData) => + this.getDynamicConfig(e), + ); return eventRespArr; } } diff --git a/src/util/errorNotifier/bugsnag.js b/src/util/errorNotifier/bugsnag.js index 7b2c3d7d97f1..09b2cd9f7188 100644 --- a/src/util/errorNotifier/bugsnag.js +++ b/src/util/errorNotifier/bugsnag.js @@ -25,7 +25,11 @@ const { NetworkInstrumentationError, } = require('../../v0/util/errorTypes'); -const { BUGSNAG_API_KEY: apiKey, transformer_build_version: imageVersion, git_commit_sha: gitCommitSHA } = process.env; +const { + BUGSNAG_API_KEY: apiKey, + transformer_build_version: imageVersion, + git_commit_sha: gitCommitSHA, +} = process.env; const errorTypesDenyList = [ BaseError, @@ -63,8 +67,8 @@ function init() { version: imageVersion, }, source: { - gitCommitSHA - } + gitCommitSHA, + }, }, onError(event) { event.severity = 'error'; diff --git a/src/util/errorNotifier/index.js b/src/util/errorNotifier/index.js index f7a14aa2c35d..2cd3ecaa368a 100644 --- a/src/util/errorNotifier/index.js +++ b/src/util/errorNotifier/index.js @@ -4,15 +4,8 @@ const client = require('./client'); const { ERROR_NOTIFIER } = process.env; -let notifier; -switch (ERROR_NOTIFIER) { - case 'Bugsnag': - notifier = Bugsnag; - break; - default: - notifier = defaultNotifier; - break; -} +const notifier = ERROR_NOTIFIER === 'Bugsnag' ? Bugsnag : defaultNotifier; + client.setNotifier(notifier); // Initialize the notifier client diff --git a/src/util/eventValidation.js b/src/util/eventValidation.js index f933aa01ba2a..ec5f72bc2be1 100644 --- a/src/util/eventValidation.js +++ b/src/util/eventValidation.js @@ -3,7 +3,7 @@ const Ajv2019 = require('ajv/dist/2019'); const Ajv = require('ajv-draft-04'); const draft7MetaSchema = require('ajv/dist/refs/json-schema-draft-07.json'); const draft6MetaSchema = require('ajv/dist/refs/json-schema-draft-06.json'); -const addFormats = require("ajv-formats"); +const addFormats = require('ajv-formats'); const NodeCache = require('node-cache'); const hash = require('object-hash'); @@ -244,6 +244,72 @@ async function validate(event) { } } +function handleValidationErrors(validationErrors, mergedTpConfig, curDropEvent, curViolationType) { + let dropEvent = curDropEvent; + let violationType = curViolationType; + const violationsByType = new Set(validationErrors.map((err) => err.type)); + // eslint-disable-next-line no-restricted-syntax + for (const [key, val] of Object.entries(mergedTpConfig)) { + // To have compatibility for config-backend, spread-sheet plugin and postman collection + // We are making everything to lower string and doing string comparison. + const value = val?.toString()?.toLowerCase(); + // eslint-disable-next-line default-case + switch (key) { + case 'allowUnplannedEvents': { + const exists = violationsByType.has(violationTypes.UnplannedEvent); + if (value === 'false' && exists) { + dropEvent = true; + violationType = violationTypes.UnplannedEvent; + break; + } + if (!(value === 'true' || value === 'false')) { + logger.error(`Unknown option ${value} in ${key}"`); + } + break; + } + case 'unplannedProperties': { + const exists = violationsByType.has(violationTypes.AdditionalProperties); + if (value === 'drop' && exists) { + dropEvent = true; + violationType = violationTypes.AdditionalProperties; + break; + } + if (!(value === 'forward' || value === 'drop')) { + logger.error(`Unknown option ${value} in ${key}"`); + } + break; + } + case 'anyOtherViolation': { + const exists1 = violationsByType.has(violationTypes.UnknownViolation); + const exists2 = violationsByType.has(violationTypes.DatatypeMismatch); + const exists3 = violationsByType.has(violationTypes.RequiredMissing); + if (value === 'drop' && (exists1 || exists2 || exists3)) { + if (exists1) { + violationType = violationTypes.UnknownViolation; + } else if (exists2) { + violationType = violationTypes.DatatypeMismatch; + } else { + violationType = violationTypes.RequiredMissing; + } + dropEvent = true; + break; + } + if (!(value === 'forward' || value === 'drop')) { + logger.error(`Unknown option ${value} in ${key}"`); + } + break; + } + case 'sendViolatedEventsTo': { + if (value !== 'procerrors') { + logger.error(`Unknown option ${value} in ${key}"`); + } + break; + } + } + } + return { dropEvent, violationType }; +} + /** * @param {*} event * @returns {dropEvent, violationType, validationErrors} @@ -283,66 +349,12 @@ async function handleValidation(event) { }; } - const violationsByType = new Set(validationErrors.map((err) => err.type)); - // eslint-disable-next-line no-restricted-syntax - for (const [key, val] of Object.entries(mergedTpConfig)) { - // To have compatibility for config-backend, spread-sheet plugin and postman collection - // We are making everything to lower string and doing string comparision. - const value = val?.toString()?.toLowerCase(); - // eslint-disable-next-line default-case - switch (key) { - case 'allowUnplannedEvents': { - const exists = violationsByType.has(violationTypes.UnplannedEvent); - if (value === 'false' && exists) { - dropEvent = true; - violationType = violationTypes.UnplannedEvent; - break; - } - if (!(value === 'true' || value === 'false')) { - logger.error(`Unknown option ${value} in ${key}"`); - } - break; - } - case 'unplannedProperties': { - const exists = violationsByType.has(violationTypes.AdditionalProperties); - if (value === 'drop' && exists) { - dropEvent = true; - violationType = violationTypes.AdditionalProperties; - break; - } - if (!(value === 'forward' || value === 'drop')) { - logger.error(`Unknown option ${value} in ${key}"`); - } - break; - } - case 'anyOtherViolation': { - const exists1 = violationsByType.has(violationTypes.UnknownViolation); - const exists2 = violationsByType.has(violationTypes.DatatypeMismatch); - const exists3 = violationsByType.has(violationTypes.RequiredMissing); - if (value === 'drop' && (exists1 || exists2 || exists3)) { - if (exists1) { - violationType = violationTypes.UnknownViolation; - } else if (exists2) { - violationType = violationTypes.DatatypeMismatch; - } else { - violationType = violationTypes.RequiredMissing; - } - dropEvent = true; - break; - } - if (!(value === 'forward' || value === 'drop')) { - logger.error(`Unknown option ${value} in ${key}"`); - } - break; - } - case 'sendViolatedEventsTo': { - if (value !== 'procerrors') { - logger.error(`Unknown option ${value} in ${key}"`); - } - break; - } - } - } + ({ dropEvent, violationType } = handleValidationErrors( + validationErrors, + mergedTpConfig, + dropEvent, + violationType, + )); return { dropEvent, diff --git a/src/util/openfaas/faasApi.js b/src/util/openfaas/faasApi.js index c7e4fe20e0c1..4db5e2a81c86 100644 --- a/src/util/openfaas/faasApi.js +++ b/src/util/openfaas/faasApi.js @@ -7,7 +7,8 @@ const parseAxiosError = (error) => { if (error.response) { const status = error.response.status || 400; const errorData = error.response?.data; - const message = (errorData && (errorData.message || errorData.error || errorData)) || error.message; + const message = + (errorData && (errorData.message || errorData.error || errorData)) || error.message; return new RespStatusError(message, status); } if (error.request) { @@ -57,7 +58,7 @@ const checkFunctionHealth = async (functionName) => const url = `${OPENFAAS_GATEWAY_URL}/function/${functionName}`; axios .get(url, { - headers: { "X-REQUEST-TYPE": "HEALTH-CHECK"} + headers: { 'X-REQUEST-TYPE': 'HEALTH-CHECK' }, }) .then((resp) => resolve(resp)) .catch((err) => reject(parseAxiosError(err))); @@ -78,5 +79,5 @@ module.exports = { getFunction, getFunctionList, invokeFunction, - checkFunctionHealth + checkFunctionHealth, }; diff --git a/src/util/openfaas/index.js b/src/util/openfaas/index.js index 0078156486d0..f27fb811866e 100644 --- a/src/util/openfaas/index.js +++ b/src/util/openfaas/index.js @@ -1,5 +1,11 @@ const NodeCache = require('node-cache'); -const { getFunction, deleteFunction, deployFunction, invokeFunction, checkFunctionHealth } = require('./faasApi'); +const { + getFunction, + deleteFunction, + deployFunction, + invokeFunction, + checkFunctionHealth, +} = require('./faasApi'); const logger = require('../../logger'); const { RetryRequestError, RespStatusError } = require('../utils'); @@ -13,8 +19,8 @@ const FAAS_MAX_INFLIGHT = process.env.FAAS_MAX_INFLIGHT || '4'; const FAAS_EXEC_TIMEOUT = process.env.FAAS_EXEC_TIMEOUT || '4s'; const FAAS_ENABLE_WATCHDOG_ENV_VARS = process.env.FAAS_ENABLE_WATCHDOG_ENV_VARS || 'true'; const CONFIG_BACKEND_URL = process.env.CONFIG_BACKEND_URL || 'https://api.rudderlabs.com'; -const FAAS_AST_VID = "ast"; -const FAAS_AST_FN_NAME = "fn-ast"; +const FAAS_AST_VID = 'ast'; +const FAAS_AST_FN_NAME = 'fn-ast'; // Initialise node cache const functionListCache = new NodeCache(); @@ -26,7 +32,13 @@ const DEFAULT_RETRY_THRESHOLD = 2; const delayInMs = async (ms = 2000) => new Promise((resolve) => setTimeout(resolve, ms)); -const callWithRetry = async (fn, count = 0, delay = DEFAULT_RETRY_DELAY_MS, retryThreshold = DEFAULT_RETRY_THRESHOLD, ...args) => { +const callWithRetry = async ( + fn, + count = 0, + delay = DEFAULT_RETRY_DELAY_MS, + retryThreshold = DEFAULT_RETRY_THRESHOLD, + ...args +) => { try { return await fn(...args); } catch (err) { @@ -38,15 +50,19 @@ const callWithRetry = async (fn, count = 0, delay = DEFAULT_RETRY_DELAY_MS, retr } }; -const awaitFunctionReadiness = async (functionName, maxWaitInMs = 22000, waitBetweenIntervalsInMs = 250) => { +const awaitFunctionReadiness = async ( + functionName, + maxWaitInMs = 22000, + waitBetweenIntervalsInMs = 250, +) => { const executionPromise = new Promise(async (resolve) => { try { await callWithRetry( checkFunctionHealth, 0, waitBetweenIntervalsInMs, - Math.floor(maxWaitInMs/waitBetweenIntervalsInMs), - functionName + Math.floor(maxWaitInMs / waitBetweenIntervalsInMs), + functionName, ); resolve(true); @@ -63,9 +79,10 @@ const awaitFunctionReadiness = async (functionName, maxWaitInMs = 22000, waitBet }, maxWaitInMs); }); - return Promise.race([executionPromise, timeoutPromise]) - .finally(() => clearTimeout(setTimeoutHandle)); -} + return Promise.race([executionPromise, timeoutPromise]).finally(() => + clearTimeout(setTimeoutHandle), + ); +}; const isFunctionDeployed = (functionName) => { const funcList = functionListCache.get(FUNC_LIST_KEY) || []; @@ -87,7 +104,7 @@ const deployFaasFunction = async (functionName, code, versionId, libraryVersionI logger.debug('[Faas] Deploying a faas function'); let envProcess = 'python index.py'; - const lvidsString = libraryVersionIDs.join(","); + const lvidsString = libraryVersionIDs.join(','); if (!testMode) { envProcess = `${envProcess} --vid ${versionId} --config-backend-url ${CONFIG_BACKEND_URL} --lvids "${lvidsString}"`; @@ -159,7 +176,13 @@ async function setupFaasFunction(functionName, code, versionId, libraryVersionID } } -const executeFaasFunction = async (functionName, events, versionId, libraryVersionIDs, testMode) => { +const executeFaasFunction = async ( + functionName, + events, + versionId, + libraryVersionIDs, + testMode, +) => { try { logger.debug('[Faas] Invoking faas function'); @@ -206,5 +229,5 @@ module.exports = { setupFaasFunction, invalidateFnCache, FAAS_AST_VID, - FAAS_AST_FN_NAME + FAAS_AST_FN_NAME, }; diff --git a/src/util/parser.js b/src/util/parser.js index 77b8f4d470f5..19ab331db764 100644 --- a/src/util/parser.js +++ b/src/util/parser.js @@ -1,18 +1,6 @@ const parseStaticImports = require('parse-static-imports'); const { executeFaasFunction, FAAS_AST_VID, FAAS_AST_FN_NAME } = require('./openfaas'); -async function parserForImport(code, validateImports=false, additionalLibraries=[], language="javascript") { - switch(language) { - case "javascript": - return parserForJSImports(code); - case "python": - case "pythonfaas": - return parserForPythonImports(code, validateImports, additionalLibraries); - default: - throw new Error(`Unsupported language ${language}`); - } -} - function parserForJSImports(code) { const obj = {}; const modules = parseStaticImports(code); @@ -34,25 +22,21 @@ function parserForJSImports(code) { return obj; } -async function parserForPythonImports(code, validateImports=true, additionalLibraries=[]) { +async function parserForPythonImports(code, validateImports = true, additionalLibraries = []) { const obj = {}; - const payload = [{ - message: { - messageId: "1", - code, - validateImports, - additionalLibraries - } - }]; + const payload = [ + { + message: { + messageId: '1', + code, + validateImports, + additionalLibraries, + }, + }, + ]; - const result = await executeFaasFunction( - FAAS_AST_FN_NAME, - payload, - FAAS_AST_VID, - [], - false - ); + const result = await executeFaasFunction(FAAS_AST_FN_NAME, payload, FAAS_AST_VID, [], false); const errMsg = result.transformedEvents[0].error; @@ -60,8 +44,27 @@ async function parserForPythonImports(code, validateImports=true, additionalLibr throw new Error(errMsg); } - result.transformedEvents[0].transformedEvent.modules.forEach((mod) => obj[mod.name] = []); + result.transformedEvents[0].transformedEvent.modules.forEach((mod) => { + obj[mod.name] = []; + }); return obj; } +async function parserForImport( + code, + validateImports = false, + additionalLibraries = [], + language = 'javascript', +) { + switch (language) { + case 'javascript': + return parserForJSImports(code); + case 'python': + case 'pythonfaas': + return parserForPythonImports(code, validateImports, additionalLibraries); + default: + throw new Error(`Unsupported language ${language}`); + } +} + exports.parserForImport = parserForImport; diff --git a/src/util/redisConnector.js b/src/util/redisConnector.js index ac7e871d92ea..180d750854af 100644 --- a/src/util/redisConnector.js +++ b/src/util/redisConnector.js @@ -3,11 +3,8 @@ const { RedisError } = require('../v0/util/errorTypes'); const log = require('../logger'); const stats = require('./stats'); -const timeoutPromise = new Promise((resolve, reject) => { - setTimeout( - () => resolve(), - 50 - ); +const timeoutPromise = new Promise((resolve) => { + setTimeout(() => resolve(), 50); }); const RedisDB = { @@ -47,9 +44,8 @@ const RedisDB = { async checkAndConnectConnection() { if (!this.client) { this.init(); - } - else if (this.client.status !== 'ready') { - await Promise.race([this.client.connect(), timeoutPromise]) + } else if (this.client.status !== 'ready') { + await Promise.race([this.client.connect(), timeoutPromise]); } }, /** @@ -64,16 +60,16 @@ const RedisDB = { await this.checkAndConnectConnection(); // check if redis is connected and if not, connect const value = await this.client.get(key); if (value) { - const bytes = Buffer.byteLength(value, "utf-8"); + const bytes = Buffer.byteLength(value, 'utf-8'); stats.gauge('redis_get_val_size', bytes, { - timestamp: Date.now() + timestamp: Date.now(), }); } return isJsonExpected ? JSON.parse(value) : value; } catch (e) { stats.increment('redis_get_val_error', { error: e, - timestamp: Date.now() + timestamp: Date.now(), }); throw new RedisError(`Error getting value from Redis: ${e}`); } @@ -90,15 +86,15 @@ const RedisDB = { try { await this.checkAndConnectConnection(); // check if redis is connected and if not, connect const valueToStore = isValJson ? JSON.stringify(value) : value; - const bytes = Buffer.byteLength(valueToStore, "utf-8"); + const bytes = Buffer.byteLength(valueToStore, 'utf-8'); await this.client.setex(key, dataExpiry, valueToStore); stats.gauge('redis_set_val_size', bytes, { - timestamp: Date.now() + timestamp: Date.now(), }); } catch (e) { stats.increment('redis_set_val_error', { error: e, - timestamp: Date.now() + timestamp: Date.now(), }); throw new RedisError(`Error setting value in Redis due ${e}`); } @@ -110,7 +106,7 @@ const RedisDB = { }); this.client.quit(); } - } + }, }; module.exports = { RedisDB }; diff --git a/src/v0/destinations/active_campaign/config.js b/src/v0/destinations/active_campaign/config.js index c17278a6bdc4..69c41f331f17 100644 --- a/src/v0/destinations/active_campaign/config.js +++ b/src/v0/destinations/active_campaign/config.js @@ -47,9 +47,27 @@ const CONFIG_CATEGORIES = { }, }; +/** + * + * @param {*} destination + * @returns the header block of structure: + * { + 'Content-Type': 'application/json', + 'Api-Token': destination.Config.apiKey, + } + */ +const getHeader = (destination) => { + const headers = { + 'Content-Type': 'application/json', + 'Api-Token': destination.Config.apiKey, + }; + return headers; +}; + const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname); module.exports = { CONFIG_CATEGORIES, MAPPING_CONFIG, + getHeader, }; diff --git a/src/v0/destinations/active_campaign/transform.js b/src/v0/destinations/active_campaign/transform.js index 1d70d56e5c9e..03e6b48bdb04 100644 --- a/src/v0/destinations/active_campaign/transform.js +++ b/src/v0/destinations/active_campaign/transform.js @@ -2,7 +2,7 @@ /* eslint-disable no-empty */ const get = require('get-value'); const { EventType } = require('../../../constants'); -const { CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); +const { CONFIG_CATEGORIES, MAPPING_CONFIG, getHeader } = require('./config'); const { defaultRequestConfig, constructPayload, @@ -20,6 +20,9 @@ const { 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'; + // The Final data is both application/url-encoded FORM and POST JSON depending on type of event // Creating a switch case for final request building const responseBuilderSimple = (payload, category, destination) => { @@ -30,10 +33,7 @@ const responseBuilderSimple = (payload, category, destination) => { case 'ACPage': response.endpoint = `${destination.Config.apiUrl}${category.endPoint}`; response.method = defaultPostRequestConfig.requestMethod; - response.headers = { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }; + response.headers = getHeader(destination); response.body.JSON = payload; break; case 'ACScreen': @@ -61,10 +61,7 @@ const syncContact = async (contactPayload, category, destination) => { contact: contactPayload, }; const requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; const res = await httpPOST(endpoint, requestData, requestOptions); if (res.success === false) { @@ -104,10 +101,7 @@ const customTagProcessor = async (message, category, destination, contactId) => // Ref - https://developers.activecampaign.com/reference/retrieve-all-tags endpoint = `${destination.Config.apiUrl}${`${category.tagEndPoint}?limit=100`}`; requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = await httpGET(endpoint, requestOptions); if (res.success === false) { @@ -127,17 +121,14 @@ const customTagProcessor = async (message, category, destination, contactId) => // We are retrieving 100 tags which is the maximum limit, in each iteration, until all tags are retrieved. // Ref - https://developers.activecampaign.com/reference/pagination const promises = []; - if (parseInt(get(res, 'response.data.meta.total'), 10) > 100) { - const limit = Math.floor(parseInt(get(res, 'response.data.meta.total'), 10) / 100); + if (parseInt(get(res, TOTAL_RECORDS_KEY), 10) > 100) { + const limit = Math.floor(parseInt(get(res, TOTAL_RECORDS_KEY), 10) / 100); for (let i = 0; i < limit; i += 1) { endpoint = `${destination.Config.apiUrl}${category.tagEndPoint}?limit=100&offset=${ 100 * (i + 1) }`; requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; const resp = httpGET(endpoint, requestOptions); promises.push(resp); @@ -176,10 +167,7 @@ const customTagProcessor = async (message, category, destination, contactId) => }, }; requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = await httpPOST(endpoint, requestData, requestOptions); if (res.success === false) { @@ -204,10 +192,7 @@ const customTagProcessor = async (message, category, destination, contactId) => }, }; requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = httpPOST(endpoint, requestData, requestOptions); return res; @@ -246,8 +231,8 @@ const customFieldProcessor = async (message, category, destination) => { responseStaging.push(res.response.status === 200 ? res.response.data.fields : []); const promises = []; - const limit = Math.floor(parseInt(get(res, 'response.data.meta.total'), 10) / 100); - if (parseInt(get(res, 'response.data.meta.total'), 10) > 100) { + const limit = Math.floor(parseInt(get(res, TOTAL_RECORDS_KEY), 10) / 100); + if (parseInt(get(res, TOTAL_RECORDS_KEY), 10) > 100) { for (let i = 0; i < limit; i += 1) { endpoint = `${destination.Config.apiUrl}${category.fieldEndPoint}?limit=100&offset=${ 100 * (i + 1) @@ -347,10 +332,7 @@ const customListProcessor = async (message, category, destination, contactId) => }, }; const requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; const res = httpPOST(endpoint, requestData, requestOptions); promises.push(res); @@ -404,10 +386,7 @@ const screenRequestHandler = async (message, category, destination) => { let res; let endpoint = `${destination.Config.apiUrl}${category.getEventEndPoint}`; const requestOptions = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = await httpGET(endpoint, requestOptions); if (res.success === false) { @@ -438,10 +417,7 @@ const screenRequestHandler = async (message, category, destination) => { }, }; const requestOpt = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = await httpPOST(endpoint, requestData, requestOpt); if (res.success === false) { @@ -466,8 +442,8 @@ const screenRequestHandler = async (message, category, destination) => { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); payload.actid = destination.Config.actid; payload.key = destination.Config.eventKey; - if (get(message, 'properties.eventData')) { - payload.eventdata = get(message, 'properties.eventData'); + if (get(message, EVENT_DATA_KEY)) { + payload.eventdata = get(message, EVENT_DATA_KEY); } payload.visit = `{"email":"${get(message, 'context.traits.email')}"}`; return responseBuilderSimple(payload, category, destination); @@ -513,10 +489,7 @@ const trackRequestHandler = async (message, category, destination) => { }, }; const requestOpt = { - headers: { - 'Content-Type': 'application/json', - 'Api-Token': destination.Config.apiKey, - }, + headers: getHeader(destination), }; res = await httpPOST(endpoint, requestData, requestOpt); if (res.response?.status !== 201) { @@ -538,8 +511,8 @@ const trackRequestHandler = async (message, category, destination) => { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); payload.actid = destination.Config.actid; payload.key = destination.Config.eventKey; - if (get(message, 'properties.eventData')) { - payload.eventdata = get(message, 'properties.eventData'); + if (get(message, EVENT_DATA_KEY)) { + payload.eventdata = get(message, EVENT_DATA_KEY); } payload.visit = `{"email":"${get(message, 'context.traits.email')}"}`; diff --git a/src/v0/destinations/active_campaign/util.js b/src/v0/destinations/active_campaign/util.js index 2421d856818e..c50861833677 100644 --- a/src/v0/destinations/active_campaign/util.js +++ b/src/v0/destinations/active_campaign/util.js @@ -28,4 +28,7 @@ const errorHandler = (err, message) => { } }; -module.exports = { errorHandler }; +const offsetLimitVarPath = 'response.data.meta.total'; +const eventDataVarPath = 'properties.eventData'; + +module.exports = { errorHandler, offsetLimitVarPath, eventDataVarPath }; diff --git a/src/v0/destinations/adj/transform.js b/src/v0/destinations/adj/transform.js index eb4e2e3983fc..1862012bb112 100644 --- a/src/v0/destinations/adj/transform.js +++ b/src/v0/destinations/adj/transform.js @@ -92,12 +92,11 @@ const processEvent = (message, destination) => { } const messageType = message.type.toLowerCase(); let category; - switch (messageType) { - case EventType.TRACK: - category = CONFIG_CATEGORIES.TRACK; - break; - default: - throw new InstrumentationError('Message type not supported'); + + if (messageType === EventType.TRACK) { + category = CONFIG_CATEGORIES.TRACK; + } else { + throw new InstrumentationError('Message type not supported'); } // build the response diff --git a/src/v0/destinations/adobe_analytics/config.js b/src/v0/destinations/adobe_analytics/config.js index 3002d82cba88..08fce3bb4c4d 100644 --- a/src/v0/destinations/adobe_analytics/config.js +++ b/src/v0/destinations/adobe_analytics/config.js @@ -25,34 +25,19 @@ const ECOM_PRODUCT_EVENTS = [ const formatDestinationConfig = (config) => ({ ...config, - eventsToTypes: getHashFromArray(config.eventsToTypes, 'from', 'to', false), - listMapping: getHashFromArray(config.listMapping, 'from', 'to', false), - listDelimiter: getHashFromArray(config.listDelimiter, 'from', 'to', false), - productMerchEvarsMap: getHashFromArray(config.productMerchEvarsMap, 'from', 'to', false), - productMerchEventToAdobeEvent: getHashFromArray( - config.productMerchEventToAdobeEvent, - 'from', - 'to', - false, - ), + eventsToTypes: getHashFromArray(config.eventsToTypes), + listMapping: getHashFromArray(config.listMapping), + listDelimiter: getHashFromArray(config.listDelimiter), + productMerchEvarsMap: getHashFromArray(config.productMerchEvarsMap), + productMerchEventToAdobeEvent: getHashFromArray(config.productMerchEventToAdobeEvent), eventMerchProperties: config.eventMerchProperties, - eventMerchEventToAdobeEvent: getHashFromArray( - config.eventMerchEventToAdobeEvent, - 'from', - 'to', - false, - ), - rudderEventsToAdobeEvents: getHashFromArray( - config.rudderEventsToAdobeEvents, - 'from', - 'to', - false, - ), - customPropsMapping: getHashFromArray(config.customPropsMapping, 'from', 'to', false), - propsDelimiter: getHashFromArray(config.propsDelimiter, 'from', 'to', false), - eVarMapping: getHashFromArray(config.eVarMapping, 'from', 'to', false), - hierMapping: getHashFromArray(config.hierMapping, 'from', 'to', false), - contextDataMapping: getHashFromArray(config.contextDataMapping, 'from', 'to', false), + eventMerchEventToAdobeEvent: getHashFromArray(config.eventMerchEventToAdobeEvent), + rudderEventsToAdobeEvents: getHashFromArray(config.rudderEventsToAdobeEvents), + customPropsMapping: getHashFromArray(config.customPropsMapping), + propsDelimiter: getHashFromArray(config.propsDelimiter), + eVarMapping: getHashFromArray(config.eVarMapping), + hierMapping: getHashFromArray(config.hierMapping), + contextDataMapping: getHashFromArray(config.contextDataMapping), }); module.exports = { diff --git a/src/v0/destinations/adobe_analytics/transform.js b/src/v0/destinations/adobe_analytics/transform.js index 6b391fcde1c6..3e61dbb8e28b 100644 --- a/src/v0/destinations/adobe_analytics/transform.js +++ b/src/v0/destinations/adobe_analytics/transform.js @@ -25,7 +25,7 @@ const { handleHier, handleList, handleCustomProperties, - stringifyValueAndJoinWithDelimitter, + stringifyValueAndJoinWithDelimiter, } = require('./utils'); /* Configuration variables documentation: https://experienceleague.adobe.com/docs/analytics/implementation/vars/config-vars/configuration-variables.html?lang=en @@ -169,51 +169,70 @@ const responseBuilderSimple = async (message, destinationConfig, basicPayload) = return response; }; -const processTrackEvent = (message, adobeEventName, destinationConfig, extras = {}) => { - // set event string and product string only - // handle extra properties - // rest of the properties are handled under common properties - const { - eventMerchEventToAdobeEvent, - eventMerchProperties, - productMerchEventToAdobeEvent, - productIdentifier, - productMerchProperties, - productMerchEvarsMap, - } = destinationConfig; - const { event: rawMessageEvent, properties } = message; - const { overrideEventString, overrideProductString, products } = properties; - const event = rawMessageEvent; - const adobeEventArr = adobeEventName ? adobeEventName.split(',') : []; - // adobeEventArr is an array of events which is defined as - // ["eventName", "mapped Adobe Event=mapped merchproperty's value", "mapped Adobe Event=mapped merchproperty's value", . . .] - - // merch event section - if (eventMerchEventToAdobeEvent[event] && eventMerchProperties) { - const adobeMerchEvent = eventMerchEventToAdobeEvent[event].split(','); - eventMerchProperties.forEach((rudderProp) => { - if (rudderProp.eventMerchProperties in properties) { - adobeMerchEvent.forEach((value) => { - if (properties[rudderProp?.eventMerchProperties]) { - const merchEventString = `${value}=${properties[rudderProp?.eventMerchProperties]}`; - adobeEventArr.push(merchEventString); - } +function handleProducts( + message, + destinationConfig, + event, + adobeProdEventArr, + isSingleProdEvent, + prod, +) { + const { productMerchEventToAdobeEvent, productMerchProperties, productMerchEvarsMap } = + destinationConfig; + const { properties } = message; + let prodEventString = ''; + let prodEVarsString = ''; + if (productMerchEventToAdobeEvent[event] && productMerchProperties) { + const merchMap = []; + productMerchProperties.forEach((rudderProp) => { + // adding product level merchandise properties + if ( + rudderProp.productMerchProperties.startsWith('products.') && + isSingleProdEvent === false + ) { + // take the keys after products. and find the value in properties + const key = rudderProp?.productMerchProperties.split('.'); + const v = get(prod, key[1]); + if (isDefinedAndNotNull(v)) { + adobeProdEventArr.forEach((val) => { + merchMap.push(`${val}=${v}`); + }); + } + } else if (rudderProp.productMerchProperties in properties) { + // adding root level merchandise properties + adobeProdEventArr.forEach((val) => { + merchMap.push(`${val}=${properties[rudderProp?.productMerchProperties]}`); }); } }); - } - - if (productMerchEventToAdobeEvent[event]) { - Object.keys(productMerchEventToAdobeEvent).forEach((value) => { - adobeEventArr.push(productMerchEventToAdobeEvent[value]); + // forming prodEventString from merchMap array delimited by | + prodEventString = merchMap.join('|'); + + const eVars = []; + Object.keys(productMerchEvarsMap).forEach((prodKey) => { + const prodVal = productMerchEvarsMap[prodKey]; + + if (prodKey.startsWith('products.')) { + // take the keys after products. and find the value in properties + const productValue = get(properties, prodKey?.split('.')?.[1]); + if (isDefinedAndNotNull(productValue)) { + eVars.push(`eVar${prodVal}=${productValue}`); + } + } else if (prodKey in properties) { + eVars.push(`eVar${prodVal}=${properties[prodKey]}`); + } }); + prodEVarsString = eVars.join('|'); } + return { prodEventString, prodEVarsString }; +} - // product string section +function handleProductStringSection(message, destinationConfig, event) { + const { productMerchEventToAdobeEvent, productIdentifier } = destinationConfig; + const { properties } = message; + const { products } = properties; const adobeProdEvent = productMerchEventToAdobeEvent[event]; const prodString = []; - let prodEventString = ''; - let prodEVarsString = ''; if (adobeProdEvent || ECOM_PRODUCT_EVENTS.includes(event.toLowerCase())) { const isSingleProdEvent = @@ -227,64 +246,31 @@ const processTrackEvent = (message, adobeEventName, destinationConfig, extras = adobeProdEventArr = adobeProdEvent.split(','); } - productsArr.forEach((value) => { - const category = value?.category || ''; - const quantity = value?.quantity || 1; - const total = value?.price ? (value.price * quantity).toFixed(2) : 0; - let item = value[productIdentifier]; + productsArr.forEach((prod) => { + const category = prod?.category || ''; + const quantity = prod?.quantity || 1; + const total = prod?.price ? (prod.price * quantity).toFixed(2) : 0; + let item = prod[productIdentifier]; if (productIdentifier === 'id') { - item = value?.product_id || value?.id; + item = prod?.product_id || prod?.id; } - const merchMap = []; - if (productMerchEventToAdobeEvent[event] && productMerchProperties) { - productMerchProperties.forEach((rudderProp) => { - // adding product level merchandise properties - if ( - rudderProp.productMerchProperties.startsWith('products.') && - isSingleProdEvent === false - ) { - // take the keys after products. and find the value in properties - const key = rudderProp?.productMerchProperties.split('.'); - const v = get(value, key[1]); - if (isDefinedAndNotNull(v)) { - adobeProdEventArr.forEach((val) => { - merchMap.push(`${val}=${v}`); - }); - } - } else if (rudderProp.productMerchProperties in properties) { - // adding root level merchandise properties - adobeProdEventArr.forEach((val) => { - merchMap.push(`${val}=${properties[rudderProp?.productMerchProperties]}`); - }); - } - }); - // forming prodEventString from merchMap array delimited by | - prodEventString = merchMap.join('|'); - - const eVars = []; - Object.keys(productMerchEvarsMap).forEach((prodKey) => { - const prodVal = productMerchEvarsMap[prodKey]; - - if (prodKey.startsWith('products.')) { - // take the keys after products. and find the value in properties - const productValue = get(properties, prodKey?.split('.')?.[1]); - if (isDefinedAndNotNull(productValue)) { - eVars.push(`eVar${prodVal}=${productValue}`); - } - } else if (prodKey in properties) { - eVars.push(`eVar${prodVal}=${properties[prodKey]}`); - } - }); - prodEVarsString = eVars.join('|'); - } + const { prodEventString, prodEVarsString } = handleProducts( + message, + destinationConfig, + event, + adobeProdEventArr, + isSingleProdEvent, + prod, + ); + // preparing the product string for the final payload // if prodEventString or prodEVarsString are missing or not let prodArr = [category, item, quantity, total]; if (prodEventString || prodEVarsString) { prodArr = [...prodArr, prodEventString, prodEVarsString]; } - const test = stringifyValueAndJoinWithDelimitter(prodArr); + const test = stringifyValueAndJoinWithDelimiter(prodArr); if (isSingleProdEvent) { prodString.push(test); } else { @@ -297,6 +283,45 @@ const processTrackEvent = (message, adobeEventName, destinationConfig, extras = prodString.pop(); } } + return prodString; +} + +const processTrackEvent = (message, adobeEventName, destinationConfig, extras = {}) => { + // set event string and product string only + // handle extra properties + // rest of the properties are handled under common properties + const { eventMerchEventToAdobeEvent, eventMerchProperties, productMerchEventToAdobeEvent } = + destinationConfig; + const { event: rawMessageEvent, properties } = message; + const { overrideEventString, overrideProductString } = properties; + const event = rawMessageEvent.toLowerCase(); + const adobeEventArr = adobeEventName ? adobeEventName.split(',') : []; + // adobeEventArr is an array of events which is defined as + // ["eventName", "mapped Adobe Event=mapped merchproperty's value", "mapped Adobe Event=mapped merchproperty's value", . . .] + + // merch event section + if (eventMerchEventToAdobeEvent[event] && eventMerchProperties) { + const adobeMerchEvent = eventMerchEventToAdobeEvent[event].split(','); + eventMerchProperties.forEach((rudderProp) => { + if (rudderProp.eventMerchProperties in properties) { + adobeMerchEvent.forEach((value) => { + if (properties[rudderProp?.eventMerchProperties]) { + const merchEventString = `${value}=${properties[rudderProp?.eventMerchProperties]}`; + adobeEventArr.push(merchEventString); + } + }); + } + }); + } + + if (productMerchEventToAdobeEvent[event]) { + Object.keys(productMerchEventToAdobeEvent).forEach((value) => { + adobeEventArr.push(productMerchEventToAdobeEvent[value]); + }); + } + + // product string section + const prodString = handleProductStringSection(message, destinationConfig, event); return { ...extras, @@ -306,12 +331,13 @@ const processTrackEvent = (message, adobeEventName, destinationConfig, extras = }; const handleTrack = (message, destinationConfig) => { + const ORDER_ID_KEY = 'properties.order_id'; const { event: rawEvent } = message; let payload = null; // handle ecommerce events separately // generic events should go to the default - const event = rawEvent; - switch (event.toLowerCase()) { + const event = rawEvent?.toLowerCase(); + switch (event) { case 'product viewed': case 'product list viewed': payload = processTrackEvent(message, 'prodView', destinationConfig); @@ -324,9 +350,8 @@ const handleTrack = (message, destinationConfig) => { break; case 'order completed': payload = processTrackEvent(message, 'purchase', destinationConfig, { - purchaseID: get(message, 'properties.purchaseId') || get(message, 'properties.order_id'), - transactionID: - get(message, 'properties.transactionId') || get(message, 'properties.order_id'), + purchaseID: get(message, 'properties.purchaseId') || get(message, ORDER_ID_KEY), + transactionID: get(message, 'properties.transactionId') || get(message, ORDER_ID_KEY), }); break; case 'cart viewed': @@ -334,19 +359,18 @@ const handleTrack = (message, destinationConfig) => { break; case 'checkout started': payload = processTrackEvent(message, 'scCheckout', destinationConfig, { - purchaseID: get(message, 'properties.purchaseId') || get(message, 'properties.order_id'), - transactionID: - get(message, 'properties.transactionId') || get(message, 'properties.order_id'), + purchaseID: get(message, 'properties.purchaseId') || get(message, ORDER_ID_KEY), + transactionID: get(message, 'properties.transactionId') || get(message, ORDER_ID_KEY), }); break; case 'cart opened': payload = processTrackEvent(message, 'scOpen', destinationConfig); break; default: - if (destinationConfig.rudderEventsToAdobeEvents[event]) { + if (destinationConfig.rudderEventsToAdobeEvents[event.toLowerCase()]) { payload = processTrackEvent( message, - destinationConfig.rudderEventsToAdobeEvents[event].trim(), + destinationConfig.rudderEventsToAdobeEvents[event.toLowerCase()].trim(), destinationConfig, ); } else { diff --git a/src/v0/destinations/adobe_analytics/utils.js b/src/v0/destinations/adobe_analytics/utils.js index c175765a3423..0763dbdf4462 100644 --- a/src/v0/destinations/adobe_analytics/utils.js +++ b/src/v0/destinations/adobe_analytics/utils.js @@ -51,8 +51,8 @@ const stringifyValue = (val) => { return val; }; -const stringifyValueAndJoinWithDelimitter = (valArr, delimitter = ';') => - valArr.map(stringifyValue).join(delimitter); +const stringifyValueAndJoinWithDelimiter = (valArr, delimiter = ';') => + valArr.map(stringifyValue).join(delimiter); function handleContextData(payload, destinationConfig, message) { const { contextDataPrefix, contextDataMapping } = destinationConfig; @@ -194,5 +194,5 @@ module.exports = { handleHier, handleList, handleCustomProperties, - stringifyValueAndJoinWithDelimitter, + stringifyValueAndJoinWithDelimiter, }; diff --git a/src/v0/destinations/af/transform.js b/src/v0/destinations/af/transform.js index aa227e81b426..d3a26a79b0ff 100644 --- a/src/v0/destinations/af/transform.js +++ b/src/v0/destinations/af/transform.js @@ -18,6 +18,7 @@ const { const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { Event, ENDPOINT, ConfigCategory, mappingConfig, nameToEventMap } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, message, destination) { const { androidAppId, appleAppId } = destination.Config; @@ -92,7 +93,7 @@ function responseBuilderSimple(payload, message, destination) { const response = defaultRequestConfig(); response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, authentication: devKey, }; response.method = defaultPostRequestConfig.requestMethod; @@ -148,10 +149,11 @@ function getEventValueMapFromMappingJson(message, mappingJson, isMultiSupport) { } function processNonTrackEvents(message, eventName) { - if (!isDefinedAndNotNull(message.event)) { - message.event = message.name || (message.properties && message.properties.name); + const clonedMessage = { ...message }; + if (!isDefinedAndNotNull(clonedMessage.event)) { + clonedMessage.event = message.name || (message.properties && message.properties.name); } - const payload = getEventValueForUnIdentifiedTrackEvent(message); + const payload = getEventValueForUnIdentifiedTrackEvent(clonedMessage); payload.eventName = eventName; return payload; } @@ -192,7 +194,7 @@ function processSingleMessage(message, destination) { let payload; switch (messageType) { case EventType.TRACK: { - payload = processEventTypeTrack(message, destination); + payload = processEventTypeTrack(message); break; } case EventType.SCREEN: { diff --git a/src/v0/destinations/airship/transform.js b/src/v0/destinations/airship/transform.js index bb13d40524b2..a390ec8060c9 100644 --- a/src/v0/destinations/airship/transform.js +++ b/src/v0/destinations/airship/transform.js @@ -23,6 +23,9 @@ const { 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'; const identifyResponseBuilder = (message, { Config }) => { const tagPayload = constructPayload(message, identifyMapping); @@ -49,8 +52,7 @@ const identifyResponseBuilder = (message, { Config }) => { timestamp = new Date(timestamp).toISOString().replace(/\.\d{3}/, ''); // Creating attribute payload - const attributePayload = {}; - attributePayload.attributes = []; + const attributePayload = { attributes: [] }; Object.keys(traits).forEach((key) => { // tags if (typeof traits[key] === 'boolean') { @@ -64,8 +66,7 @@ const identifyResponseBuilder = (message, { Config }) => { } // attribute if (typeof traits[key] !== 'boolean') { - const attribute = {}; - attribute.action = 'set'; + const attribute = { action: 'set' }; const keyMapped = RESERVED_TRAITS_MAPPING[key.toLowerCase()]; if (keyMapped) { attribute.key = keyMapped; @@ -91,8 +92,8 @@ const identifyResponseBuilder = (message, { Config }) => { tagResponse = defaultRequestConfig(); tagResponse.endpoint = `${BASE_URL}/api/named_users/tags`; tagResponse.headers = { - 'Content-Type': 'application/json', - Accept: 'application/vnd.urbanairship+json; version=3', + 'Content-Type': JSON_MIME_TYPE, + Accept: DEFAULT_ACCEPT_HEADER, Authorization: `Bearer ${apiKey}`, }; tagResponse.method = defaultPostRequestConfig.requestMethod; @@ -107,8 +108,8 @@ const identifyResponseBuilder = (message, { Config }) => { 'userId', )}/attributes`; attributeResponse.headers = { - 'Content-Type': 'application/json', - Accept: 'application/vnd.urbanairship+json; version=3', + 'Content-Type': JSON_MIME_TYPE, + Accept: DEFAULT_ACCEPT_HEADER, Authorization: `Bearer ${apiKey}`, }; attributeResponse.method = defaultPostRequestConfig.requestMethod; @@ -154,8 +155,8 @@ const trackResponseBuilder = async (message, { Config }) => { response.body.JSON.user = {}; response.body.JSON.user.named_user_id = message.userId; response.headers = { - 'Content-Type': 'application/json', - Accept: 'application/vnd.urbanairship+json; version=3', + 'Content-Type': JSON_MIME_TYPE, + Accept: DEFAULT_ACCEPT_HEADER, 'X-UA-Appkey': `${appKey}`, Authorization: `Bearer ${apiKey}`, }; @@ -190,8 +191,7 @@ const groupResponseBuilder = (message, { Config }) => { let timestamp = getFieldValueFromMessage(message, 'timestamp'); timestamp = new Date(timestamp).toISOString().replace(/\.\d{3}/, ''); - const attributePayload = {}; - attributePayload.attributes = []; + const attributePayload = { attributes: [] }; Object.keys(traits).forEach((key) => { // tags if (typeof traits[key] === 'boolean') { @@ -205,8 +205,7 @@ const groupResponseBuilder = (message, { Config }) => { } // attribute if (typeof traits[key] !== 'boolean') { - const attribute = {}; - attribute.action = 'set'; + const attribute = { action: 'set' }; const keyMapped = RESERVED_TRAITS_MAPPING[key.toLowerCase()]; if (keyMapped) { attribute.key = keyMapped; @@ -233,8 +232,8 @@ const groupResponseBuilder = (message, { Config }) => { tagResponse = defaultRequestConfig(); tagResponse.endpoint = `${BASE_URL}/api/named_users/tags`; tagResponse.headers = { - 'Content-Type': 'application/json', - Accept: 'application/vnd.urbanairship+json; version=3', + 'Content-Type': JSON_MIME_TYPE, + Accept: DEFAULT_ACCEPT_HEADER, Authorization: `Bearer ${apiKey}`, }; tagResponse.method = defaultPostRequestConfig.requestMethod; @@ -249,8 +248,8 @@ const groupResponseBuilder = (message, { Config }) => { 'userId', )}/attributes`; attributeResponse.headers = { - 'Content-Type': 'application/json', - Accept: 'application/vnd.urbanairship+json; version=3', + 'Content-Type': JSON_MIME_TYPE, + Accept: DEFAULT_ACCEPT_HEADER, Authorization: `Bearer ${apiKey}`, }; attributeResponse.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/algolia/transform.js b/src/v0/destinations/algolia/transform.js index 23c10bbbbb47..157ad82f198a 100644 --- a/src/v0/destinations/algolia/transform.js +++ b/src/v0/destinations/algolia/transform.js @@ -100,12 +100,10 @@ const process = (event) => { const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: - response = trackResponseBuilder(message, destination); - break; - default: - throw new InstrumentationError(`message type ${messageType} not supported`); + if (messageType === EventType.TRACK) { + response = trackResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`message type ${messageType} not supported`); } return response; }; diff --git a/src/v0/destinations/am/deleteUsers.js b/src/v0/destinations/am/deleteUsers.js index c03da7e13aec..8d86fb7cca5c 100644 --- a/src/v0/destinations/am/deleteUsers.js +++ b/src/v0/destinations/am/deleteUsers.js @@ -10,6 +10,7 @@ const { ConfigurationError, NetworkError } = require('../../util/errorTypes'); const { executeCommonValidations } = require('../../util/regulation-api'); const { DELETE_MAX_BATCH_SIZE } = require('./config'); const { getUserIdBatches } = require('../../util/deleteUserUtils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const userDeletionHandler = async (userAttributes, config) => { if (!config) { @@ -21,7 +22,7 @@ const userDeletionHandler = async (userAttributes, config) => { } const headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${btoa(`${apiKey}:${apiSecret}`)}`, }; // Ref : https://www.docs.developers.amplitude.com/analytics/apis/user-privacy-api/#response diff --git a/src/v0/destinations/am/transform.js b/src/v0/destinations/am/transform.js index a302c9fe9c86..de2c81bf95cb 100644 --- a/src/v0/destinations/am/transform.js +++ b/src/v0/destinations/am/transform.js @@ -41,19 +41,20 @@ 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 EVENTS_KEY_PATH = 'body.JSON.events'; + const baseEndpoint = (destConfig) => { let retVal; - switch (destConfig.residencyServer) { - case 'EU': - retVal = BASE_URL_EU; - break; - default: - // "US" or when it is not specified - retVal = BASE_URL; + if (destConfig.residencyServer === 'EU') { + retVal = BASE_URL_EU; + } else { + // "US" or when it is not specified + retVal = BASE_URL; } return retVal; }; @@ -97,8 +98,8 @@ function getSessionId(message) { return get(message, 'session_id') ? handleSessionIdUnderRoot(message) : get(message, 'context.sessionId') - ? handleSessionIdUnderContext(message) - : -1; + ? handleSessionIdUnderContext(message) + : -1; } function addMinIdlength() { @@ -176,34 +177,46 @@ function handleTraits(messageTrait, destination) { return traitsObject; } +function handleMappingJsonObject( + mappingJson, + sourceKey, + validatePayload, + payload, + message, + Config, +) { + const { isFunc, funcName, outKey } = mappingJson[sourceKey]; + if (isFunc) { + if (validatePayload) { + const data = get(payload, outKey); + if (!isDefinedAndNotNull(data)) { + const val = AMUtils[funcName](message, sourceKey, Config); + if (val || val === false || val === 0) { + set(payload, outKey, val); + } + } + } else { + const data = get(message.traits, outKey); + // when in identify(or any other call) it checks whether outKey is present in traits + // then that value is assigned else function is applied. + // that key (outKey) will be a default key for reverse ETL and thus removed from the payload. + 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)); + } + } + } +} + function 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') { - const { isFunc, funcName, outKey } = mappingJson[sourceKey]; - if (isFunc) { - if (validatePayload) { - const data = get(payload, outKey); - if (!isDefinedAndNotNull(data)) { - const val = AMUtils[funcName](message, sourceKey, Config); - if (val || val === false || val === 0) { - set(payload, outKey, val); - } - } - } else { - const data = get(message.traits, outKey); // when in identify(or any other call) it checks whether outKey is present in traits - // then that value is assigned else function is applied. - // that key (outKey) will be a default key for reverse ETL and thus removed from the payload. - 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)); - } - } - } + handleMappingJsonObject(mappingJson, sourceKey, validatePayload, payload, message, Config); } else { // For common config if (validatePayload) { @@ -232,67 +245,10 @@ function updateConfigProperty(message, payload, mappingJson, validatePayload, Co }); } -function responseBuilderSimple( - groupInfo, - rootElementName, - message, - evType, - mappingJson, - destination, -) { - let rawPayload = {}; - const addOptions = 'options'; - const respList = []; - const response = defaultRequestConfig(); - const groupResponse = defaultRequestConfig(); - const aliasResponse = defaultRequestConfig(); - - let groups; - +function getResponseData(evType, destination, rawPayload, message, groupInfo) { let endpoint = defaultEndpoint(destination.Config); let traits; - - if ( - EventType.IDENTIFY && // If mapped to destination, Add externalId to traits - get(message, MappedToDestinationKey) - ) { - addExternalIdToTraits(message); - const identifierType = get(message, 'context.externalId.0.identifierType'); - if (identifierType === 'user_id') { - // this can be either device_id / user_id - adduserIdFromExternalId(message); - } - } - - // 1. first populate the dest keys from the config files. - // Group config file is similar to Identify config file - // because we need to make an identify call too along with group entity update - // to link the user to the partuclar group name/value. (pass in "groups" key to https://api.amplitude.com/2/httpapi where event_type: $identify) - // Additionally, we will update the user_properties with groupName:groupValue - updateConfigProperty(message, rawPayload, mappingJson, false, destination.Config); - - // 2. get campaign info (only present for JS sdk and http calls) - const campaign = get(message, 'context.campaign') || {}; - const initialRef = { - initial_referrer: get(message, 'context.page.initial_referrer'), - initial_referring_domain: get(message, 'context.page.initial_referring_domain'), - }; - 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] }); - delete campaign[oldKey]; - }); - - // append campaign info extracted above(2.) to user_properties. - // AM sdk's have a flag that captures the UTM params(https://amplitude.github.io/Amplitude-JavaScript/#amplitudeclientinit) - // but http api docs don't have any such specific keys to send the UTMs, so attaching to user_properties - rawPayload.user_properties = rawPayload.user_properties || {}; - rawPayload.user_properties = { - ...rawPayload.user_properties, - ...initialRef, - ...campaign, - }; + let groups; switch (evType) { case EventType.IDENTIFY: @@ -303,7 +259,7 @@ function responseBuilderSimple( 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 useproperties (think we can skip this extra processing as AM supports nesting upto 40 levels) + // 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); @@ -362,7 +318,7 @@ function responseBuilderSimple( if (message.isRevenue) { // making the revenue payload rawPayload = createRevenuePayload(message, rawPayload); - // deleting the properties price, product_id, quantity and revenue from evemt_properties since it is already in root + // 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; @@ -372,6 +328,70 @@ function responseBuilderSimple( } groups = groupInfo && Object.assign(groupInfo); } + return { endpoint, rawPayload, groups }; +} + +function responseBuilderSimple( + groupInfo, + rootElementName, + message, + evType, + mappingJson, + destination, +) { + let rawPayload = {}; + const addOptions = 'options'; + 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) + ) { + addExternalIdToTraits(message); + const identifierType = get(message, 'context.externalId.0.identifierType'); + if (identifierType === 'user_id') { + // this can be either device_id / user_id + adduserIdFromExternalId(message); + } + } + + // 1. first populate the dest keys from the config files. + // Group config file is similar to Identify config file + // because we need to make an identify call too along with group entity update + // to link the user to the particular group name/value. (pass in "groups" key to https://api.amplitude.com/2/httpapi where event_type: $identify) + // Additionally, we will update the user_properties with groupName:groupValue + updateConfigProperty(message, rawPayload, mappingJson, false, destination.Config); + + // 2. get campaign info (only present for JS sdk and http calls) + const campaign = get(message, 'context.campaign') || {}; + const initialRef = { + initial_referrer: get(message, 'context.page.initial_referrer'), + initial_referring_domain: get(message, 'context.page.initial_referring_domain'), + }; + 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] }); + delete campaign[oldKey]; + }); + + // append campaign info extracted above(2.) to user_properties. + // AM sdk's have a flag that captures the UTM params(https://amplitude.github.io/Amplitude-JavaScript/#amplitudeclientinit) + // but http api docs don't have any such specific keys to send the UTMs, so attaching to user_properties + rawPayload.user_properties = rawPayload.user_properties || {}; + rawPayload.user_properties = { + ...rawPayload.user_properties, + ...initialRef, + ...campaign, + }; + + const respData = getResponseData(evType, destination, rawPayload, message, groupInfo); + const { groups } = respData; + ({ endpoint, rawPayload } = respData); // for https://api.amplitude.com/2/httpapi , pass the "groups" key // refer (1.) for passing "groups" for Rudder group call @@ -379,118 +399,115 @@ function responseBuilderSimple( set(rawPayload, 'groups', groups); let payload = removeUndefinedValues(rawPayload); let unmapUserId; - switch (evType) { - case EventType.ALIAS: - // By default (1.), Alias config file populates user_id and global_user_id - // if the alias Rudder call has unmap set, delete the global_user_id key from AM event payload - // https://help.amplitude.com/hc/en-us/articles/360002750712-Portfolio-Cross-Project-Analysis#h_76557c8b-54cd-4e28-8c82-2f6778f65cd4 - unmapUserId = get(message, 'integrations.Amplitude.unmap'); - if (unmapUserId) { - payload.user_id = unmapUserId; - delete payload.global_user_id; - payload.unmap = true; + if (evType === EventType.ALIAS) { + // By default (1.), Alias config file populates user_id and global_user_id + // if the alias Rudder call has unmap set, delete the global_user_id key from AM event payload + // https://help.amplitude.com/hc/en-us/articles/360002750712-Portfolio-Cross-Project-Analysis#h_76557c8b-54cd-4e28-8c82-2f6778f65cd4 + unmapUserId = get(message, 'integrations.Amplitude.unmap'); + if (unmapUserId) { + payload.user_id = unmapUserId; + delete payload.global_user_id; + payload.unmap = true; + } + aliasResponse.method = defaultPostRequestConfig.requestMethod; + aliasResponse.endpoint = aliasEndpoint(destination.Config); + aliasResponse.userId = message.anonymousId; + payload = removeUndefinedValues(payload); + aliasResponse.body.FORM = { + api_key: destination.Config.apiKey, + [rootElementName]: [JSON.stringify(payload)], + }; + respList.push(aliasResponse); + } else { + if (message.channel === 'mobile') { + if (!destination.Config.mapDeviceBrand) { + set(payload, 'device_brand', get(message, 'context.device.manufacturer')); } - aliasResponse.method = defaultPostRequestConfig.requestMethod; - aliasResponse.endpoint = aliasEndpoint(destination.Config); - aliasResponse.userId = message.anonymousId; - payload = removeUndefinedValues(payload); - aliasResponse.body.FORM = { - api_key: destination.Config.apiKey, - [rootElementName]: [JSON.stringify(payload)], - }; - respList.push(aliasResponse); - break; - default: - 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'); + 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); - } + 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); + payload.time = new Date(getFieldValueFromMessage(message, 'timestamp')).getTime(); - updateConfigProperty( - message, - payload, - mappingConfig[ConfigCategory.COMMON_CONFIG.name], - true, - destination.Config, - ); + // 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( + 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; - } + // 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'); - } + 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': 'application/json', - }; - response.userId = message.anonymousId; - response.body.JSON = { + 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, - [rootElementName]: [payload], - [addOptions]: addMinIdlength(), + identification: [JSON.stringify(groupPayload)], }; - 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); - } - break; + respList.push(groupResponse); + } } return respList; @@ -510,6 +527,7 @@ function processSingleMessage(message, destination) { let category = ConfigCategory.DEFAULT; const messageType = message.type.toLowerCase(); + const CATEGORY_KEY = 'properties.category'; switch (messageType) { case EventType.IDENTIFY: payloadObjectName = 'events'; // identify same as events @@ -517,19 +535,18 @@ function processSingleMessage(message, destination) { category = ConfigCategory.IDENTIFY; break; case EventType.PAGE: - evType = `Viewed ${message.name || get(message, 'properties.category') || ''} Page`; + evType = `Viewed ${message.name || get(message, CATEGORY_KEY) || ''} Page`; message.properties = { ...message.properties, - name: message.name || get(message, 'properties.category'), + name: message.name || get(message, CATEGORY_KEY), }; category = ConfigCategory.PAGE; break; case EventType.SCREEN: - evType = `Viewed ${message.name || message.event || get(message, 'properties.category') || '' - } Screen`; + evType = `Viewed ${message.name || message.event || get(message, CATEGORY_KEY) || ''} Screen`; message.properties = { ...message.properties, - name: message.name || message.event || get(message, 'properties.category'), + name: message.name || message.event || get(message, CATEGORY_KEY), }; category = ConfigCategory.SCREEN; break; @@ -718,7 +735,7 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { const batchEventJobs = get(batchEventResponse, 'metadata') || []; const batchPayloadJSON = get(batchEventResponse, 'batchedRequest.body.JSON') || {}; const incomingMessageJSON = get(message, 'body.JSON'); - let incomingMessageEvent = get(message, 'body.JSON.events'); + let incomingMessageEvent = get(message, EVENTS_KEY_PATH); // check if the incoming singular event is an array or not // and set it back to array incomingMessageEvent = Array.isArray(incomingMessageEvent) @@ -742,7 +759,7 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { delete incomingMessageEvent.user_id; } - set(message, 'body.JSON.events', [incomingMessageEvent]); + set(message, EVENTS_KEY_PATH, [incomingMessageEvent]); // if this is the first event, push to batch and return const BATCH_ENDPOINT = batchEndpoint(destination.Config); if (batchEventArray.length === 0) { @@ -760,7 +777,7 @@ function getBatchEvents(message, destination, metadata, batchEventResponse) { if ( batchEventArray.length < AMBatchEventLimit && JSON.stringify(batchPayloadJSON).length + JSON.stringify(incomingMessageEvent).length < - AMBatchSizeLimit + AMBatchSizeLimit ) { batchEventArray.push(incomingMessageEvent); // set value batchEventJobs.push(metadata); @@ -789,19 +806,19 @@ function batch(destEvents) { const { message, metadata, destination } = ev; destinationObject = { ...destination }; jsonBody = get(message, 'body.JSON'); - messageEvent = get(message, 'body.JSON.events'); + messageEvent = get(message, EVENTS_KEY_PATH); userId = messageEvent && Array.isArray(messageEvent) ? messageEvent[0].user_id : messageEvent - ? messageEvent.user_id - : undefined; + ? messageEvent.user_id + : undefined; deviceId = messageEvent && Array.isArray(messageEvent) ? messageEvent[0].device_id : messageEvent - ? messageEvent.device_id - : undefined; + ? messageEvent.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) { diff --git a/src/v0/destinations/appcues/transform.js b/src/v0/destinations/appcues/transform.js index 8d4443111e6e..095256cc4e7a 100644 --- a/src/v0/destinations/appcues/transform.js +++ b/src/v0/destinations/appcues/transform.js @@ -8,6 +8,7 @@ const { removeUndefinedAndNullAndEmptyValues, simpleProcessRouterDest, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig, getEndpoint } = require('./config'); @@ -19,7 +20,7 @@ function buildResponse(payload, endpoint) { return { ...response, headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }; } diff --git a/src/v0/destinations/attentive_tag/transform.js b/src/v0/destinations/attentive_tag/transform.js index 1d5decf8c043..231beec14342 100644 --- a/src/v0/destinations/attentive_tag/transform.js +++ b/src/v0/destinations/attentive_tag/transform.js @@ -19,6 +19,7 @@ const { validateTimestamp, } = require('./util'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, apiKey, endpoint) => { if (payload) { @@ -26,7 +27,7 @@ const responseBuilder = (payload, apiKey, endpoint) => { response.endpoint = `${BASE_URL}${endpoint}`; response.headers = { Authorization: `Bearer ${apiKey}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = removeUndefinedAndNullValues(payload); diff --git a/src/v0/destinations/attentive_tag/util.js b/src/v0/destinations/attentive_tag/util.js index a8c6830b5f76..890f73cdc9f8 100644 --- a/src/v0/destinations/attentive_tag/util.js +++ b/src/v0/destinations/attentive_tag/util.js @@ -113,9 +113,7 @@ const getDestinationItemProperties = (message, isItemsRequired) => { products.forEach((item) => { const element = constructPayload(item, mappingConfig[ConfigCategory.ITEMS.name]); const price = []; - const pricing = {}; - pricing.value = parseInt(item.price, 10); - pricing.currency = item.currency; + const pricing = { value: parseInt(item.price, 10), currency: item.currency }; price.push(pricing); if ( !isDefinedAndNotNull(element.productId) || diff --git a/src/v0/destinations/attribution/transform.js b/src/v0/destinations/attribution/transform.js index 04f910d27aae..712f3e5e5d27 100644 --- a/src/v0/destinations/attribution/transform.js +++ b/src/v0/destinations/attribution/transform.js @@ -6,13 +6,14 @@ const { getFieldValueFromMessage, } = require('../../util'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, attributionConfig) { const basicAuth = Buffer.from(`${attributionConfig.writeKey}:`).toString('base64'); const response = defaultRequestConfig(); const header = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/autopilot/transform.js b/src/v0/destinations/autopilot/transform.js index 03f40d3a9034..e0fe9aa400e2 100644 --- a/src/v0/destinations/autopilot/transform.js +++ b/src/v0/destinations/autopilot/transform.js @@ -10,6 +10,7 @@ const { } = require('../../util'); const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyFields = [ 'email', @@ -29,8 +30,8 @@ function responseBuilderSimple(message, category, destination) { const response = defaultRequestConfig(); response.headers = { autopilotapikey: destination.Config.apiKey, - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, }; let responseBody; let contactIdOrEmail; diff --git a/src/v0/destinations/blueshift/transform.js b/src/v0/destinations/blueshift/transform.js index dc63e648b4f0..b79af327d25d 100644 --- a/src/v0/destinations/blueshift/transform.js +++ b/src/v0/destinations/blueshift/transform.js @@ -9,6 +9,7 @@ const { extractCustomFields, simpleProcessRouterDest, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { TransformationError, InstrumentationError, @@ -25,18 +26,15 @@ const { } = require('./config'); function checkValidEventName(str) { - if (str.includes('.') || /\d/.test(str) || str.length > 64) return true; - return false; + return str.includes('.') || /\d/.test(str) || str.length > 64; } const getBaseURL = (config) => { let urlValue; - switch (config.dataCenter) { - case 'eu': - urlValue = BASE_URL_EU; - break; - default: - urlValue = BASE_URL; + if (config.dataCenter === 'eu') { + urlValue = BASE_URL_EU; + } else { + urlValue = BASE_URL; } return urlValue; }; @@ -77,7 +75,7 @@ const trackResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.eventApiKey).toString('base64'); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = payload; return response; @@ -108,7 +106,7 @@ const identifyResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.usersApiKey).toString('base64'); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = payload; return response; @@ -136,7 +134,7 @@ const groupResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.eventApiKey).toString('base64'); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = payload; return response; diff --git a/src/v0/destinations/bqstream/transform.js b/src/v0/destinations/bqstream/transform.js index a6d0f4978243..dae26def5c5a 100644 --- a/src/v0/destinations/bqstream/transform.js +++ b/src/v0/destinations/bqstream/transform.js @@ -105,30 +105,28 @@ const processRouterDest = (inputs) => { const eventsChunk = []; // temporary variable to divide payload into chunks const errorRespList = []; - Promise.all( - inputs.map((event) => { - try { - if (event.message.statusCode) { - // already transformed event - eventsChunk.push(event); - } else { - // if not transformed - let response = process(event); - response = Array.isArray(response) ? response : [response]; - response.forEach((res) => { - eventsChunk.push({ - message: res, - metadata: event.metadata, - destination: event.destination, - }); + inputs.forEach((event) => { + try { + if (event.message.statusCode) { + // already transformed event + eventsChunk.push(event); + } else { + // if not transformed + let response = process(event); + response = Array.isArray(response) ? response : [response]; + response.forEach((res) => { + eventsChunk.push({ + message: res, + metadata: event.metadata, + destination: event.destination, }); - } - } catch (error) { - const errRespEvent = handleRtTfSingleEventError(event, error, DESTINATION); - errorRespList.push(errRespEvent); + }); } - }), - ); + } catch (error) { + const errRespEvent = handleRtTfSingleEventError(event, error, DESTINATION); + errorRespList.push(errRespEvent); + } + }); let batchedResponseList = []; if (eventsChunk.length > 0) { diff --git a/src/v0/destinations/bqstream/util.js b/src/v0/destinations/bqstream/util.js index 05afb95e0dfc..cc3aba78b2e8 100644 --- a/src/v0/destinations/bqstream/util.js +++ b/src/v0/destinations/bqstream/util.js @@ -137,10 +137,10 @@ const responseHandler = (respTransformPayload) => { }; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = proxyRequest; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler }; diff --git a/src/v0/destinations/branch/transform.js b/src/v0/destinations/branch/transform.js index c3d926a257a5..ae214819b2bd 100644 --- a/src/v0/destinations/branch/transform.js +++ b/src/v0/destinations/branch/transform.js @@ -12,6 +12,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilder(payload, message, destination, category) { const response = defaultRequestConfig(); @@ -31,8 +32,8 @@ function responseBuilder(payload, message, destination, category) { return { ...response, headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, }, userId: message.anonymousId, }; diff --git a/src/v0/destinations/braze/deleteUsers.js b/src/v0/destinations/braze/deleteUsers.js index aa4c76d1d64b..c90946dae40f 100644 --- a/src/v0/destinations/braze/deleteUsers.js +++ b/src/v0/destinations/braze/deleteUsers.js @@ -9,6 +9,7 @@ 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) => { if (!config) { @@ -35,7 +36,7 @@ const userDeletionHandler = async (userAttributes, config) => { const data = { external_ids: batchEvent }; const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${restApiKey}`, }, }; diff --git a/src/v0/destinations/braze/networkHandler.js b/src/v0/destinations/braze/networkHandler.js index 13d5e94cc24c..f942fdc3c37c 100644 --- a/src/v0/destinations/braze/networkHandler.js +++ b/src/v0/destinations/braze/networkHandler.js @@ -46,12 +46,12 @@ const responseHandler = (destinationResponse, _dest) => { }; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = proxyRequest; this.prepareProxy = prepareProxyRequest; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 1e59ca76d44f..700ab087ad0e 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -30,20 +30,21 @@ const logger = require('../../../logger'); const { getEndpointFromConfig } = require('./util'); const { handleHttpRequest } = require('../../../adapters/network'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function formatGender(gender) { // few possible cases of woman - if (['woman', 'female', 'w', 'f'].includes(gender.toLowerCase())) { + if (['woman', 'female', 'w', 'f'].includes(gender?.toLowerCase())) { return 'F'; } // few possible cases of man - if (['man', 'male', 'm'].includes(gender.toLowerCase())) { + if (['man', 'male', 'm'].includes(gender?.toLowerCase())) { return 'M'; } // few possible cases of other - if (['other', 'o'].includes(gender.toLowerCase())) { + if (['other', 'o'].includes(gender?.toLowerCase())) { return 'O'; } @@ -58,8 +59,8 @@ function buildResponse(message, destination, properties, endpoint) { return { ...response, headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, Authorization: `Bearer ${destination.Config.restApiKey}`, }, userId: message.userId || message.anonymousId, @@ -131,7 +132,7 @@ function populateCustomAttributesWithOperation( }); } } catch (exp) { - logger.info('Failure occured during custom attributes operations', exp); + logger.info('Failure occurred during custom attributes operations', exp); } } @@ -147,21 +148,6 @@ function getUserAttributesObject(message, mappingJson, destination) { return traits; } - // iterate over the destKeys and set the value if present - Object.keys(mappingJson).forEach((destKey) => { - let value = get(traits, mappingJson[destKey]); - if (value) { - // handle gender special case - if (destKey === 'gender') { - value = formatGender(value); - } - if (destKey === 'email') { - value = value.toLowerCase(); - } - data[destKey] = value; - } - }); - // reserved keys : already mapped through mappingJson const reservedKeys = [ 'address', @@ -174,7 +160,22 @@ function getUserAttributesObject(message, mappingJson, destination) { 'phone', ]; + // iterate over the destKeys and set the value if present if (traits) { + Object.keys(mappingJson).forEach((destKey) => { + let value = get(traits, mappingJson[destKey]); + if (value || (value === null && reservedKeys.includes(destKey))) { + // handle gender special case + if (destKey === 'gender') { + value = formatGender(value); + } + if (destKey === 'email') { + value = value.toLowerCase(); + } + data[destKey] = value; + } + }); + // iterate over rest of the traits properties Object.keys(traits).forEach((traitKey) => { // if traitKey is not reserved add the value to final output @@ -261,9 +262,7 @@ function processTrackWithUserAttributes(message, destination, mappingJson, proce getTrackEndPoint(getEndpointFromConfig(destination)), ); } - throw new InstrumentationError( - 'No attributes found to update the user profile', - ); + throw new InstrumentationError('No attributes found to update the user profile'); } function handleReservedProperties(props) { @@ -369,10 +368,8 @@ function processTrackEvent(messageType, message, destination, mappingJson, proce delete properties.products; delete properties.currency; - let payload = {}; - payload.properties = properties; - - payload = setExternalIdOrAliasObject(payload, message); + const payload = { properties }; + setExternalIdOrAliasObject(payload, message); return buildResponse( message, destination, @@ -422,8 +419,9 @@ function processGroup(message, destination) { 'Message should have traits with subscriptionState, email or phone', ); } - const subscriptionGroup = {}; - subscriptionGroup.subscription_group_id = groupId; + const subscriptionGroup = { + subscription_group_id: groupId, + }; if ( message.traits.subscriptionState !== 'subscribed' && message.traits.subscriptionState !== 'unsubscribed' @@ -447,8 +445,8 @@ function processGroup(message, destination) { return { ...response, headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, Authorization: `Bearer ${destination.Config.restApiKey}`, }, }; diff --git a/src/v0/destinations/braze/util.js b/src/v0/destinations/braze/util.js index 45fe2eaee249..8833923af8c1 100644 --- a/src/v0/destinations/braze/util.js +++ b/src/v0/destinations/braze/util.js @@ -33,12 +33,14 @@ const CustomAttributeOperationUtil = { data[key] = {}; const opsResultArray = []; for (let i = 0; i < traits[key][CustomAttributeOperationTypes.UPDATE].length; i += 1) { - const myObj = {}; - myObj.$identifier_key = traits[key][CustomAttributeOperationTypes.UPDATE][i].identifier; - myObj.$identifier_value = - traits[key][CustomAttributeOperationTypes.UPDATE][i][ - traits[key][CustomAttributeOperationTypes.UPDATE][i].identifier - ]; + const myObj = { + $identifier_key: traits[key][CustomAttributeOperationTypes.UPDATE][i].identifier, + $identifier_value: + traits[key][CustomAttributeOperationTypes.UPDATE][i][ + traits[key][CustomAttributeOperationTypes.UPDATE][i].identifier + ], + }; + delete traits[key][CustomAttributeOperationTypes.UPDATE][i][ traits[key][CustomAttributeOperationTypes.UPDATE][i].identifier ]; @@ -59,12 +61,13 @@ const CustomAttributeOperationUtil = { customAttributeRemoveOperation(key, data, traits) { const opsResultArray = []; for (let i = 0; i < traits[key][CustomAttributeOperationTypes.REMOVE].length; i += 1) { - const myObj = {}; - myObj.$identifier_key = traits[key][CustomAttributeOperationTypes.REMOVE][i].identifier; - myObj.$identifier_value = - traits[key][CustomAttributeOperationTypes.REMOVE][i][ - traits[key][CustomAttributeOperationTypes.REMOVE][i].identifier - ]; + const myObj = { + $identifier_key: traits[key][CustomAttributeOperationTypes.REMOVE][i].identifier, + $identifier_value: + traits[key][CustomAttributeOperationTypes.REMOVE][i][ + traits[key][CustomAttributeOperationTypes.REMOVE][i].identifier + ], + }; opsResultArray.push(myObj); } data[key][`$${CustomAttributeOperationTypes.REMOVE}`] = opsResultArray; @@ -128,7 +131,6 @@ const BrazeDedupUtility = { const externalIdentifiers = ids.filter((id) => id.external_id); const aliasIdentifiers = ids.filter((id) => id.alias_name !== undefined); - const startTime = Date.now(); const { processedResponse: lookUpResponse } = await handleHttpRequest( 'post', `${getEndpointFromConfig(destination)}/users/export/ids`, @@ -143,11 +145,6 @@ const BrazeDedupUtility = { timeout: 10 * 1000, }, ); - const endTime = Date.now(); - // TODO: Remove this log - console.log( - `Time taken to fetch user store: ${endTime - startTime} ms for ${ids.length} users`, - ); stats.counter('braze_lookup_failure_count', 1, { http_status: lookUpResponse.status }); const { users } = lookUpResponse.response; diff --git a/src/v0/destinations/campaign_manager/networkHandler.js b/src/v0/destinations/campaign_manager/networkHandler.js index 39505770fe72..d324c6300bed 100644 --- a/src/v0/destinations/campaign_manager/networkHandler.js +++ b/src/v0/destinations/campaign_manager/networkHandler.js @@ -17,12 +17,10 @@ const tags = require('../../util/tags'); * @returns */ const getAuthErrCategory = (code) => { - switch (code) { - case 401: - return REFRESH_TOKEN; - default: - return ''; + if (code === 401) { + return REFRESH_TOKEN; } + return ''; }; function checkIfFailuresAreRetryable(response) { @@ -79,11 +77,11 @@ const responseHandler = (destinationResponse) => { ); }; -const networkHandler = function () { +function networkHandler() { this.prepareProxy = prepareProxyRequest; this.proxy = proxyRequest; this.processAxiosResponse = processAxiosResponse; this.responseHandler = responseHandler; -}; +} module.exports = { networkHandler }; diff --git a/src/v0/destinations/campaign_manager/transform.js b/src/v0/destinations/campaign_manager/transform.js index 6941824a9d65..93ec3e8ea3cb 100644 --- a/src/v0/destinations/campaign_manager/transform.js +++ b/src/v0/destinations/campaign_manager/transform.js @@ -18,6 +18,7 @@ const { } = require('./config'); const { InstrumentationError, OAuthSecretError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const getAccessToken = ({ secret }) => { if (!secret) { @@ -36,7 +37,7 @@ function buildResponse(requestJson, metadata, endpointUrl, requestType, encrypti response.endpoint = endpointUrl; response.headers = { Authorization: `Bearer ${getAccessToken(metadata)}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON.kind = @@ -190,12 +191,10 @@ function process(event) { const messageType = message.type.toLowerCase(); let response = {}; - switch (messageType) { - case EventType.TRACK: - response = processTrack(message, metadata, destination); - break; - default: - throw new InstrumentationError(`Message type ${messageType} not supported`); + if (messageType === EventType.TRACK) { + response = processTrack(message, metadata, destination); + } else { + throw new InstrumentationError(`Message type ${messageType} not supported`); } postValidateRequest(response); return response; diff --git a/src/v0/destinations/candu/transform.js b/src/v0/destinations/candu/transform.js index f7c6110a47e6..659af3654053 100644 --- a/src/v0/destinations/candu/transform.js +++ b/src/v0/destinations/candu/transform.js @@ -5,6 +5,7 @@ const { removeUndefinedAndNullValues, simpleProcessRouterDest, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const { endpoint, identifyDataMapping, trackDataMapping } = require('./config'); @@ -22,7 +23,7 @@ const responseBuilder = (body, { Config }) => { const basicAuth = Buffer.from(Config.apiKey).toString('base64'); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; }; diff --git a/src/v0/destinations/canny/transform.js b/src/v0/destinations/canny/transform.js index 6910fa31b30e..d837a8ddd3be 100644 --- a/src/v0/destinations/canny/transform.js +++ b/src/v0/destinations/canny/transform.js @@ -15,6 +15,7 @@ const { validateEventMapping, } = require('./util'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (responseConfgs) => { const { payload, apiKey, endpoint, contentType, responseBody } = responseConfgs; @@ -34,7 +35,7 @@ const responseBuilder = (responseConfgs) => { const identifyResponseBuilder = (message, { Config }) => { const { apiKey } = Config; - const contentType = 'application/json'; + const contentType = JSON_MIME_TYPE; const responseBody = 'JSON'; const payload = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY.name]); @@ -73,7 +74,7 @@ const getTrackResponse = async (apiKey, message, operationType) => { payload.voterID = voterID; endpoint = ConfigCategory.CREATE_VOTE.endpoint; } else if (operationType === 'createPost') { - contentType = 'application/json'; + contentType = JSON_MIME_TYPE; responseBody = 'JSON'; payload = constructPayload(message, mappingConfig[ConfigCategory.CREATE_POST.name]); diff --git a/src/v0/destinations/canny/util.js b/src/v0/destinations/canny/util.js index 2fef313e315b..956de5482918 100644 --- a/src/v0/destinations/canny/util.js +++ b/src/v0/destinations/canny/util.js @@ -4,6 +4,8 @@ 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'); /** * Function to retrieve userId from canny using axios @@ -25,7 +27,7 @@ const retrieveUserId = async (apiKey, message) => { const header = { 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }; const requestBody = { @@ -37,11 +39,11 @@ const retrieveUserId = async (apiKey, message) => { requestBody.userID = `${userId}`; } const response = await httpPOST(url, qs.stringify(requestBody), header); - console.log(response); + logger.debug(response); // If the request fails, throwing error. if (response.success === false) { throw new NetworkError( - `[Canny]:: CannyUserID can't be gnerated due to ${response.data.error}`, + `[Canny]:: CannyUserID can't be generated due to ${response.data.error}`, response.data?.status, { [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(response.data?.status), diff --git a/src/v0/destinations/clevertap/deleteUsers.js b/src/v0/destinations/clevertap/deleteUsers.js index 05ebdca94ea3..105015a8a3c6 100644 --- a/src/v0/destinations/clevertap/deleteUsers.js +++ b/src/v0/destinations/clevertap/deleteUsers.js @@ -9,6 +9,7 @@ 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'); /** * This function will help to delete the users one by one from the userAttributes array. @@ -27,7 +28,7 @@ const userDeletionHandler = async (userAttributes, config) => { const headers = { 'X-CleverTap-Account-Id': accountId, 'X-CleverTap-Passcode': passcode, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; // userIdBatches = [[u1,u2,u3,...batchSize],[u1,u2,u3,...batchSize]...] // ref : https://developer.clevertap.com/docs/disassociate-api diff --git a/src/v0/destinations/clevertap/transform.js b/src/v0/destinations/clevertap/transform.js index 0645228050fa..1ac8468fa7d0 100644 --- a/src/v0/destinations/clevertap/transform.js +++ b/src/v0/destinations/clevertap/transform.js @@ -21,9 +21,12 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const TIMESTAMP_KEY_PATH = 'context.traits.ts'; /* -Following behaviour is expected when "enableObjectIdMapping" is enabled +Following behavior is expected when "enableObjectIdMapping" is enabled For Identify Events ---------------RudderStack----------------- ------------Clevertap------------- @@ -43,7 +46,7 @@ false true identity (value = userId) // wraps to default request config const responseWrapper = (payload, destination) => { const response = defaultRequestConfig(); - // If the acount belongs to specific regional server, + // If the account belongs to specific regional server, // we need to modify the url endpoint based on dest config. // Source: https://developer.clevertap.com/docs/idc response.endpoint = getEndpoint(destination.Config); @@ -51,14 +54,14 @@ const responseWrapper = (payload, destination) => { response.headers = { 'X-CleverTap-Account-Id': destination.Config.accountId, 'X-CleverTap-Passcode': destination.Config.passcode, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = payload; return response; }; /** - * Expected behaviours: + * Expected behaviors: payload = { "finalPayload": { "device": { "device": "{\"browser\":{\"name\":\"Chrome121\",\"version\":\"106.0.0.0\"},\"os\":{\"version\":\"10.15.7\"}}", "browser": { "name": "macOS", @@ -109,7 +112,7 @@ const mapIdentifyPayloadWithObjectId = (message, profile) => { const payload = { type: 'profile', profileData: profile, - ts: get(message, 'traits.ts') || get(message, 'context.traits.ts'), + ts: get(message, 'traits.ts') || get(message, TIMESTAMP_KEY_PATH), }; // If timestamp is not in unix format @@ -117,7 +120,7 @@ const mapIdentifyPayloadWithObjectId = (message, profile) => { payload.ts = toUnixTimestamp(payload.ts); } - // If anonymousId is present prioritising to set it as objectId + // If anonymousId is present prioritizing to set it as objectId if (anonymousId) { payload.objectId = anonymousId; // If userId is present we set it as identity inside profiledData @@ -140,7 +143,7 @@ const mapIdentifyPayload = (message, profile) => { { type: 'profile', profileData: profile, - ts: get(message, 'traits.ts') || get(message, 'context.traits.ts'), + ts: get(message, 'traits.ts') || get(message, TIMESTAMP_KEY_PATH), identity: getFieldValueFromMessage(message, 'userId'), }, ], @@ -159,7 +162,7 @@ const mapAliasPayload = (message) => { { type: 'profile', profileData: { identity: message.userId }, - ts: get(message, 'traits.ts') || get(message, 'context.traits.ts'), + ts: get(message, 'traits.ts') || get(message, TIMESTAMP_KEY_PATH), identity: message.previousId, }, ], diff --git a/src/v0/destinations/clickup/transform.js b/src/v0/destinations/clickup/transform.js index 37844f24b19b..d93e53b3490c 100644 --- a/src/v0/destinations/clickup/transform.js +++ b/src/v0/destinations/clickup/transform.js @@ -15,13 +15,14 @@ const { } = 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) => { if (payload) { const response = defaultRequestConfig(); response.endpoint = createTaskEndPoint(listId); response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: apiToken, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/clickup/util.js b/src/v0/destinations/clickup/util.js index 44f6a4f30c8c..e270d7119214 100644 --- a/src/v0/destinations/clickup/util.js +++ b/src/v0/destinations/clickup/util.js @@ -11,6 +11,7 @@ const { const { getCustomFieldsEndPoint } = require('./config'); const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Validates priority @@ -209,7 +210,7 @@ const retrieveCustomFields = async (listId, apiToken) => { const endpoint = getCustomFieldsEndPoint(listId); const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: apiToken, }, }; diff --git a/src/v0/destinations/courier/transform.js b/src/v0/destinations/courier/transform.js index a35354bb0586..a30324b3336d 100644 --- a/src/v0/destinations/courier/transform.js +++ b/src/v0/destinations/courier/transform.js @@ -5,6 +5,7 @@ const { removeUndefinedAndNullValues, simpleProcessRouterDest, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { TransformationError, InstrumentationError, @@ -18,7 +19,7 @@ const responseBuilder = (payload, endpoint, destination) => { const { apiKey } = destination.Config; response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/criteo_audience/config.js b/src/v0/destinations/criteo_audience/config.js index 1779aa3f5696..e0a344bda89d 100644 --- a/src/v0/destinations/criteo_audience/config.js +++ b/src/v0/destinations/criteo_audience/config.js @@ -1,10 +1,10 @@ -const version = "2022-10"; +const version = '2022-10'; const BASE_ENDPOINT = `https://api.criteo.com/${version}/`; -const operation = ["add", "remove"]; +const operation = ['add', 'remove']; // https://developers.criteo.com/marketing-solutions/v2021.04/docs/managing-users-in-an-audience const MAX_IDENTIFIERS = 50000; module.exports = { BASE_ENDPOINT, operation, - MAX_IDENTIFIERS + MAX_IDENTIFIERS, }; diff --git a/src/v0/destinations/criteo_audience/networkHandler.js b/src/v0/destinations/criteo_audience/networkHandler.js index b9424810af78..5bf29f63c51a 100644 --- a/src/v0/destinations/criteo_audience/networkHandler.js +++ b/src/v0/destinations/criteo_audience/networkHandler.js @@ -1,22 +1,25 @@ -const { - prepareProxyRequest, - proxyRequest -} = require("../../../adapters/network"); -const { isHttpStatusSuccess } = require("../../util/index"); -const { - REFRESH_TOKEN -} = require("../../../adapters/networkhandler/authConstants"); -const tags = require("../../util/tags"); +const { prepareProxyRequest, proxyRequest } = require('../../../adapters/network'); +const { isHttpStatusSuccess } = require('../../util/index'); +const { REFRESH_TOKEN } = require('../../../adapters/networkhandler/authConstants'); +const tags = require('../../util/tags'); const { getDynamicErrorType, - processAxiosResponse -} = require("../../../adapters/utils/networkUtils"); -const { NetworkError, ThrottledError, NetworkInstrumentationError, AbortedError, RetryableError } = require("../../util/errorTypes"); + 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. const matchErrorCode = (errorCode, response) => - response && Array.isArray(response?.errors) && response.errors.some((resp) => resp?.code === errorCode); + response && + Array.isArray(response?.errors) && + response.errors.some((resp) => resp?.code === errorCode); const criteoAudienceRespHandler = (destResponse, stageMsg) => { const { status, response } = destResponse; @@ -28,10 +31,10 @@ const criteoAudienceRespHandler = (destResponse, stageMsg) => { `${response?.errors[0]?.title} ${stageMsg}`, status, { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status) + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), }, response, - REFRESH_TOKEN + REFRESH_TOKEN, ); } else if (status === 404 && matchErrorCode('audience-invalid', response)) { // to handle the case when audience-id is invalid @@ -47,37 +50,34 @@ const criteoAudienceRespHandler = (destResponse, stageMsg) => { ); } else if (status === 503 || status === 500) { // see if its 500 internal error or 503 service unavailable - throw new RetryableError( - `Request Failed: ${stageMsg} (Retryable)`, - 500, - destResponse, - ); + throw new RetryableError(`Request Failed: ${stageMsg} (Retryable)`, 500, destResponse); } // else throw the error const errorMessage = response?.errors; throw new AbortedError( - `Request Failed: ${stageMsg} with status "${status}" due to "${errorMessage? JSON.stringify(errorMessage[0]) : JSON.stringify(response) + `Request Failed: ${stageMsg} with status "${status}" due to "${ + errorMessage ? JSON.stringify(errorMessage[0]) : JSON.stringify(response) }", (Aborted) `, 400, destResponse, ); }; -const responseHandler = destinationResponse => { +const responseHandler = (destinationResponse) => { const message = `Request Processed Successfully`; const { status } = destinationResponse; if (!isHttpStatusSuccess(status)) { // if error, successfully return status, message and original destination response criteoAudienceRespHandler( destinationResponse, - "during criteo_audience response transformation" + 'during criteo_audience response transformation', ); } // Mostly any error will not have a status of 2xx return { status, message, - destinationResponse + destinationResponse, }; }; diff --git a/src/v0/destinations/criteo_audience/transform.js b/src/v0/destinations/criteo_audience/transform.js index b748457da7a0..7ddbdbef2033 100644 --- a/src/v0/destinations/criteo_audience/transform.js +++ b/src/v0/destinations/criteo_audience/transform.js @@ -11,7 +11,6 @@ const { } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); const { MappedToDestinationKey } = require('../../../constants'); - const { preparePayload } = require('./util'); const prepareResponse = (payload, audienceId, accessToken) => { diff --git a/src/v0/destinations/criteo_audience/util.js b/src/v0/destinations/criteo_audience/util.js index 6bd58816c44c..ab58560fb1c1 100644 --- a/src/v0/destinations/criteo_audience/util.js +++ b/src/v0/destinations/criteo_audience/util.js @@ -1,18 +1,15 @@ const _ = require('lodash'); -const { isDefinedAndNotNullAndNotEmpty } = require("../../util"); -const { - ConfigurationError, - InstrumentationError -} = require("../../util/errorTypes"); -const { MAX_IDENTIFIERS } = require("./config"); +const { isDefinedAndNotNullAndNotEmpty } = require('../../util'); +const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); +const { MAX_IDENTIFIERS } = require('./config'); const populateIdentifiers = (audienceList, audienceType) => { const identifiers = []; - audienceList.forEach(userTraits => { + audienceList.forEach((userTraits) => { const traits = Object.keys(userTraits); if (!traits.includes(audienceType)) { throw new InstrumentationError( - `Required property for ${audienceType} type audience is not available in an object` + `Required property for ${audienceType} type audience is not available in an object`, ); } identifiers.push(userTraits[audienceType]); @@ -23,19 +20,18 @@ const populateIdentifiers = (audienceList, audienceType) => { const populateAttributes = (audienceList, operationType, Config) => { const { audienceType, gumCallerId } = Config; - + const attributesArray = []; const identifiers = populateIdentifiers(audienceList, audienceType); - identifiers.forEach(identifier => { - const attributes = {}; - attributes.operation = operationType; - attributes.identifierType = audienceType; - attributes.internalIdentifiers = false; - if (audienceType === "gum") { + identifiers.forEach((identifier) => { + const attributes = { + operation: operationType, + identifierType: audienceType, + internalIdentifiers: false, + }; + if (audienceType === 'gum') { if (!isDefinedAndNotNullAndNotEmpty(gumCallerId)) { - throw new ConfigurationError( - `gumCallerId is required for audience type ${audienceType}` - ); + throw new ConfigurationError(`gumCallerId is required for audience type ${audienceType}`); } else { attributes.gumCallerId = gumCallerId; } @@ -49,10 +45,11 @@ const populateAttributes = (audienceList, operationType, Config) => { const populateData = (audienceList, operationType, Config) => { const arrayData = []; const populatedAttributesArray = populateAttributes(audienceList, operationType, Config); - populatedAttributesArray.forEach(populatedAttribute => { - const data = {}; - data.type = "ContactlistAmendment"; - data.attributes = populatedAttribute; + populatedAttributesArray.forEach((populatedAttribute) => { + const data = { + type: 'ContactlistAmendment', + attributes: populatedAttribute, + }; arrayData.push(data); }); return arrayData; @@ -61,12 +58,12 @@ const populateData = (audienceList, operationType, Config) => { const preparePayload = (audienceList, operationType, Config) => { const responsePayload = []; const populatedData = populateData(audienceList, operationType, Config); - populatedData.forEach(data => { + populatedData.forEach((data) => { responsePayload.push({ data }); }); return responsePayload; }; module.exports = { - preparePayload + preparePayload, }; diff --git a/src/v0/destinations/custify/transform.js b/src/v0/destinations/custify/transform.js index 74f20d8c6db0..fd81511982ae 100644 --- a/src/v0/destinations/custify/transform.js +++ b/src/v0/destinations/custify/transform.js @@ -10,6 +10,7 @@ const { } = require('../../util'); const { processIdentify, processTrack, processGroup } = require('./util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * This function validates the message and builds the response @@ -48,9 +49,9 @@ const validateAndBuildResponse = async (message, destination) => { response.method = defaultPostRequestConfig.requestMethod; response.endpoint = category.endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${destination.Config.apiKey}`, - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }; response.userId = responseBody.user_id; return response; diff --git a/src/v0/destinations/custify/util.js b/src/v0/destinations/custify/util.js index a662dbbf4cd4..82ac6ec9c5df 100644 --- a/src/v0/destinations/custify/util.js +++ b/src/v0/destinations/custify/util.js @@ -18,6 +18,7 @@ const { } = require('../../util'); const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * @@ -29,7 +30,7 @@ const tags = require('../../util/tags'); const createUpdateCompany = async (companyPayload, Config) => { const companyResponse = await httpPOST(ConfigCategory.GROUP_COMPANY.endpoint, companyPayload, { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${Config.apiKey}`, }, }); diff --git a/src/v0/destinations/customerio/config.js b/src/v0/destinations/customerio/config.js index 1f93d727863a..94e0b70e31e7 100644 --- a/src/v0/destinations/customerio/config.js +++ b/src/v0/destinations/customerio/config.js @@ -22,8 +22,8 @@ const CONFIG_CATEGORIES = { }; const MAX_BATCH_SIZE = 1000; -const DEFAULT_OBJECT_ACTION = "identify"; -const OBJECT_ACTIONS = ["identify", "delete", "add_relationships", "delete_relationships"]; +const DEFAULT_OBJECT_ACTION = 'identify'; +const OBJECT_ACTIONS = ['identify', 'delete', 'add_relationships', 'delete_relationships']; const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname); diff --git a/src/v0/destinations/customerio/data/customerIoGroup.json b/src/v0/destinations/customerio/data/customerIoGroup.json index 6d6196037242..7a18b78530ce 100644 --- a/src/v0/destinations/customerio/data/customerIoGroup.json +++ b/src/v0/destinations/customerio/data/customerIoGroup.json @@ -1,56 +1,47 @@ [ - { - "destKey": "object_id", - "sourceKeys": "groupId", - "sourceFromGenericMap": true, - "metadata": { - "type": "toString" - }, - "required": true + { + "destKey": "object_id", + "sourceKeys": "groupId", + "sourceFromGenericMap": true, + "metadata": { + "type": "toString" }, - { - "destKey": "object_type_id", - "sourceKeys": "traits.objectTypeId", - "metadata": { - "defaultValue": "1", - "type": "toString" - }, - "required": false + "required": true + }, + { + "destKey": "object_type_id", + "sourceKeys": "traits.objectTypeId", + "metadata": { + "defaultValue": "1", + "type": "toString" }, - { - "destKey": "userId", - "sourceKeys": "userIdOnly", - "sourceFromGenericMap": true, - "metadata": { - "type": "toString" - }, - "required": false + "required": false + }, + { + "destKey": "userId", + "sourceKeys": "userIdOnly", + "sourceFromGenericMap": true, + "metadata": { + "type": "toString" }, - { - "destKey": "email", - "sourceKeys": [ - "context.traits.email", - "properties.email", - "context.externalId.0.id" - ], - "required": false - }, - { - "destKey": "action", - "sourceKeys": [ - "traits.action", - "properties.action" - ], - "required": false - }, - { - "destKey": "attributes", - "sourceKeys": "traits", - "required": false, - "metadata": { - "excludes": [ - "action" - ] - } + "required": false + }, + { + "destKey": "email", + "sourceKeys": ["context.traits.email", "properties.email", "context.externalId.0.id"], + "required": false + }, + { + "destKey": "action", + "sourceKeys": ["traits.action", "properties.action"], + "required": false + }, + { + "destKey": "attributes", + "sourceKeys": "traits", + "required": false, + "metadata": { + "excludes": ["action"] } -] \ No newline at end of file + } +] diff --git a/src/v0/destinations/customerio/transform.js b/src/v0/destinations/customerio/transform.js index 2cdc5b76a858..5e69f948d3b8 100644 --- a/src/v0/destinations/customerio/transform.js +++ b/src/v0/destinations/customerio/transform.js @@ -1,79 +1,38 @@ const get = require('get-value'); -const set = require('set-value'); const btoa = require('btoa'); -const truncate = require('truncate-utf8-bytes'); -const { isAppleFamily } = require('rudder-transformer-cdk/build/utils'); -const { - EventType, - SpecedTraits, - TraitsMapping, - MappedToDestinationKey, -} = require('../../../constants'); +const { EventType, MappedToDestinationKey } = require('../../../constants'); const { - constructPayload, getErrorRespEvents, getSuccessRespEvents, defaultRequestConfig, addExternalIdToTraits, removeUndefinedValues, adduserIdFromExternalId, - defaultPutRequestConfig, - defaultPostRequestConfig, getFieldValueFromMessage, handleRtTfSingleEventError, } = require('../../util'); -const { - MAPPING_CONFIG, - OBJECT_ACTIONS, - CONFIG_CATEGORIES, - IDENTITY_ENDPOINT, - MERGE_USER_ENDPOINT, - USER_EVENT_ENDPOINT, - ANON_EVENT_ENDPOINT, - OBJECT_EVENT_ENDPOINT, - DEFAULT_OBJECT_ACTION, - DEVICE_DELETE_ENDPOINT, - DEVICE_REGISTER_ENDPOINT, -} = require('./config'); const logger = require('../../../logger'); -const { getEventChunks } = require('./util'); +const { + getEventChunks, + identifyResponseBuilder, + aliasResponseBuilder, + groupResponseBuilder, + defaultResponseBuilder, +} = require('./util'); const { InstrumentationError } = require('../../util/errorTypes'); - -const deviceRelatedEventNames = [ - 'Application Installed', - 'Application Opened', - 'Application Uninstalled', -]; - -const isdeviceRelatedEventName = (eventName, destination) => - deviceRelatedEventNames.includes(eventName) || - (destination.Config && - destination.Config.deviceTokenEventName && - destination.Config.deviceTokenEventName === eventName); - -const deviceDeleteRelatedEventName = 'Application Uninstalled'; - -// Get the spec'd traits, for now only address needs treatment as 2 layers. -// populate the list of spec'd traits in constants.js -const populateSpecedTraits = (payload, message) => { - const pathToTraits = message.traits ? 'traits' : 'context.traits'; - SpecedTraits.forEach((trait) => { - const mapping = TraitsMapping[trait]; - const keys = Object.keys(mapping); - keys.forEach((key) => { - set(payload, key, get(message, `${pathToTraits}.${mapping[`${key}`]}`)); - }); - }); -}; +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilder(message, evType, evName, destination, messageType) { - const rawPayload = {}; - let endpoint; - let trimmedEvName; - let requestConfig = defaultPostRequestConfig; + let identifyResponse; + let aliasResponse; + let groupResponse; + let defaultResponse; + let temporaryResponseDetails = {}; + + // let requestConfig = defaultPostRequestConfig; // override userId with externalId in context(if present) and event is mapped to destination const mappedToDestination = get(message, MappedToDestinationKey); if (mappedToDestination) { @@ -88,181 +47,35 @@ function responseBuilder(message, evType, evName, destination, messageType) { Authorization: `Basic ${btoa(`${destination.Config.siteID}:${destination.Config.apiKey}`)}`, }; - if (evType === EventType.IDENTIFY) { - // if userId is not there simply drop the payload - if (!userId) { - throw new InstrumentationError('userId not present'); - } - - // populate speced traits - const identityTrailts = getFieldValueFromMessage(message, 'traits') || {}; - populateSpecedTraits(rawPayload, message); - - if (Object.keys(identityTrailts).length > 0) { - const traits = Object.keys(identityTrailts); - const pathToTraits = message.traits ? 'traits' : 'context.traits'; - traits.forEach((trait) => { - // populate keys other than speced traits - // also don't send anonymousId, userId as we are setting those form the SDK and it's not actually an user property for the customer - // discard createdAt as well as we are setting the values at created_at separately - if ( - !SpecedTraits.includes(trait) && - trait !== 'createdAt' && - trait !== 'userId' && - trait !== 'anonymousId' - ) { - const dotEscapedTrait = trait.replace('.', '\\.'); - set(rawPayload, dotEscapedTrait, get(message, `${pathToTraits}.${trait}`)); - } - }); - } - - // populate user_properties (DEPRECATED) - if (message.user_properties) { - const userProps = Object.keys(message.user_properties); - userProps.forEach((prop) => { - const val = get(message, `user_properties.${prop}`); - set(rawPayload, prop, val); - }); - } - - // make user creation time - const createAt = getFieldValueFromMessage(message, 'createdAtOnly'); - // set the created_at field if traits.createAt or context.traits.createAt is passed - if (createAt) { - set(rawPayload, 'created_at', Math.floor(new Date(createAt).getTime() / 1000)); - } - - // Impportant for historical import - if (getFieldValueFromMessage(message, 'historicalTimestamp')) { - set( - rawPayload, - '_timestamp', - Math.floor( - new Date(getFieldValueFromMessage(message, 'historicalTimestamp')).getTime() / 1000, - ), + switch (evType) { + case EventType.IDENTIFY: + identifyResponse = identifyResponseBuilder(userId, message); + temporaryResponseDetails = { ...identifyResponse }; + break; + case EventType.ALIAS: + aliasResponse = aliasResponseBuilder(message, userId); + temporaryResponseDetails = { ...aliasResponse }; + break; + case EventType.GROUP: + groupResponse = groupResponseBuilder(message); + temporaryResponseDetails = { ...groupResponse }; + break; + default: + defaultResponse = defaultResponseBuilder( + message, + evName, + userId, + evType, + destination, + messageType, ); - } - // anonymous_id needs to be sent for identify calls to merge with any previous anon track calls - if (message && message.anonymousId) { - set(rawPayload, 'anonymous_id', message.anonymousId); - } - endpoint = IDENTITY_ENDPOINT.replace(':id', userId); - requestConfig = defaultPutRequestConfig; - } else if (evType === EventType.ALIAS) { - // ref : https://customer.io/docs/api/#operation/merge - if (!userId && !message.previousId) { - throw new InstrumentationError('Both userId and previousId is mandatory for merge operation'); - } - endpoint = MERGE_USER_ENDPOINT; - requestConfig = defaultPostRequestConfig; - rawPayload.primary = {}; - rawPayload.primary.id = userId; - rawPayload.secondary = {}; - rawPayload.secondary.id = message.previousId; - } else if (evType === EventType.GROUP) { - endpoint = OBJECT_EVENT_ENDPOINT; - const payload = constructPayload(message, MAPPING_CONFIG[CONFIG_CATEGORIES.OBJECT_EVENTS.name]); - rawPayload.identifiers = { - object_id: payload.object_id, - object_type_id: payload.object_type_id, - }; - rawPayload.type = 'object'; - rawPayload.action = - payload.action && OBJECT_ACTIONS.includes(payload.action) - ? payload.action - : DEFAULT_OBJECT_ACTION; - rawPayload.attributes = payload.attributes || {}; - rawPayload.cio_relationships = []; - if (payload.userId) { - rawPayload.cio_relationships.push({ identifiers: { id: payload.userId } }); - } else if (payload.email) { - rawPayload.cio_relationships.push({ identifiers: { email: payload.email } }); - } - } else { - // any other event type except identify - const token = get(message, 'context.device.token'); - - // use this if only top level keys are to be sent - // DEVICE DELETE from CustomerIO - if (deviceDeleteRelatedEventName === evName) { - if (userId && token) { - endpoint = DEVICE_DELETE_ENDPOINT.replace(':id', userId).replace(':device_id', token); - - response.endpoint = endpoint; - response.method = 'DELETE'; - - return response; - } - throw new InstrumentationError('userId or device_token not present'); - } - - // DEVICE registration - if (isdeviceRelatedEventName(evName, destination) && userId && token) { - const devProps = message.properties || {}; - set(devProps, 'id', get(message, 'context.device.token')); - const deviceType = get(message, 'context.device.type'); - if (deviceType) { - // Ref - https://www.customer.io/docs/api/#operation/add_device - // supported platform are "ios", "android" - if (isAppleFamily(deviceType)) { - set(devProps, 'platform', 'ios'); - } else { - set(devProps, 'platform', deviceType.toLowerCase()); - } - } - set(devProps, 'last_used', Math.floor(new Date(message.originalTimestamp).getTime() / 1000)); - set(rawPayload, 'device', devProps); - requestConfig = defaultPutRequestConfig; - } else { - rawPayload.data = {}; - set(rawPayload, 'data', message.properties); - set(rawPayload, 'name', evName); - set(rawPayload, 'type', evType); - if (getFieldValueFromMessage(message, 'historicalTimestamp')) { - set( - rawPayload, - 'timestamp', - Math.floor( - new Date(getFieldValueFromMessage(message, 'historicalTimestamp')).getTime() / 1000, - ), - ); - } - } - - if (userId) { - if (isdeviceRelatedEventName(evName, destination) && token) { - endpoint = DEVICE_REGISTER_ENDPOINT.replace(':id', userId); - } else { - endpoint = USER_EVENT_ENDPOINT.replace(':id', userId); - } - } else { - endpoint = ANON_EVENT_ENDPOINT; - // CustomerIO supports 100byte of event name for anonymous users - if (messageType === EventType.SCREEN) { - // 100 - len(`Viewed Screen`) = 86 - trimmedEvName = `Viewed ${truncate(message.event || message.properties.name, 86)} Screen`; - } else { - if (!evName) { - logger.error(`Could not determine event name`); - throw new InstrumentationError(`Could not determine event name`); - } - trimmedEvName = truncate(evName, 100); - } - // anonymous_id needs to be sent for anon track calls to provide information on which anon user is being tracked - // This will help in merging for subsequent calls - const anonymousId = message.anonymousId ? message.anonymousId : undefined; - if (!anonymousId) { - throw new InstrumentationError('Anonymous id/ user id is required'); - } else { - rawPayload.anonymous_id = anonymousId; - } - set(rawPayload, 'name', trimmedEvName); - } + temporaryResponseDetails = { ...defaultResponse }; + break; } - const payload = removeUndefinedValues(rawPayload); - response.endpoint = endpoint; - response.method = requestConfig.requestMethod; + + const payload = removeUndefinedValues(temporaryResponseDetails.rawPayload); + response.endpoint = temporaryResponseDetails.endpoint; + response.method = temporaryResponseDetails.requestConfig.requestMethod; response.body.JSON = payload; return response; @@ -322,7 +135,7 @@ const batchEvents = (successRespList) => { const groupEvents = []; // Filtering out group calls to process batching successRespList.forEach((resp) => { - if (!resp.message.endpoint.includes("v2/batch")) { + if (!resp.message.endpoint.includes('v2/batch')) { batchedResponseList.push( getSuccessRespEvents(resp.message, [resp.metadata], resp.destination), ); @@ -345,7 +158,7 @@ const batchEvents = (successRespList) => { eventChunks.forEach((chunk) => { const request = defaultRequestConfig(); request.endpoint = endpoint; - request.headers = { ...headers, 'Content-Type': 'application/json' }; + request.headers = { ...headers, 'Content-Type': JSON_MIME_TYPE }; // Setting the request body to an object with a single property called "batch" containing the batched data request.body.JSON = { batch: chunk.data }; diff --git a/src/v0/destinations/customerio/util.js b/src/v0/destinations/customerio/util.js index 40d4c1b724e8..5066668063ad 100644 --- a/src/v0/destinations/customerio/util.js +++ b/src/v0/destinations/customerio/util.js @@ -1,4 +1,42 @@ +const get = require('get-value'); +const set = require('set-value'); +const truncate = require('truncate-utf8-bytes'); const { MAX_BATCH_SIZE } = require('./config'); +const logger = require('../../../logger'); +const { + constructPayload, + defaultPutRequestConfig, + defaultPostRequestConfig, + getFieldValueFromMessage, + defaultDeleteRequestConfig, + isAppleFamily, +} = require('../../util'); + +const { EventType, SpecedTraits, TraitsMapping } = require('../../../constants'); + +const { + MAPPING_CONFIG, + OBJECT_ACTIONS, + CONFIG_CATEGORIES, + IDENTITY_ENDPOINT, + MERGE_USER_ENDPOINT, + USER_EVENT_ENDPOINT, + ANON_EVENT_ENDPOINT, + OBJECT_EVENT_ENDPOINT, + DEFAULT_OBJECT_ACTION, + DEVICE_DELETE_ENDPOINT, + DEVICE_REGISTER_ENDPOINT, +} = require('./config'); + +const { InstrumentationError } = require('../../util/errorTypes'); + +const deviceRelatedEventNames = [ + 'Application Installed', + 'Application Opened', + 'Application Uninstalled', +]; + +const deviceDeleteRelatedEventName = 'Application Uninstalled'; const getSizeInBytes = (obj) => { let str = null; @@ -40,4 +78,233 @@ const getEventChunks = (groupEvents) => { return eventChunks; }; -module.exports = { getEventChunks }; +// Get the spec'd traits, for now only address needs treatment as 2 layers. +// populate the list of spec'd traits in constants.js +const populateSpecedTraits = (payload, message) => { + const pathToTraits = message.traits ? 'traits' : 'context.traits'; + SpecedTraits.forEach((trait) => { + const mapping = TraitsMapping[trait]; + const keys = Object.keys(mapping); + keys.forEach((key) => { + set(payload, key, get(message, `${pathToTraits}.${mapping[`${key}`]}`)); + }); + }); +}; + +const isdeviceRelatedEventName = (eventName, destination) => + deviceRelatedEventNames.includes(eventName) || + (destination.Config && + destination.Config.deviceTokenEventName && + destination.Config.deviceTokenEventName === eventName); + +const identifyResponseBuilder = (userId, message) => { + const rawPayload = {}; + // if userId is not there simply drop the payload + if (!userId) { + throw new InstrumentationError('userId not present'); + } + + // populate speced traits + const identityTrailts = getFieldValueFromMessage(message, 'traits') || {}; + populateSpecedTraits(rawPayload, message); + + if (Object.keys(identityTrailts).length > 0) { + const traits = Object.keys(identityTrailts); + const pathToTraits = message.traits ? 'traits' : 'context.traits'; + traits.forEach((trait) => { + // populate keys other than speced traits + // also don't send anonymousId, userId as we are setting those form the SDK and it's not actually an user property for the customer + // discard createdAt as well as we are setting the values at created_at separately + if ( + !SpecedTraits.includes(trait) && + trait !== 'createdAt' && + trait !== 'userId' && + trait !== 'anonymousId' + ) { + const dotEscapedTrait = trait.replace('.', '\\.'); + set(rawPayload, dotEscapedTrait, get(message, `${pathToTraits}.${trait}`)); + } + }); + } + + // populate user_properties (DEPRECATED) + if (message.user_properties) { + const userProps = Object.keys(message.user_properties); + userProps.forEach((prop) => { + const val = get(message, `user_properties.${prop}`); + set(rawPayload, prop, val); + }); + } + + // make user creation time + const createAt = getFieldValueFromMessage(message, 'createdAtOnly'); + // set the created_at field if traits.createAt or context.traits.createAt is passed + if (createAt) { + set(rawPayload, 'created_at', Math.floor(new Date(createAt).getTime() / 1000)); + } + + // Impportant for historical import + if (getFieldValueFromMessage(message, 'historicalTimestamp')) { + set( + rawPayload, + '_timestamp', + Math.floor( + new Date(getFieldValueFromMessage(message, 'historicalTimestamp')).getTime() / 1000, + ), + ); + } + // anonymous_id needs to be sent for identify calls to merge with any previous anon track calls + if (message && message.anonymousId) { + set(rawPayload, 'anonymous_id', message.anonymousId); + } + const endpoint = IDENTITY_ENDPOINT.replace(':id', userId); + const requestConfig = defaultPutRequestConfig; + + return { rawPayload, endpoint, requestConfig }; +}; + +const aliasResponseBuilder = (message, userId) => { + // ref : https://customer.io/docs/api/#operation/merge + if (!userId && !message.previousId) { + throw new InstrumentationError('Both userId and previousId is mandatory for merge operation'); + } + const endpoint = MERGE_USER_ENDPOINT; + const requestConfig = defaultPostRequestConfig; + const rawPayload = { + primary: { + id: userId, + }, + secondary: { + id: message.previousId, + }, + }; + + return { rawPayload, endpoint, requestConfig }; +}; + +const groupResponseBuilder = (message) => { + const payload = constructPayload(message, MAPPING_CONFIG[CONFIG_CATEGORIES.OBJECT_EVENTS.name]); + const rawPayload = { + identifiers: { + object_id: payload.object_id, + object_type_id: payload.object_type_id, + }, + type: 'object', + action: + payload.action && OBJECT_ACTIONS.includes(payload.action) + ? payload.action + : DEFAULT_OBJECT_ACTION, + attributes: payload.attributes || {}, + cio_relationships: [], + }; + if (payload.userId) { + rawPayload.cio_relationships.push({ identifiers: { id: payload.userId } }); + } else if (payload.email) { + rawPayload.cio_relationships.push({ identifiers: { email: payload.email } }); + } + const requestConfig = defaultPostRequestConfig; + const endpoint = OBJECT_EVENT_ENDPOINT; + + return { rawPayload, endpoint, requestConfig }; +}; + +const defaultResponseBuilder = (message, evName, userId, evType, destination, messageType) => { + const rawPayload = {}; + let endpoint; + let trimmedEvName; + let requestConfig = defaultPostRequestConfig; + // any other event type except identify + const token = get(message, 'context.device.token'); + + // use this if only top level keys are to be sent + // DEVICE DELETE from CustomerIO + if (deviceDeleteRelatedEventName === evName) { + if (userId && token) { + endpoint = DEVICE_DELETE_ENDPOINT.replace(':id', userId).replace(':device_id', token); + requestConfig = defaultDeleteRequestConfig; + + return { rawPayload, endpoint, requestConfig }; + } + throw new InstrumentationError('userId or device_token not present'); + } + + // DEVICE registration + if (isdeviceRelatedEventName(evName, destination) && userId && token) { + const devProps = { + ...message.properties, + id: get(message, 'context.device.token'), + last_used: Math.floor(new Date(message.originalTimestamp).getTime() / 1000), + }; + // const devProps = message.properties || {}; + // set(devProps, 'id', get(message, 'context.device.token')); + const deviceType = get(message, 'context.device.type'); + if (deviceType) { + // Ref - https://www.customer.io/docs/api/#operation/add_device + // supported platform are "ios", "android" + if (isAppleFamily(deviceType)) { + set(devProps, 'platform', 'ios'); + } else { + set(devProps, 'platform', deviceType.toLowerCase()); + } + } + // set(devProps, 'last_used', Math.floor(new Date(message.originalTimestamp).getTime() / 1000)); + set(rawPayload, 'device', devProps); + requestConfig = defaultPutRequestConfig; + } else { + rawPayload.data = {}; + set(rawPayload, 'data', message.properties); + set(rawPayload, 'name', evName); + set(rawPayload, 'type', evType); + if (getFieldValueFromMessage(message, 'historicalTimestamp')) { + set( + rawPayload, + 'timestamp', + Math.floor( + new Date(getFieldValueFromMessage(message, 'historicalTimestamp')).getTime() / 1000, + ), + ); + } + } + + if (userId) { + if (isdeviceRelatedEventName(evName, destination) && token) { + endpoint = DEVICE_REGISTER_ENDPOINT.replace(':id', userId); + } else { + endpoint = USER_EVENT_ENDPOINT.replace(':id', userId); + } + } else { + endpoint = ANON_EVENT_ENDPOINT; + // CustomerIO supports 100byte of event name for anonymous users + if (messageType === EventType.SCREEN) { + // 100 - len(`Viewed Screen`) = 86 + trimmedEvName = `Viewed ${truncate(message.event || message.properties.name, 86)} Screen`; + } else { + if (!evName) { + logger.error(`Could not determine event name`); + throw new InstrumentationError(`Could not determine event name`); + } + trimmedEvName = truncate(evName, 100); + } + // anonymous_id needs to be sent for anon track calls to provide information on which anon user is being tracked + // This will help in merging for subsequent calls + const anonymousId = message.anonymousId ? message.anonymousId : undefined; + if (!anonymousId) { + throw new InstrumentationError('Anonymous id/ user id is required'); + } else { + rawPayload.anonymous_id = anonymousId; + } + set(rawPayload, 'name', trimmedEvName); + } + + return { rawPayload, endpoint, requestConfig }; +}; + +module.exports = { + getEventChunks, + identifyResponseBuilder, + aliasResponseBuilder, + groupResponseBuilder, + defaultResponseBuilder, + populateSpecedTraits, + isdeviceRelatedEventName, +}; diff --git a/src/v0/destinations/customerio/util.test.js b/src/v0/destinations/customerio/util.test.js new file mode 100644 index 000000000000..70e200ca90cf --- /dev/null +++ b/src/v0/destinations/customerio/util.test.js @@ -0,0 +1,134 @@ +const { + isdeviceRelatedEventName, + identifyResponseBuilder, + aliasResponseBuilder, + groupResponseBuilder, +} = require('./util'); + +const getTestMessage = () => { + let message = { + anonymousId: 'anonId', + traits: { + email: 'abc@test.com', + name: 'rudder', + address: { + city: 'kolkata', + country: 'India', + }, + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + }; + return message; +}; + +const getGroupTestMessage = () => { + let message = { + groupId: 'group1', + anonymousId: 'anonId', + traits: { + objectTypeId: 'obj1', + email: 'abc@test.com', + name: 'rudder', + address: { + city: 'kolkata', + country: 'India', + }, + action: 'test', + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + }; + return message; +}; + +describe('Unit test cases for customerio isdeviceRelatedEventName', () => { + it('Device token name does not match with event name as well as allowed list', async () => { + const destination = { + Config: { + apiKey: 'ef32c3f60fb98f39ef35', + datacenterEU: true, + deviceTokenEventName: 'device_token_registered', + siteID: 'c0efdbd20b9fbe24a7e2', + }, + }; + expect(isdeviceRelatedEventName('test', destination)).toEqual(false); + }); + it('Device token matches with event name but not with allowed list', async () => { + const destination = { + Config: { + apiKey: 'ef32c3f60fb98f39ef35', + datacenterEU: true, + deviceTokenEventName: 'test', + siteID: 'c0efdbd20b9fbe24a7e2', + }, + }; + expect(isdeviceRelatedEventName('test', destination)).toEqual(true); + }); + + it('Device token does not match with event name but with allowed list', async () => { + const destination = { + Config: { + apiKey: 'ef32c3f60fb98f39ef35', + datacenterEU: true, + deviceTokenEventName: 'test', + siteID: 'c0efdbd20b9fbe24a7e2', + }, + }; + expect(isdeviceRelatedEventName('Application Installed', destination)).toEqual(true); + }); +}); + +describe('Unit test cases for customerio identifyResponseBuilder', () => { + it('Device token name does not match with event name as well as allowed list', async () => { + let expectedOutput = { + endpoint: 'https://track.customer.io/api/v1/customers/user1', + rawPayload: { + anonymous_id: 'anonId', + city: 'kolkata', + country: 'India', + created_at: 1400687660, + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + }, + requestConfig: { requestFormat: 'JSON', requestMethod: 'PUT' }, + }; + expect(identifyResponseBuilder('user1', getTestMessage())).toEqual(expectedOutput); + }); +}); + +describe('Unit test cases for customerio aliasResponseBuilder', () => { + it('Device token name does not match with event name as well as allowed list', async () => { + let expectedOutput = { + endpoint: 'https://track.customer.io/api/v1/merge_customers', + rawPayload: { primary: { id: 'user1' }, secondary: { id: undefined } }, + requestConfig: { requestFormat: 'JSON', requestMethod: 'POST' }, + }; + expect(aliasResponseBuilder(getTestMessage(), 'user1')).toEqual(expectedOutput); + }); +}); + +describe('Unit test cases for customerio groupResponseBuilder', () => { + it('Device token name does not match with event name as well as allowed list', async () => { + let expectedOutput = { + endpoint: 'https://track.customer.io/api/v2/batch', + rawPayload: { + action: 'identify', + attributes: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + objectTypeId: 'obj1', + timestamp: '2014-05-21T15:54:20Z', + }, + cio_relationships: [], + identifiers: { object_id: 'group1', object_type_id: 'obj1' }, + type: 'object', + }, + requestConfig: { requestFormat: 'JSON', requestMethod: 'POST' }, + }; + expect(groupResponseBuilder(getGroupTestMessage(), 'user1')).toEqual(expectedOutput); + }); +}); diff --git a/src/v0/destinations/delighted/transform.js b/src/v0/destinations/delighted/transform.js index 0d62d0b8c5a8..f5a2afdcaf42 100644 --- a/src/v0/destinations/delighted/transform.js +++ b/src/v0/destinations/delighted/transform.js @@ -25,6 +25,7 @@ const { ConfigurationError, NetworkInstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyResponseBuilder = (message, { Config }) => { const userId = getFieldValueFromMessage(message, 'userIdOnly'); @@ -68,7 +69,7 @@ const identifyResponseBuilder = (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.endpoint = ENDPOINT; @@ -119,7 +120,7 @@ const trackResponseBuilder = async (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.endpoint = ENDPOINT; @@ -159,7 +160,7 @@ const aliasResponseBuilder = (message, { Config }) => { response.body.JSON = payload; response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.endpoint = ENDPOINT; return response; diff --git a/src/v0/destinations/delighted/util.js b/src/v0/destinations/delighted/util.js index 4f4ec8d99742..abf598628978 100644 --- a/src/v0/destinations/delighted/util.js +++ b/src/v0/destinations/delighted/util.js @@ -8,6 +8,7 @@ const { } = require('../../util/errorTypes'); const { ENDPOINT } = require('./config'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const isValidEmail = (email) => { const re = @@ -54,7 +55,7 @@ const userValidity = async (channel, Config, userId) => { response = await axios.get(`${ENDPOINT}`, { headers: { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, params: paramsdata, }); diff --git a/src/v0/destinations/discord/transform.js b/src/v0/destinations/discord/transform.js index 21b823bcd387..4eb2f7923506 100644 --- a/src/v0/destinations/discord/transform.js +++ b/src/v0/destinations/discord/transform.js @@ -16,6 +16,7 @@ const { getWhiteListedTraits, buildDefaultTraitTemplate, } = require('../slack/util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const getEmbed = (templateInput, destination, callType) => { // building titleTemplate @@ -53,7 +54,7 @@ const buildResponse = (responseBody, destination) => { const response = defaultRequestConfig(); response.endpoint = endpoint; response.method = defaultPostRequestConfig.requestMethod; - response.headers = { 'Content-Type': 'application/json' }; + response.headers = { 'Content-Type': JSON_MIME_TYPE }; response.body.JSON = responseBody; return response; }; diff --git a/src/v0/destinations/drip/transform.js b/src/v0/destinations/drip/transform.js index efcf22c963ab..9abe3e3f7786 100644 --- a/src/v0/destinations/drip/transform.js +++ b/src/v0/destinations/drip/transform.js @@ -36,6 +36,7 @@ const { ConfigurationError, NetworkInstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const identifyResponseBuilder = async (message, { Config }) => { const id = getDestinationExternalID(message, 'dripId'); @@ -91,8 +92,7 @@ const identifyResponseBuilder = async (message, { Config }) => { keys.forEach((key) => { if ( !regex.test(key) || - (typeof customFields[key] === 'object' && - JSON.stringify(customFields[key]).length > 910) || + (typeof customFields[key] === 'object' && JSON.stringify(customFields[key]).length > 910) || customFields[key].toString().length > 1000 ) { delete customFields[key]; @@ -112,7 +112,7 @@ const identifyResponseBuilder = async (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; const campaignId = getDestinationExternalID(message, 'dripCampaignId') || Config.campaignId; @@ -190,7 +190,7 @@ const trackResponseBuilder = async (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.endpoint = `${ENDPOINT}/v3/${Config.accountId}/shopper_activity/order`; @@ -230,7 +230,7 @@ const trackResponseBuilder = async (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.endpoint = `${ENDPOINT}/v2/${Config.accountId}/events`; diff --git a/src/v0/destinations/drip/util.js b/src/v0/destinations/drip/util.js index 7359309c1093..bdc35c89d275 100644 --- a/src/v0/destinations/drip/util.js +++ b/src/v0/destinations/drip/util.js @@ -5,6 +5,7 @@ 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'); const isValidEmail = (email) => { const re = @@ -25,7 +26,7 @@ const userExists = async (Config, id) => { response = await axios.get(`${ENDPOINT}/v2/${Config.accountId}/subscribers/${id}`, { headers: { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }); if (response && response.status) { @@ -62,7 +63,7 @@ const createUpdateUser = async (finalpayload, Config, basicAuth) => { { headers: { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }, ); diff --git a/src/v0/destinations/engage/deleteUsers.js b/src/v0/destinations/engage/deleteUsers.js index 9685314a9c28..285798171435 100644 --- a/src/v0/destinations/engage/deleteUsers.js +++ b/src/v0/destinations/engage/deleteUsers.js @@ -7,6 +7,7 @@ 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'); /** * This function will help to delete the users one by one from the userAttributes array. @@ -26,7 +27,7 @@ const userDeletionHandler = async (userAttributes, config) => { const BASE_URL = 'https://api.engage.so/v1/users/uid'; const basicAuth = Buffer.from(`${publicKey}:${privateKey}`).toString('base64'); const headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; diff --git a/src/v0/destinations/engage/transform.js b/src/v0/destinations/engage/transform.js index b2eff6a58ac5..98b8bb2bb9b3 100644 --- a/src/v0/destinations/engage/transform.js +++ b/src/v0/destinations/engage/transform.js @@ -15,6 +15,9 @@ 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'; const responseBuilder = (payload, endpoint, method, Config) => { if (!payload) { @@ -25,7 +28,7 @@ const responseBuilder = (payload, endpoint, method, Config) => { // Authentication Ref : https://engage.so/docs/api/ const basicAuth = Buffer.from(`${publicKey}:${privateKey}`).toString('base64'); response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; response.body.JSON = removeUndefinedAndNullValues(payload); @@ -43,7 +46,7 @@ const identifyResponseBuilder = (message, Config) => { getDestinationExternalID(message, 'engageId') || getFieldValueFromMessage(message, 'userIdOnly'); if (!uid) { - throw new InstrumentationError('Neither externalId or userId is available.'); + throw new InstrumentationError(UID_ERROR_MSG); } const endpoint = `${ConfigCategories.IDENTIFY.endpoint.replace('uid', uid)}`; const refinedPayload = refinePayload(traits, ConfigCategories.IDENTIFY.genericFields); @@ -66,7 +69,7 @@ const trackResponseBuilder = (message, Config) => { getDestinationExternalID(message, 'engageId') || getFieldValueFromMessage(message, 'userIdOnly'); if (!uid) { - throw new InstrumentationError('Neither externalId or userId is available.'); + throw new InstrumentationError(UID_ERROR_MSG); } const endpoint = `${ConfigCategories.TRACK.endpoint.replace('uid', uid)}`; payload.properties = meta; @@ -79,7 +82,7 @@ const pageResponseBuilder = (message, Config) => { getDestinationExternalID(message, 'engageId') || getFieldValueFromMessage(message, 'userIdOnly'); if (!uid) { - throw new InstrumentationError('Neither externalId or userId is available.'); + throw new InstrumentationError(UID_ERROR_MSG); } const endpoint = `${ConfigCategories.PAGE.endpoint.replace('uid', uid)}`; diff --git a/src/v0/destinations/facebook_offline_conversions/utils.js b/src/v0/destinations/facebook_offline_conversions/utils.js index 9a406d77b1c9..819bf8056d1a 100644 --- a/src/v0/destinations/facebook_offline_conversions/utils.js +++ b/src/v0/destinations/facebook_offline_conversions/utils.js @@ -442,10 +442,11 @@ const offlineConversionResponseBuilder = (message, destination) => { const offlineConversionsPayloads = []; eventToIdsArray.forEach((eventToIds) => { const { standardEvent, eventSetIds } = eventToIds; - const obj = {}; - obj.data = getData(data, standardEvent, message, destination); - obj.eventSetIds = eventSetIds; - obj.payload = payload; + const obj = { + data: getData(data, standardEvent, message, destination), + eventSetIds, + payload, + }; offlineConversionsPayloads.push(obj); }); return offlineConversionsPayloads; diff --git a/src/v0/destinations/facebook_pixel/networkHandler.js b/src/v0/destinations/facebook_pixel/networkHandler.js index 7af1f0ab36da..b3d1ab8c5f30 100644 --- a/src/v0/destinations/facebook_pixel/networkHandler.js +++ b/src/v0/destinations/facebook_pixel/networkHandler.js @@ -115,13 +115,13 @@ const destResponseHandler = (destinationResponse) => { }; }; -const networkHandler = function () { +function networkHandler() { // The order of execution also happens in this way this.prepareProxy = prepareProxyRequest; this.proxy = proxyRequest; this.processAxiosResponse = processAxiosResponse; this.responseHandler = destResponseHandler; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/facebook_pixel/transform.js b/src/v0/destinations/facebook_pixel/transform.js index 06afd46e3d53..f0d59f57de70 100644 --- a/src/v0/destinations/facebook_pixel/transform.js +++ b/src/v0/destinations/facebook_pixel/transform.js @@ -1,5 +1,4 @@ /* eslint-disable no-param-reassign */ -const sha256 = require('sha256'); const get = require('get-value'); const moment = require('moment'); const stats = require('../../../util/stats'); @@ -13,232 +12,25 @@ const { EventType } = require('../../../constants'); const { constructPayload, - defaultPostRequestConfig, - defaultRequestConfig, extractCustomFields, flattenJson, getIntegrationsObj, - isObject, getValidDynamicFormConfig, simpleProcessRouterDest, } = require('../../util'); const { - deduceFbcParam, - formatRevenue, - getContentType, transformedPayloadData, getActionSource, + fetchUserData, + handleProduct, + handleSearch, + handleProductListViewed, + handleOrder, + formingFinalResponse, } = require('./utils'); -const { - InstrumentationError, - ConfigurationError, - TransformationError, -} = require('../../util/errorTypes'); - -/** - * This method gets content category with proper error-handling - * - * @param {*} category - * @returns The content category as a string - */ -const getContentCategory = (category) => { - let contentCategory = category; - if (Array.isArray(contentCategory)) { - contentCategory = contentCategory.map(String).join(','); - } - if ( - contentCategory && - typeof contentCategory !== 'string' && - typeof contentCategory !== 'object' - ) { - contentCategory = String(contentCategory); - } - if ( - contentCategory && - typeof contentCategory !== 'string' && - !Array.isArray(contentCategory) && - typeof contentCategory === 'object' - ) { - throw new InstrumentationError("'properties.category' must be either be a string or an array"); - } - return contentCategory; -}; - -/** - * - * @param {*} message Rudder element - * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] - * - * Handles order completed and checkout started types of specific events - */ -const handleOrder = (message, categoryToContent) => { - const { products, revenue } = message.properties; - const value = formatRevenue(revenue); - - const contentType = getContentType(message, 'product', categoryToContent); - const contentIds = []; - const contents = []; - const { category, quantity, price, currency, contentName } = message.properties; - if (products) { - if (products.length > 0 && Array.isArray(products)) { - products.forEach((singleProduct) => { - const pId = singleProduct.product_id || singleProduct.sku || singleProduct.id; - if (pId) { - contentIds.push(pId); - // required field for content - // ref: https://developers.facebook.com/docs/meta-pixel/reference#object-properties - const content = { - id: pId, - quantity: singleProduct.quantity || quantity || 1, - item_price: singleProduct.price || price, - }; - contents.push(content); - } - }); - } else { - throw new InstrumentationError("'properties.products' is not sent as an Array"); - } - } - - return { - content_category: getContentCategory(category), - content_ids: contentIds, - content_type: contentType, - currency: currency || 'USD', - value, - contents, - num_items: contentIds.length, - content_name: contentName, - }; -}; - -/** - * - * @param {*} message Rudder element - * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] - * - * Handles product list viewed - */ -const handleProductListViewed = (message, categoryToContent) => { - let contentType; - const contentIds = []; - const contents = []; - const { products, category, quantity, value, contentName } = message.properties; - if (products && products.length > 0 && Array.isArray(products)) { - products.forEach((product, index) => { - if (isObject(product)) { - const productId = product.product_id || product.sku || product.id; - if (productId) { - contentIds.push(productId); - contents.push({ - id: productId, - quantity: product.quantity || quantity || 1, - item_price: product.price, - }); - } - } else { - throw new InstrumentationError(`'properties.products[${index}]' is not an object`); - } - }); - } - - if (contentIds.length > 0) { - contentType = 'product'; - // for viewContent event content_ids and content arrays are not mandatory - } else if (category) { - contentIds.push(category); - contents.push({ - id: category, - quantity: 1, - }); - contentType = 'product_group'; - } - - return { - content_ids: contentIds, - content_type: getContentType(message, contentType, categoryToContent), - contents, - content_category: getContentCategory(category), - content_name: contentName, - value: formatRevenue(value), - }; -}; - -/** - * - * @param {*} message Rudder Payload - * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] - * @param {*} valueFieldIdentifier it can be either value or price which will be matched from properties and assigned to value for fb payload - */ -const handleProduct = (message, categoryToContent, valueFieldIdentifier) => { - const contentIds = []; - const contents = []; - const useValue = valueFieldIdentifier === 'properties.value'; - const contentId = - message.properties?.product_id || message.properties?.sku || message.properties?.id; - const contentType = getContentType(message, 'product', categoryToContent); - const contentName = message.properties.product_name || message.properties.name || ''; - const contentCategory = message.properties.category || ''; - const currency = message.properties.currency || 'USD'; - const value = useValue - ? formatRevenue(message.properties.value) - : formatRevenue(message.properties.price); - if (contentId) { - contentIds.push(contentId); - contents.push({ - id: contentId, - quantity: message.properties.quantity || 1, - item_price: message.properties.price, - }); - } - return { - content_ids: contentIds, - content_type: contentType, - content_name: contentName, - content_category: getContentCategory(contentCategory), - currency, - value, - contents, - }; -}; - -const handleSearch = (message) => { - const query = message?.properties?.query; - /** - * Facebook Pixel states "search_string" a string type - * ref: https://developers.facebook.com/docs/meta-pixel/reference#:~:text=an%20exact%20value.-,search_string,-String - * But it accepts "number" and "boolean" types. So, we are also doing the same by accepting "number" and "boolean" - * and throwing an error if "Object" or other types are being sent. - */ - const validQueryType = ['string', 'number', 'boolean']; - if (query && !validQueryType.includes(typeof query)) { - throw new InstrumentationError("'query' should be in string format only"); - } - - const contentIds = []; - const contents = []; - const contentId = - message.properties?.product_id || message.properties?.sku || message.properties?.id; - const contentCategory = message?.properties?.category || ''; - const value = message?.properties?.value; - if (contentId) { - contentIds.push(contentId); - contents.push({ - id: contentId, - quantity: message?.properties?.quantity || 1, - item_price: message?.properties?.price, - }); - } - return { - content_ids: contentIds, - content_category: getContentCategory(contentCategory), - value: formatRevenue(value), - contents, - search_string: query, - }; -}; +const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const responseBuilderSimple = (message, category, destination, categoryToContent) => { const { Config } = destination; @@ -257,24 +49,7 @@ const responseBuilderSimple = (message, category, destination, categoryToContent const endpoint = `https://graph.facebook.com/v16.0/${pixelId}/events?access_token=${accessToken}`; - const userData = constructPayload( - message, - MAPPING_CONFIG[CONFIG_CATEGORIES.USERDATA.name], - 'fb_pixel', - ); - const { removeExternalId } = Config; - if (removeExternalId) { - delete userData.external_id; - } - if (userData) { - const split = userData.name ? userData.name.split(' ') : null; - if (split !== null && Array.isArray(split) && split.length === 2) { - userData.fn = integrationsObj && integrationsObj.hashed ? split[0] : sha256(split[0]); - userData.ln = integrationsObj && integrationsObj.hashed ? split[1] : sha256(split[1]); - } - delete userData.name; - userData.fbc = userData.fbc || deduceFbcParam(message); - } + const userData = fetchUserData(message, Config); let customData = {}; let commonData = {}; @@ -397,30 +172,66 @@ const responseBuilderSimple = (message, category, destination, categoryToContent // content_category should only be a string ref: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data - if (userData && commonData) { - const response = defaultRequestConfig(); - response.endpoint = endpoint; - response.method = defaultPostRequestConfig.requestMethod; - const jsonStringify = JSON.stringify({ - user_data: userData, - ...commonData, - custom_data: customData, - }); - const payload = { - data: [jsonStringify], - }; + return formingFinalResponse( + userData, + commonData, + customData, + endpoint, + testDestination, + testEventCode, + ); +}; - // Ref: https://developers.facebook.com/docs/marketing-api/conversions-api/using-the-api/ - // Section: Test Events Tool - if (testDestination) { - payload.test_event_code = testEventCode; - } - response.body.FORM = payload; - return response; +function getCategoryFromEvent(checkEvent) { + let category; + switch (checkEvent) { + case CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED.type: + case 'ViewContent': + category = CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED; + break; + case CONFIG_CATEGORIES.PRODUCT_VIEWED.type: + category = CONFIG_CATEGORIES.PRODUCT_VIEWED; + break; + case CONFIG_CATEGORIES.PRODUCT_ADDED.type: + case 'AddToCart': + category = CONFIG_CATEGORIES.PRODUCT_ADDED; + break; + case CONFIG_CATEGORIES.ORDER_COMPLETED.type: + case 'Purchase': + category = CONFIG_CATEGORIES.ORDER_COMPLETED; + break; + case CONFIG_CATEGORIES.PRODUCTS_SEARCHED.type: + case 'Search': + category = CONFIG_CATEGORIES.PRODUCTS_SEARCHED; + break; + case CONFIG_CATEGORIES.CHECKOUT_STARTED.type: + case 'InitiateCheckout': + category = CONFIG_CATEGORIES.CHECKOUT_STARTED; + break; + case 'AddToWishlist': + case 'AddPaymentInfo': + case 'Lead': + case 'CompleteRegistration': + case 'Contact': + case 'CustomizeProduct': + case 'Donate': + case 'FindLocation': + case 'Schedule': + case 'StartTrial': + case 'SubmitApplication': + case 'Subscribe': + category = CONFIG_CATEGORIES.OTHER_STANDARD; + category.event = checkEvent; + break; + case 'PageView': + category = CONFIG_CATEGORIES.PAGE_VIEW; + break; + default: + category = CONFIG_CATEGORIES.SIMPLE_TRACK; + break; } - // fail-safety for developer error - throw new TransformationError('Payload could not be constructed'); -}; + return category; +} const processEvent = (message, destination) => { if (!message.type) { @@ -502,52 +313,7 @@ const processEvent = (message, destination) => { } checkEvent = standardTo !== '' ? standardTo : message.event.toLowerCase(); - switch (checkEvent) { - case CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED.type: - case 'ViewContent': - category = CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED; - break; - case CONFIG_CATEGORIES.PRODUCT_VIEWED.type: - category = CONFIG_CATEGORIES.PRODUCT_VIEWED; - break; - case CONFIG_CATEGORIES.PRODUCT_ADDED.type: - case 'AddToCart': - category = CONFIG_CATEGORIES.PRODUCT_ADDED; - break; - case CONFIG_CATEGORIES.ORDER_COMPLETED.type: - case 'Purchase': - category = CONFIG_CATEGORIES.ORDER_COMPLETED; - break; - case CONFIG_CATEGORIES.PRODUCTS_SEARCHED.type: - case 'Search': - category = CONFIG_CATEGORIES.PRODUCTS_SEARCHED; - break; - case CONFIG_CATEGORIES.CHECKOUT_STARTED.type: - case 'InitiateCheckout': - category = CONFIG_CATEGORIES.CHECKOUT_STARTED; - break; - case 'AddToWishlist': - case 'AddPaymentInfo': - case 'Lead': - case 'CompleteRegistration': - case 'Contact': - case 'CustomizeProduct': - case 'Donate': - case 'FindLocation': - case 'Schedule': - case 'StartTrial': - case 'SubmitApplication': - case 'Subscribe': - category = CONFIG_CATEGORIES.OTHER_STANDARD; - category.event = checkEvent; - break; - case 'PageView': - category = CONFIG_CATEGORIES.PAGE_VIEW; - break; - default: - category = CONFIG_CATEGORIES.SIMPLE_TRACK; - break; - } + category = getCategoryFromEvent(checkEvent); break; default: throw new InstrumentationError(`Message type ${messageType} not supported`); @@ -563,4 +329,11 @@ const processRouterDest = async (inputs, reqMetadata) => { return respList; }; -module.exports = { process, processRouterDest, handleSearch }; +module.exports = { + process, + processRouterDest, + handleSearch, + handleProductListViewed, + handleProduct, + handleOrder, +}; diff --git a/src/v0/destinations/facebook_pixel/transform.test.js b/src/v0/destinations/facebook_pixel/transform.test.js index 7ed07c38d37a..25332d770c70 100644 --- a/src/v0/destinations/facebook_pixel/transform.test.js +++ b/src/v0/destinations/facebook_pixel/transform.test.js @@ -1,4 +1,9 @@ -const { handleSearch } = require('../../../../src/v0/destinations/facebook_pixel/transform'); +const { + handleSearch, + handleProductListViewed, + handleProduct, + handleOrder, +} = require('../../../../src/v0/destinations/facebook_pixel/transform'); const getTestMessage = () => { let message = { @@ -19,6 +24,16 @@ const getTestMessage = () => { return message; }; +const getTestCategoryToContent = () => { + let categoryToContent = [ + { + from: 'spin_result', + to: 'Schedule', + }, + ]; + return categoryToContent; +}; + describe('Unit test cases for facebook_pixel handle search', () => { it('should return content with all fields not null', async () => { const expectedOutput = { @@ -71,3 +86,116 @@ describe('Unit test cases for facebook_pixel handle search', () => { expect(handleSearch(message)).toEqual(expectedOutput); }); }); + +describe('Unit test cases for facebook_pixel handleProductListViewed', () => { + it('without product array', () => { + let expectedOutput = { + content_category: 'clothing', + content_ids: ['clothing'], + content_name: undefined, + content_type: 'product_group', + contents: [{ id: 'clothing', quantity: 1 }], + value: 30, + }; + expect(handleProductListViewed(getTestMessage(), getTestCategoryToContent())).toEqual( + expectedOutput, + ); + }); + + it('with product array', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [{ id: 'clothing', quantity: 2 }]; + let expectedOutput = { + content_category: 'clothing', + content_ids: ['clothing'], + content_name: undefined, + content_type: 'product', + contents: [{ id: 'clothing', item_price: undefined, quantity: 2 }], + value: 30, + }; + expect(handleProductListViewed(fittingPayload, getTestCategoryToContent())).toEqual( + expectedOutput, + ); + }); +}); + +describe('Unit test cases for facebook_pixel handleProduct', () => { + it('with valueFieldIdentifier properties.value', () => { + let expectedOutput = { + content_category: 'clothing', + content_ids: ['p-298'], + content_name: 'my product 1', + content_type: 'product', + contents: [{ id: 'p-298', item_price: 24.75, quantity: 1 }], + currency: 'CAD', + value: 30, + }; + expect(handleProduct(getTestMessage(), getTestCategoryToContent(), 'properties.value')).toEqual( + expectedOutput, + ); + }); + + it('with valueFieldIdentifier properties.price', () => { + let expectedOutput = { + content_category: 'clothing', + content_ids: ['p-298'], + content_name: 'my product 1', + content_type: 'product', + contents: [{ id: 'p-298', item_price: 24.75, quantity: 1 }], + currency: 'CAD', + value: 24.75, + }; + expect(handleProduct(getTestMessage(), getTestCategoryToContent(), 'properties.price')).toEqual( + expectedOutput, + ); + }); +}); + +describe('Unit test cases for facebook_pixel handleOrder', () => { + it('without product array', () => { + let expectedOutput = { + content_category: 'clothing', + content_ids: [], + content_name: undefined, + content_type: 'product', + contents: [], + currency: 'CAD', + num_items: 0, + value: 0, + }; + expect(handleOrder(getTestMessage(), getTestCategoryToContent())).toEqual(expectedOutput); + }); + + it('with product array without revenue', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [{ id: 'clothing', quantity: 2 }]; + let expectedOutput = { + content_category: 'clothing', + content_ids: ['clothing'], + content_name: undefined, + content_type: 'product', + contents: [{ id: 'clothing', item_price: 24.75, quantity: 2 }], + currency: 'CAD', + num_items: 1, + value: 0, + }; + expect(handleOrder(fittingPayload, getTestCategoryToContent())).toEqual(expectedOutput); + }); + + it('with product array with revenue', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [{ id: 'clothing', quantity: 2 }]; + fittingPayload.properties.revenue = 124; + let expectedOutput = { + content_category: 'clothing', + content_ids: ['clothing'], + content_name: undefined, + content_type: 'product', + contents: [{ id: 'clothing', item_price: 24.75, quantity: 2 }], + currency: 'CAD', + num_items: 1, + value: 124, + }; + expect(handleOrder(fittingPayload, getTestCategoryToContent())).toEqual(expectedOutput); + }); +}); diff --git a/src/v0/destinations/facebook_pixel/utils.js b/src/v0/destinations/facebook_pixel/utils.js index c8852df67690..a3a61df472b5 100644 --- a/src/v0/destinations/facebook_pixel/utils.js +++ b/src/v0/destinations/facebook_pixel/utils.js @@ -1,7 +1,16 @@ const sha256 = require('sha256'); -const { isObject, getFieldValueFromMessage, formatTimeStamp, getIntegrationsObj } = require('../../util'); -const { ACTION_SOURCES_VALUES } = require('./config'); -const { InstrumentationError } = require('../../util/errorTypes'); +const { + isObject, + getFieldValueFromMessage, + formatTimeStamp, + getIntegrationsObj, + constructPayload, + defaultPostRequestConfig, + defaultRequestConfig, +} = require('../../util'); +const { ACTION_SOURCES_VALUES, CONFIG_CATEGORIES, MAPPING_CONFIG } = require('./config'); + +const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); /** format revenue according to fb standards with max two decimal places. * @param revenue @@ -28,10 +37,11 @@ const formatRevenue = (revenue) => { * - https://developers.facebook.com/docs/facebook-pixel/reference/#object-properties */ const getContentType = (message, defaultValue, categoryToContent) => { + let tempCategoryToContent = categoryToContent; const { properties } = message; const integrationsObj = getIntegrationsObj(message, 'fb_pixel'); - if(integrationsObj?.contentType){ + if (integrationsObj?.contentType) { return integrationsObj.contentType; } @@ -42,15 +52,16 @@ const getContentType = (message, defaultValue, categoryToContent) => { category = products[0].category; } } else { - if (categoryToContent === undefined) { - categoryToContent = []; + if (tempCategoryToContent === undefined) { + tempCategoryToContent = []; } - const mapped = categoryToContent; + const mapped = tempCategoryToContent; const mappedTo = mapped.reduce((filtered, map) => { + let filter = filtered; if (map.from === category) { - filtered = map.to; + filter = map.to; } - return filtered; + return filter; }, ''); if (mappedTo.length > 0) { return mappedTo; @@ -141,52 +152,53 @@ const transformedPayloadData = ( 'postalCode', 'birthday', ]; - blacklistPiiProperties = blacklistPiiProperties || []; - whitelistPiiProperties = whitelistPiiProperties || []; - eventCustomProperties = eventCustomProperties || []; + const clonedCustomData = { ...customData }; + const finalBlacklistPiiProperties = blacklistPiiProperties || []; + const finalWhitelistPiiProperties = whitelistPiiProperties || []; + const finalEventCustomProperties = eventCustomProperties || []; const customBlackListedPiiProperties = {}; const customWhiteListedProperties = {}; const customEventProperties = {}; - blacklistPiiProperties.forEach((property) => { + finalBlacklistPiiProperties.forEach((property) => { const singularConfigInstance = property; customBlackListedPiiProperties[singularConfigInstance.blacklistPiiProperties] = singularConfigInstance.blacklistPiiHash; }); - whitelistPiiProperties.forEach((property) => { + finalWhitelistPiiProperties.forEach((property) => { const singularConfigInstance = property; customWhiteListedProperties[singularConfigInstance.whitelistPiiProperties] = true; }); - eventCustomProperties.forEach((property) => { + finalEventCustomProperties.forEach((property) => { const singularConfigInstance = property; customEventProperties[singularConfigInstance.eventCustomProperties] = true; }); - Object.keys(customData).forEach((eventProp) => { + Object.keys(clonedCustomData).forEach((eventProp) => { const isDefaultPiiProperty = defaultPiiProperties.includes(eventProp); const isProperyWhiteListed = customWhiteListedProperties[eventProp] || false; if (isDefaultPiiProperty && !isProperyWhiteListed) { - delete customData[eventProp]; + delete clonedCustomData[eventProp]; } if (Object.prototype.hasOwnProperty.call(customBlackListedPiiProperties, eventProp)) { if (customBlackListedPiiProperties[eventProp]) { - customData[eventProp] = + clonedCustomData[eventProp] = integrationsObj && integrationsObj.hashed ? String(message.properties[eventProp]) : sha256(String(message.properties[eventProp])); } else { - delete customData[eventProp]; + delete clonedCustomData[eventProp]; } } const isCustomProperty = customEventProperties[eventProp] || false; if (isStandard && !isCustomProperty && !isDefaultPiiProperty) { - delete customData[eventProp]; + delete clonedCustomData[eventProp]; } }); - return customData; + return clonedCustomData; }; /** @@ -249,10 +261,275 @@ const getActionSource = (payload, channel) => { return actionSource; }; +/** + * This method gets content category with proper error-handling + * + * @param {*} category + * @returns The content category as a string + */ +const getContentCategory = (category) => { + let contentCategory = category; + if (Array.isArray(contentCategory)) { + contentCategory = contentCategory.map(String).join(','); + } + if ( + contentCategory && + typeof contentCategory !== 'string' && + typeof contentCategory !== 'object' + ) { + contentCategory = String(contentCategory); + } + if ( + contentCategory && + typeof contentCategory !== 'string' && + !Array.isArray(contentCategory) && + typeof contentCategory === 'object' + ) { + throw new InstrumentationError("'properties.category' must be either be a string or an array"); + } + return contentCategory; +}; + +const fetchUserData = (message, Config) => { + const integrationsObj = getIntegrationsObj(message, 'fb_pixel'); + const userData = constructPayload( + message, + MAPPING_CONFIG[CONFIG_CATEGORIES.USERDATA.name], + 'fb_pixel', + ); + const { removeExternalId } = Config; + if (removeExternalId) { + delete userData.external_id; + } + if (userData) { + const split = userData.name ? userData.name.split(' ') : null; + if (split !== null && Array.isArray(split) && split.length === 2) { + userData.fn = integrationsObj && integrationsObj.hashed ? split[0] : sha256(split[0]); + userData.ln = integrationsObj && integrationsObj.hashed ? split[1] : sha256(split[1]); + } + delete userData.name; + userData.fbc = userData.fbc || deduceFbcParam(message); + } + return userData; +}; + +/** + * + * @param {*} message Rudder element + * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] + * + * Handles order completed and checkout started types of specific events + */ +const handleOrder = (message, categoryToContent) => { + const { products, revenue } = message.properties; + const value = formatRevenue(revenue); + + const contentType = getContentType(message, 'product', categoryToContent); + const contentIds = []; + const contents = []; + const { category, quantity, price, currency, contentName } = message.properties; + if (products) { + if (products.length > 0 && Array.isArray(products)) { + products.forEach((singleProduct) => { + const pId = singleProduct.product_id || singleProduct.sku || singleProduct.id; + if (pId) { + contentIds.push(pId); + // required field for content + // ref: https://developers.facebook.com/docs/meta-pixel/reference#object-properties + const content = { + id: pId, + quantity: singleProduct.quantity || quantity || 1, + item_price: singleProduct.price || price, + }; + contents.push(content); + } + }); + } else { + throw new InstrumentationError("'properties.products' is not sent as an Array"); + } + } + + return { + content_category: getContentCategory(category), + content_ids: contentIds, + content_type: contentType, + currency: currency || 'USD', + value, + contents, + num_items: contentIds.length, + content_name: contentName, + }; +}; + +/** + * + * @param {*} message Rudder element + * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] + * + * Handles product list viewed + */ +const handleProductListViewed = (message, categoryToContent) => { + let contentType; + const contentIds = []; + const contents = []; + const { products, category, quantity, value, contentName } = message.properties; + if (products && products.length > 0 && Array.isArray(products)) { + products.forEach((product, index) => { + if (isObject(product)) { + const productId = product.product_id || product.sku || product.id; + if (productId) { + contentIds.push(productId); + contents.push({ + id: productId, + quantity: product.quantity || quantity || 1, + item_price: product.price, + }); + } + } else { + throw new InstrumentationError(`'properties.products[${index}]' is not an object`); + } + }); + } + + if (contentIds.length > 0) { + contentType = 'product'; + // for viewContent event content_ids and content arrays are not mandatory + } else if (category) { + contentIds.push(category); + contents.push({ + id: category, + quantity: 1, + }); + contentType = 'product_group'; + } + + return { + content_ids: contentIds, + content_type: getContentType(message, contentType, categoryToContent), + contents, + content_category: getContentCategory(category), + content_name: contentName, + value: formatRevenue(value), + }; +}; + +/** + * + * @param {*} message Rudder Payload + * @param {*} categoryToContent [ { from: 'clothing', to: 'product' } ] + * @param {*} valueFieldIdentifier it can be either value or price which will be matched from properties and assigned to value for fb payload + */ +const handleProduct = (message, categoryToContent, valueFieldIdentifier) => { + const contentIds = []; + const contents = []; + const useValue = valueFieldIdentifier === 'properties.value'; + const contentId = + message.properties?.product_id || message.properties?.sku || message.properties?.id; + const contentType = getContentType(message, 'product', categoryToContent); + const contentName = message.properties.product_name || message.properties.name || ''; + const contentCategory = message.properties.category || ''; + const currency = message.properties.currency || 'USD'; + const value = useValue + ? formatRevenue(message.properties.value) + : formatRevenue(message.properties.price); + if (contentId) { + contentIds.push(contentId); + contents.push({ + id: contentId, + quantity: message.properties.quantity || 1, + item_price: message.properties.price, + }); + } + return { + content_ids: contentIds, + content_type: contentType, + content_name: contentName, + content_category: getContentCategory(contentCategory), + currency, + value, + contents, + }; +}; + +const handleSearch = (message) => { + const query = message?.properties?.query; + /** + * Facebook Pixel states "search_string" a string type + * ref: https://developers.facebook.com/docs/meta-pixel/reference#:~:text=an%20exact%20value.-,search_string,-String + * But it accepts "number" and "boolean" types. So, we are also doing the same by accepting "number" and "boolean" + * and throwing an error if "Object" or other types are being sent. + */ + const validQueryType = ['string', 'number', 'boolean']; + if (query && !validQueryType.includes(typeof query)) { + throw new InstrumentationError("'query' should be in string format only"); + } + + const contentIds = []; + const contents = []; + const contentId = + message.properties?.product_id || message.properties?.sku || message.properties?.id; + const contentCategory = message?.properties?.category || ''; + const value = message?.properties?.value; + if (contentId) { + contentIds.push(contentId); + contents.push({ + id: contentId, + quantity: message?.properties?.quantity || 1, + item_price: message?.properties?.price, + }); + } + return { + content_ids: contentIds, + content_category: getContentCategory(contentCategory), + value: formatRevenue(value), + contents, + search_string: query, + }; +}; + +const formingFinalResponse = ( + userData, + commonData, + customData, + endpoint, + testDestination, + testEventCode, +) => { + if (userData && commonData) { + const response = defaultRequestConfig(); + response.endpoint = endpoint; + response.method = defaultPostRequestConfig.requestMethod; + const jsonStringify = JSON.stringify({ + user_data: userData, + ...commonData, + custom_data: customData, + }); + const payload = { + data: [jsonStringify], + }; + + // Ref: https://developers.facebook.com/docs/marketing-api/conversions-api/using-the-api/ + // Section: Test Events Tool + if (testDestination) { + payload.test_event_code = testEventCode; + } + response.body.FORM = payload; + return response; + } + // fail-safety for developer error + throw new TransformationError('Payload could not be constructed'); +}; + module.exports = { deduceFbcParam, formatRevenue, getContentType, transformedPayloadData, getActionSource, + fetchUserData, + handleProduct, + handleSearch, + handleProductListViewed, + handleOrder, + formingFinalResponse, }; diff --git a/src/v0/destinations/factorsai/transform.js b/src/v0/destinations/factorsai/transform.js index 9a7b57b0a6ef..eec9baa819c2 100644 --- a/src/v0/destinations/factorsai/transform.js +++ b/src/v0/destinations/factorsai/transform.js @@ -8,6 +8,7 @@ const { defaultPostRequestConfig, simpleProcessRouterDest, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategories, mappingConfig, BASE_URL } = require('./config'); @@ -18,7 +19,7 @@ function buildResponse(payload, factorsAIApiKey) { const apiKey = Buffer.from(`${factorsAIApiKey}:`).toString('base64'); response.endpoint = BASE_URL; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${apiKey}`, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/fb/transform.js b/src/v0/destinations/fb/transform.js index 8dcb37f42b98..c546a4cf6780 100644 --- a/src/v0/destinations/fb/transform.js +++ b/src/v0/destinations/fb/transform.js @@ -65,14 +65,15 @@ const eventAndPropRegexPattern = '^[0-9a-zA-Z_][0-9a-zA-Z _-]{0,39}$'; const eventAndPropRegex = new RegExp(eventAndPropRegexPattern); function sanityCheckPayloadForTypesAndModifications(updatedEvent) { + const clonedUpdatedEvent = { ...updatedEvent }; // Conversion required fields - const dateTime = new Date(get(updatedEvent.custom_events[0], '_logTime')); - set(updatedEvent.custom_events[0], '_logTime', dateTime.getTime()); + const dateTime = new Date(get(clonedUpdatedEvent.custom_events[0], '_logTime')); + set(clonedUpdatedEvent.custom_events[0], '_logTime', dateTime.getTime()); - let num = Number(updatedEvent.advertiser_tracking_enabled); - updatedEvent.advertiser_tracking_enabled = Number.isNaN(num) ? '0' : `${num}`; - num = Number(updatedEvent.application_tracking_enabled); - updatedEvent.application_tracking_enabled = Number.isNaN(num) ? '0' : `${num}`; + let num = Number(clonedUpdatedEvent.advertiser_tracking_enabled); + clonedUpdatedEvent.advertiser_tracking_enabled = Number.isNaN(num) ? '0' : `${num}`; + num = Number(clonedUpdatedEvent.application_tracking_enabled); + clonedUpdatedEvent.application_tracking_enabled = Number.isNaN(num) ? '0' : `${num}`; let isUDSet = false; userProps.forEach((prop) => { @@ -82,40 +83,44 @@ function sanityCheckPayloadForTypesAndModifications(updatedEvent) { case 'ud[ln]': case 'ud[st]': case 'ud[cn]': - if (updatedEvent[prop] && updatedEvent[prop] !== '') { + if (clonedUpdatedEvent[prop] && clonedUpdatedEvent[prop] !== '') { isUDSet = true; - updatedEvent[prop] = sha256(updatedEvent[prop].toLowerCase()); + clonedUpdatedEvent[prop] = sha256(clonedUpdatedEvent[prop].toLowerCase()); } break; case 'ud[zp]': case 'ud[ph]': - if (updatedEvent[prop] && updatedEvent[prop] !== '') { + if (clonedUpdatedEvent[prop] && clonedUpdatedEvent[prop] !== '') { isUDSet = true; // remove all non-numerical characters - let processedVal = updatedEvent[prop].replace(/\D/g, ''); + let processedVal = clonedUpdatedEvent[prop].replace(/\D/g, ''); // remove all leading zeros processedVal = processedVal.replace(/^0+/g, ''); if (processedVal.length > 0) { - updatedEvent[prop] = sha256(processedVal); + clonedUpdatedEvent[prop] = sha256(processedVal); } } break; case 'ud[ge]': - if (updatedEvent[prop] && updatedEvent[prop] !== '') { + if (clonedUpdatedEvent[prop] && clonedUpdatedEvent[prop] !== '') { isUDSet = true; - updatedEvent[prop] = sha256(updatedEvent[prop].toLowerCase() === 'female' ? 'f' : 'm'); + clonedUpdatedEvent[prop] = sha256( + clonedUpdatedEvent[prop].toLowerCase() === 'female' ? 'f' : 'm', + ); } break; case 'ud[db]': - if (updatedEvent[prop] && updatedEvent[prop] !== '') { + if (clonedUpdatedEvent[prop] && clonedUpdatedEvent[prop] !== '') { isUDSet = true; - updatedEvent[prop] = sha256(getDateInFormat(updatedEvent[prop])); + clonedUpdatedEvent[prop] = sha256(getDateInFormat(clonedUpdatedEvent[prop])); } break; case 'ud[ct]': - if (updatedEvent[prop] && updatedEvent[prop] !== '') { + if (clonedUpdatedEvent[prop] && clonedUpdatedEvent[prop] !== '') { isUDSet = true; - updatedEvent[prop] = sha256(updatedEvent[prop].toLowerCase().replace(/ /g, '')); + clonedUpdatedEvent[prop] = sha256( + clonedUpdatedEvent[prop].toLowerCase().replace(/ /g, ''), + ); } break; default: @@ -124,26 +129,28 @@ function sanityCheckPayloadForTypesAndModifications(updatedEvent) { }); // remove anon_id if user data or advertiser_id present - if (isUDSet || updatedEvent.advertiser_id) { - delete updatedEvent.anon_id; + if (isUDSet || clonedUpdatedEvent.advertiser_id) { + delete clonedUpdatedEvent.anon_id; } - if (!isUDSet && !updatedEvent.advertiser_id && !updatedEvent.anon_id) { + if (!isUDSet && !clonedUpdatedEvent.advertiser_id && !clonedUpdatedEvent.anon_id) { throw new InstrumentationError( 'Either context.device.advertisingId or traits or anonymousId must be present for all events', ); } - if (updatedEvent.custom_events) { - updatedEvent.custom_events = JSON.stringify(updatedEvent.custom_events); + if (clonedUpdatedEvent.custom_events) { + clonedUpdatedEvent.custom_events = JSON.stringify(clonedUpdatedEvent.custom_events); } - if (updatedEvent.extinfo) { - updatedEvent.extinfo = JSON.stringify(updatedEvent.extinfo); + if (clonedUpdatedEvent.extinfo) { + clonedUpdatedEvent.extinfo = JSON.stringify(clonedUpdatedEvent.extinfo); } // Event type required by fb - updatedEvent.event = 'CUSTOM_APP_EVENTS'; + clonedUpdatedEvent.event = 'CUSTOM_APP_EVENTS'; + + return clonedUpdatedEvent; } function getCorrectedTypedValue(pathToKey, value, originalPath) { @@ -251,9 +258,10 @@ function responseBuilderSimple(message, payload, destination) { } function buildBaseEvent(message) { - const baseEvent = {}; - baseEvent.extinfo = Array.from(extInfoArray); - baseEvent.custom_events = [{}]; + const baseEvent = { + extinfo: Array.from(extInfoArray), + custom_events: [{}], + }; let sourceSDK = get(message, 'context.device.type') || ''; sourceSDK = sourceSDK.toLowerCase(); @@ -290,9 +298,9 @@ function buildBaseEvent(message) { baseEvent.extinfo[extInfoIdx] = outputVal || baseEvent.extinfo[extInfoIdx]; } else if (splits.length === 3) { // custom event key - set(baseEvent.custom_events[0], splits[2], inputVal || ''); + set(baseEvent.custom_events[0], splits[2], inputVal); } else { - set(baseEvent, destKey, inputVal || ''); + set(baseEvent, destKey, inputVal); } } }); @@ -340,7 +348,7 @@ function processSingleMessage(message, destination) { throw new InstrumentationError(`Message type ${message.type} not supported`); } - sanityCheckPayloadForTypesAndModifications(updatedEvent); + updatedEvent = sanityCheckPayloadForTypesAndModifications(updatedEvent); return responseBuilderSimple(message, updatedEvent, destination); } diff --git a/src/v0/destinations/fb_custom_audience/config.js b/src/v0/destinations/fb_custom_audience/config.js index ef86a9a56ff6..6d498c1eb7fb 100644 --- a/src/v0/destinations/fb_custom_audience/config.js +++ b/src/v0/destinations/fb_custom_audience/config.js @@ -96,7 +96,7 @@ const USER_DELETE = 'remove'; /* 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 +const maxPayloadSize = 60000; // bytes module.exports = { getEndPoint, schemaFields, @@ -104,5 +104,5 @@ module.exports = { USER_DELETE, typeFields, subTypeFields, - maxPayloadSize + maxPayloadSize, }; diff --git a/src/v0/destinations/fb_custom_audience/transform.js b/src/v0/destinations/fb_custom_audience/transform.js index 2d1628850e4a..38c20645768f 100644 --- a/src/v0/destinations/fb_custom_audience/transform.js +++ b/src/v0/destinations/fb_custom_audience/transform.js @@ -11,7 +11,11 @@ const { simpleProcessRouterDest, getDestinationExternalIDInfoForRetl, } = require('../../util'); -const { prepareDataField, getSchemaForEventMappedToDest, batchingWithPayloadSize } = require('./util'); +const { + prepareDataField, + getSchemaForEventMappedToDest, + batchingWithPayloadSize, +} = require('./util'); const { getEndPoint, schemaFields, @@ -47,6 +51,7 @@ const responseBuilderSimple = (payload, audienceId) => { // fail-safety for developer error throw new TransformationError(`Payload could not be constructed`); }; + // Function responsible prepare the payload field of every event parameter const preparePayload = ( @@ -55,7 +60,6 @@ const preparePayload = ( paramsPayload, isHashRequired, disableFormat, - skipVerify, ) => { const prepareFinalPayload = _.cloneDeep(paramsPayload); if (Array.isArray(userSchema)) { @@ -69,7 +73,6 @@ const preparePayload = ( userUpdateList, isHashRequired, disableFormat, - skipVerify, ); return batchingWithPayloadSize(prepareFinalPayload); }; @@ -83,7 +86,7 @@ const prepareResponse = ( userSchema, isHashRequired = true, ) => { - const { accessToken, disableFormat, type, subType, isRaw, skipVerify } = destination.Config; + const { accessToken, disableFormat, type, subType, isRaw } = destination.Config; const mappedToDestination = get(message, MappedToDestinationKey); @@ -122,14 +125,13 @@ const prepareResponse = ( paramsPayload, isHashRequired, disableFormat, - skipVerify, ); // paramsPayload.schema = userSchema; const respList = []; payloadBatches.forEach((payloadBatch) => { const response = { ...prepareParams, - payload: payloadBatch , + payload: payloadBatch, }; respList.push(response); }); @@ -137,13 +139,19 @@ const prepareResponse = ( }; /** - * Prepare to send events array - * @param {*} message - * @param {*} destination - * @returns + * Prepare to send events array + * @param {*} message + * @param {*} destination + * @returns */ -const prepareToSendEvents = (message, destination, audienceChunksArray, userSchema, - isHashRequired, operation) => { +const prepareToSendEvents = ( + message, + destination, + audienceChunksArray, + userSchema, + isHashRequired, + operation, +) => { const toSendEvents = []; audienceChunksArray.forEach((allowedAudienceArray) => { const responseArray = prepareResponse( @@ -159,7 +167,7 @@ const prepareToSendEvents = (message, destination, audienceChunksArray, userSche operationCategory: operation, }; toSendEvents.push(wrappedResponse); - }) + }); }); return toSendEvents; }; @@ -208,13 +216,29 @@ const processEvent = (message, destination) => { // when "remove" is present in the payload if (isDefinedAndNotNullAndNotEmpty(listData[USER_DELETE])) { const audienceChunksArray = returnArrayOfSubarrays(listData[USER_DELETE], maxUserCountNumber); - toSendEvents = prepareToSendEvents(message, destination, audienceChunksArray, userSchema, isHashRequired, USER_DELETE); + toSendEvents = prepareToSendEvents( + message, + destination, + audienceChunksArray, + userSchema, + isHashRequired, + USER_DELETE, + ); } // When "add" is present in the payload if (isDefinedAndNotNullAndNotEmpty(listData[USER_ADD])) { const audienceChunksArray = returnArrayOfSubarrays(listData[USER_ADD], maxUserCountNumber); - toSendEvents.push(...prepareToSendEvents(message, destination, audienceChunksArray, userSchema, isHashRequired, USER_ADD)); + toSendEvents.push( + ...prepareToSendEvents( + message, + destination, + audienceChunksArray, + userSchema, + isHashRequired, + USER_ADD, + ), + ); } toSendEvents.forEach((sendEvent) => { respList.push(responseBuilderSimple(sendEvent, operationAudienceId)); diff --git a/src/v0/destinations/fb_custom_audience/util.js b/src/v0/destinations/fb_custom_audience/util.js index 02ad34857c4f..a7a71866bb6d 100644 --- a/src/v0/destinations/fb_custom_audience/util.js +++ b/src/v0/destinations/fb_custom_audience/util.js @@ -3,14 +3,9 @@ const sha256 = require('sha256'); const get = require('get-value'); const jsonSize = require('json-size'); -const { - isDefinedAndNotNull, -} = require('../../util'); -const { maxPayloadSize } = require("./config"); -const { - InstrumentationError, - ConfigurationError, -} = require('../../util/errorTypes'); +const { isDefinedAndNotNull } = require('../../util'); +const { maxPayloadSize } = require('./config'); +const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); /** * Example payload ={ @@ -30,158 +25,144 @@ const { ] } */ const batchingWithPayloadSize = (payload) => { - const payloadSize = jsonSize(payload); - if (payloadSize > maxPayloadSize) { - const revisedPayloadArray = []; - const noOfBatches = Math.ceil(payloadSize / maxPayloadSize); - const revisedRecordsPerPayload = Math.floor(payload.data.length / noOfBatches); - const revisedDataArray = _.chunk(payload.data, revisedRecordsPerPayload); - // const { schema } = payload; - revisedDataArray.forEach((data) => { - revisedPayloadArray.push({ ...payload, data }); - }); - return revisedPayloadArray; - } - return [payload]; -} + const payloadSize = jsonSize(payload); + if (payloadSize > maxPayloadSize) { + const revisedPayloadArray = []; + const noOfBatches = Math.ceil(payloadSize / maxPayloadSize); + const revisedRecordsPerPayload = Math.floor(payload.data.length / noOfBatches); + const revisedDataArray = _.chunk(payload.data, revisedRecordsPerPayload); + // const { schema } = payload; + revisedDataArray.forEach((data) => { + revisedPayloadArray.push({ ...payload, data }); + }); + return revisedPayloadArray; + } + return [payload]; +}; const getSchemaForEventMappedToDest = (message) => { - const mappedSchema = get(message, 'context.destinationFields'); - if (!mappedSchema) { - throw new InstrumentationError( - 'context.destinationFields is required property for events mapped to destination ', - ); - } - // context.destinationFields has 2 possible values. An Array of fields or Comma seperated string with field names - let userSchema = Array.isArray(mappedSchema) ? mappedSchema : mappedSchema.split(','); - userSchema = userSchema.map((field) => field.trim()); - return userSchema; + const mappedSchema = get(message, 'context.destinationFields'); + if (!mappedSchema) { + throw new InstrumentationError( + 'context.destinationFields is required property for events mapped to destination ', + ); + } + // context.destinationFields has 2 possible values. An Array of fields or Comma seperated string with field names + let userSchema = Array.isArray(mappedSchema) ? mappedSchema : mappedSchema.split(','); + userSchema = userSchema.map((field) => field.trim()); + return userSchema; }; // function responsible to ensure the user inputs are passed according to the allowed format const ensureApplicableFormat = (userProperty, userInformation) => { - let updatedProperty; - let userInformationTrimmed; - userInformation = userInformation.toString(); + let updatedProperty; + let userInformationTrimmed; + if (isDefinedAndNotNull(userInformation)) { + const stringifiedUserInformation = userInformation.toString(); switch (userProperty) { - case 'EMAIL': - updatedProperty = userInformation.trim().toLowerCase(); - break; - case 'PHONE': - // remove all non-numerical characters - updatedProperty = userInformation.replace(/\D/g, ''); - // remove all leading zeros - updatedProperty = updatedProperty.replace(/^0+/g, ''); - break; - case 'GEN': - updatedProperty = - userInformation.toLowerCase() === 'f' || userInformation.toLowerCase() === 'female' - ? 'f' - : 'm'; - break; - case 'DOBY': - updatedProperty = userInformation.trim().replace(/\./g, ''); - break; - case 'DOBM': - userInformationTrimmed = userInformation.replace(/\./g, ''); - if (userInformationTrimmed.length < 2) { - updatedProperty = `0${userInformationTrimmed}`; - } else { - updatedProperty = userInformationTrimmed; - } - break; - case 'DOBD': - userInformationTrimmed = userInformation.replace(/\./g, ''); - if (userInformationTrimmed.length < 2) { - updatedProperty = `0${userInformationTrimmed}`; - } else { - updatedProperty = userInformationTrimmed; - } - break; - case 'LN': - case 'FN': - case 'FI': - if (userProperty !== 'FI') { - updatedProperty = userInformation.toLowerCase().replace(/[!#$%&@A-Za-z]/g, ''); - } else { - updatedProperty = userInformation.toLowerCase().replace(/[^!#$%&,.?@A-Za-z]/g, ''); - } - break; - case 'MADID': - updatedProperty = userInformation.toLowerCase(); - break; - case 'COUNTRY': - updatedProperty = userInformation.toLowerCase(); - break; - case 'ZIP': - userInformationTrimmed = userInformation.replace(/\s/g, ''); - updatedProperty = userInformationTrimmed.toLowerCase(); - break; - case 'ST': - case 'CT': - updatedProperty = userInformation - .replace(/[^ A-Za-z]/g, '') - .replace(/\s/g, '') - .toLowerCase(); - break; - case 'EXTERN_ID': - updatedProperty = userInformation; - break; - default: - throw new ConfigurationError(`The property ${userProperty} is not supported`); + case 'EMAIL': + updatedProperty = stringifiedUserInformation.trim().toLowerCase(); + break; + case 'PHONE': + // remove all non-numerical characters + updatedProperty = stringifiedUserInformation.replace(/\D/g, ''); + // remove all leading zeros + updatedProperty = updatedProperty.replace(/^0+/g, ''); + break; + case 'GEN': + updatedProperty = + stringifiedUserInformation.toLowerCase() === 'f' || + stringifiedUserInformation.toLowerCase() === 'female' + ? 'f' + : 'm'; + break; + case 'DOBY': + updatedProperty = stringifiedUserInformation.trim().replace(/\./g, ''); + break; + case 'DOBM': + case 'DOBD': + userInformationTrimmed = stringifiedUserInformation.replace(/\./g, ''); + if (userInformationTrimmed.length < 2) { + updatedProperty = `0${userInformationTrimmed}`; + } else { + updatedProperty = userInformationTrimmed; + } + break; + case 'LN': + case 'FN': + case 'FI': + if (userProperty !== 'FI') { + updatedProperty = stringifiedUserInformation.toLowerCase().replace(/[!#$%&@A-Za-z]/g, ''); + } else { + updatedProperty = stringifiedUserInformation + .toLowerCase() + .replace(/[^!#$%&,.?@A-Za-z]/g, ''); + } + break; + case 'MADID': + updatedProperty = stringifiedUserInformation.toLowerCase(); + break; + case 'COUNTRY': + updatedProperty = stringifiedUserInformation.toLowerCase(); + break; + case 'ZIP': + userInformationTrimmed = stringifiedUserInformation.replace(/\s/g, ''); + updatedProperty = userInformationTrimmed.toLowerCase(); + break; + case 'ST': + case 'CT': + updatedProperty = stringifiedUserInformation + .replace(/[^ A-Za-z]/g, '') + .replace(/\s/g, '') + .toLowerCase(); + break; + case 'EXTERN_ID': + updatedProperty = stringifiedUserInformation; + break; + default: + throw new ConfigurationError(`The property ${userProperty} is not supported`); } - return updatedProperty; + } + return updatedProperty; }; // Function responsible for making the data field without payload object // Based on the "isHashRequired" value hashing is explicitly enabled or disabled -const prepareDataField = ( - userSchema, - userUpdateList, - isHashRequired, - disableFormat, - skipVerify, -) => { - const data = []; - let updatedProperty; - let dataElement; - userUpdateList.forEach((eachUser) => { - dataElement = []; - userSchema.forEach((eachProperty) => { - // if skip verify is true we replace undefined/null user properties with empty string - let userProperty = eachUser[eachProperty]; - if (skipVerify && !isDefinedAndNotNull(userProperty)) { - userProperty = ''; - } - if (isDefinedAndNotNull(userProperty)) { - if (isHashRequired) { - if (!disableFormat) { - // when user requires formatting - updatedProperty = ensureApplicableFormat(eachProperty, userProperty); - } else { - // when user requires hashing but does not require formatting - updatedProperty = userProperty; - } - } else { - // when hashing is not required - updatedProperty = userProperty; - } - if (isHashRequired && eachProperty !== 'MADID' && eachProperty !== 'EXTERN_ID') { - // for MOBILE_ADVERTISER_ID, MADID,EXTERN_ID hashing is not required ref: https://developers.facebook.com/docs/marketing-api/audiences/guides/custom-audiences#hash - updatedProperty = `${updatedProperty}`; - dataElement.push(sha256(updatedProperty)); - } else { - dataElement.push(updatedProperty); - } - } else { - throw new ConfigurationError( - `Configured Schema field ${eachProperty} is missing in one or more user records`, - ); - } - }); - data.push(dataElement); +const prepareDataField = (userSchema, userUpdateList, isHashRequired, disableFormat) => { + const data = []; + let updatedProperty; + let dataElement; + userUpdateList.forEach((eachUser) => { + dataElement = []; + userSchema.forEach((eachProperty) => { + const userProperty = eachUser[eachProperty]; + if (isHashRequired) { + if (!disableFormat) { + // when user requires formatting + updatedProperty = ensureApplicableFormat(eachProperty, userProperty); + } else { + // when user requires hashing but does not require formatting + updatedProperty = userProperty; + } + } else { + // when hashing is not required + updatedProperty = userProperty; + } + if (isHashRequired && eachProperty !== 'MADID' && eachProperty !== 'EXTERN_ID') { + // for MOBILE_ADVERTISER_ID, MADID,EXTERN_ID hashing is not required ref: https://developers.facebook.com/docs/marketing-api/audiences/guides/custom-audiences#hash + if (updatedProperty) { + updatedProperty = `${updatedProperty}`; + dataElement.push(sha256(updatedProperty)); + } else { + dataElement.push(null); + } + } else { + dataElement.push(updatedProperty); + } }); + data.push(dataElement); + }); - return data; + return data; }; -module.exports = { prepareDataField, getSchemaForEventMappedToDest, batchingWithPayloadSize } \ No newline at end of file +module.exports = { prepareDataField, getSchemaForEventMappedToDest, batchingWithPayloadSize }; diff --git a/src/v0/destinations/freshmarketer/transform.js b/src/v0/destinations/freshmarketer/transform.js index 27a6b2784b20..4695b5852493 100644 --- a/src/v0/destinations/freshmarketer/transform.js +++ b/src/v0/destinations/freshmarketer/transform.js @@ -26,6 +26,7 @@ const { getContactsDetails, updateAccountWOContact, } = require('./utils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /* * This functions is used for creating response config for identify call. @@ -38,7 +39,7 @@ const identifyResponseConfig = (Config) => { response.method = defaultPostRequestConfig.requestMethod; response.headers = { Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; }; @@ -97,7 +98,7 @@ const trackResponseBuilder = async (message, { Config }, event) => { } response.headers = { Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; return response; diff --git a/src/v0/destinations/freshmarketer/utils.js b/src/v0/destinations/freshmarketer/utils.js index 9ab92ddab48d..5499262fd2b6 100644 --- a/src/v0/destinations/freshmarketer/utils.js +++ b/src/v0/destinations/freshmarketer/utils.js @@ -19,6 +19,15 @@ const { NetworkError, } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const getHeaders = (apiKey) => { + const headers = { + Authorization: `Token token=${apiKey}`, + 'Content-Type': JSON_MIME_TYPE, + }; + return headers; +}; /* * This functions is used for getting Account details. @@ -30,10 +39,7 @@ const tags = require('../../util/tags'); */ const createUpdateAccount = async (payload, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const payloadBody = { unique_identifier: { name: payload.name }, @@ -70,10 +76,7 @@ const createUpdateAccount = async (payload, Config) => { */ const getUserAccountDetails = async (payload, userEmail, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const userPayload = { unique_identifier: { @@ -126,10 +129,7 @@ const getUserAccountDetails = async (payload, userEmail, Config) => { */ const createOrUpdateListDetails = async (listName, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const endPoint = `https://${Config.domain}${CONFIG_CATEGORIES.GROUP.baseUrlList}`; // fetch all lists @@ -176,10 +176,7 @@ const updateAccountWOContact = (payload, Config) => { unique_identifier: { name: payload.name }, sales_account: payload, }; - response.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); return response; }; @@ -195,10 +192,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.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); response.body.JSON = { ids: [userId], }; @@ -215,10 +209,7 @@ const updateContactWithList = (userId, listId, Config) => { */ const getContactsDetails = async (userEmail, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const userPayload = { unique_identifier: { @@ -276,10 +267,7 @@ const responseBuilderWithContactDetails = async (email, Config, payload, salesAc */ const UpdateContactWithLifeCycleStage = async (message, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const emails = getFieldValueFromMessage(message, 'email'); if (!emails) { @@ -346,10 +334,7 @@ const UpdateContactWithLifeCycleStage = async (message, Config) => { */ const UpdateContactWithSalesActivity = async (payload, message, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; if (!payload.sales_activity_name && !payload.sales_activity_type_id) { throw new InstrumentationError( diff --git a/src/v0/destinations/freshsales/transform.js b/src/v0/destinations/freshsales/transform.js index 0f1d24d5cab0..46a9e8c50000 100644 --- a/src/v0/destinations/freshsales/transform.js +++ b/src/v0/destinations/freshsales/transform.js @@ -17,6 +17,7 @@ const { UpdateContactWithSalesActivity, UpdateContactWithLifeCycleStage, updateAccountWOContact, + getHeaders, } = require('./utils'); /* @@ -28,10 +29,7 @@ const identifyResponseConfig = (Config) => { const response = defaultRequestConfig(); response.endpoint = `https://${Config.domain}${CONFIG_CATEGORIES.IDENTIFY.baseUrl}`; response.method = defaultPostRequestConfig.requestMethod; - response.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); return response; }; @@ -51,10 +49,7 @@ const identifyResponseBuilder = (message, { Config }) => { if (payload.address) payload.address = flattenAddress(payload.address); const response = defaultRequestConfig(); - response.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); response.endpoint = `https://${Config.domain}${CONFIG_CATEGORIES.IDENTIFY.baseUrl}`; response.method = CONFIG_CATEGORIES.IDENTIFY.method; response.body.JSON = { @@ -96,10 +91,7 @@ const trackResponseBuilder = async (message, { Config }, event) => { default: throw new InstrumentationError(`event name ${event} is not supported. Aborting!`); } - response.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); response.method = defaultPostRequestConfig.requestMethod; return response; }; @@ -173,7 +165,9 @@ const processEvent = async (message, destination) => { const mappedEvents = eventMappingHandler(message, destination); if (mappedEvents.length > 0) { const respList = await Promise.all( - mappedEvents.map(async (mappedEvent) => trackResponseBuilder(message, destination, mappedEvent)) + mappedEvents.map(async (mappedEvent) => + trackResponseBuilder(message, destination, mappedEvent), + ), ); response = respList; diff --git a/src/v0/destinations/freshsales/utils.js b/src/v0/destinations/freshsales/utils.js index 1f3a7519ec1c..b2f314977f96 100644 --- a/src/v0/destinations/freshsales/utils.js +++ b/src/v0/destinations/freshsales/utils.js @@ -17,6 +17,15 @@ const { } = require('../../util/errorTypes'); const { CONFIG_CATEGORIES, LIFECYCLE_STAGE_ENDPOINT } = require('./config'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const getHeaders = (apiKey) => { + const headers = { + Authorization: `Token token=${apiKey}`, + 'Content-Type': JSON_MIME_TYPE, + }; + return headers; +}; /* * This functions is used for getting Account details. @@ -28,10 +37,7 @@ const tags = require('../../util/tags'); */ const createUpdateAccount = async (payload, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const payloadBody = { unique_identifier: { name: payload.name }, @@ -67,10 +73,7 @@ const createUpdateAccount = async (payload, Config) => { */ const getUserAccountDetails = async (payload, userEmail, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const userPayload = { unique_identifier: { @@ -122,10 +125,7 @@ const getUserAccountDetails = async (payload, userEmail, Config) => { */ const getContactsDetails = async (userEmail, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const userPayload = { unique_identifier: { @@ -185,10 +185,7 @@ const responseBuilderWithContactDetails = async (email, Config, payload, salesAc */ const UpdateContactWithSalesActivity = async (payload, message, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; if (!payload.sales_activity_name && !payload.sales_activity_type_id) { throw new InstrumentationError( @@ -279,10 +276,7 @@ const UpdateContactWithSalesActivity = async (payload, message, Config) => { */ const UpdateContactWithLifeCycleStage = async (message, Config) => { const requestOptions = { - headers: { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }, + headers: getHeaders(Config.apiKey), }; const emails = getFieldValueFromMessage(message, 'email'); if (!emails) { @@ -356,10 +350,7 @@ const updateAccountWOContact = (payload, Config) => { unique_identifier: { name: payload.name }, sales_account: payload, }; - response.headers = { - Authorization: `Token token=${Config.apiKey}`, - 'Content-Type': 'application/json', - }; + response.headers = getHeaders(Config.apiKey); return response; }; @@ -379,4 +370,5 @@ module.exports = { UpdateContactWithSalesActivity, UpdateContactWithLifeCycleStage, updateAccountWOContact, + getHeaders, }; diff --git a/src/v0/destinations/ga/deleteUsers.js b/src/v0/destinations/ga/deleteUsers.js index 6e3c6df7b5aa..b3f5553847a1 100644 --- a/src/v0/destinations/ga/deleteUsers.js +++ b/src/v0/destinations/ga/deleteUsers.js @@ -5,6 +5,7 @@ const { InstrumentationError, OAuthSecretError } = require('../../util/errorType const { executeCommonValidations } = require('../../util/regulation-api'); const { GA_USER_DELETION_ENDPOINT } = require('./config'); const { gaResponseHandler } = require('./networkHandler'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Prepare the delete users request @@ -47,8 +48,8 @@ const prepareDeleteRequest = (userAttributes, config, rudderDestInfo) => { } const headers = { Authorization: `Bearer ${secret?.access_token}`, - Accept: 'application/json', - 'Content-Type': 'application/json', + Accept: JSON_MIME_TYPE, + 'Content-Type': JSON_MIME_TYPE, }; return { body: reqBody, diff --git a/src/v0/destinations/ga/transform.js b/src/v0/destinations/ga/transform.js index 9b3a8ac39156..0c2a0f8a49b9 100644 --- a/src/v0/destinations/ga/transform.js +++ b/src/v0/destinations/ga/transform.js @@ -3,6 +3,7 @@ const get = require('get-value'); const md5 = require('md5'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { Event, GA_ENDPOINT, ConfigCategory, mappingConfig, nameToEventMap } = require('./config'); +const { setContextualFields } = require('./utils'); const { addExternalIdToTraits, @@ -216,35 +217,8 @@ function responseBuilderSimple(parameters, message, hitType, mappingJson, destin const params = removeUndefinedAndNullValues(parameters); if (message.context) { - const { campaign, userAgent, locale, app, screen } = message.context; - rawPayload.ua = params.ua || userAgent; - rawPayload.ul = params.ul || locale; - if (app) { - rawPayload.an = params.an || app.name; - rawPayload.av = params.av || app.version; - rawPayload.aiid = params.aiid || app.namespace; - } - if (campaign) { - const { name, source, medium, content, term, campaignId } = campaign; - rawPayload.cn = params.cn || name; - rawPayload.cs = params.cs || source; - rawPayload.cm = params.cm || medium; - rawPayload.cc = params.cc || content; - rawPayload.ck = params.ck || term; - rawPayload.ci = campaignId; - } - - if (screen) { - const { width, height } = screen; - if (width && height) { - rawPayload.sr = `${width}x${height}`; - } - - const { innerWidth, innerHeight } = screen; - if (innerWidth && innerHeight) { - rawPayload.vp = `${innerWidth}x${innerHeight}`; - } - } + const addedContextualFields = setContextualFields(rawPayload, message, params); + Object.assign(rawPayload, addedContextualFields); } rawPayload.gclid = getDestinationExternalID(message, 'googleAdsId'); @@ -264,16 +238,16 @@ function responseBuilderSimple(parameters, message, hitType, mappingJson, destin const payload = removeUndefinedAndNullValues(rawPayload); // Get dimensions from destination config - let dimensionsParam = getParamsFromConfig(message, dimensions, 'dimensions'); + let dimensionsParam = getParamsFromConfig(message, dimensions); dimensionsParam = removeUndefinedAndNullValues(dimensionsParam); // Get metrics from destination config - let metricsParam = getParamsFromConfig(message, metrics, 'metrics'); + let metricsParam = getParamsFromConfig(message, metrics); metricsParam = removeUndefinedAndNullValues(metricsParam); // Get contentGroupings from destination config - let contentGroupingsParam = getParamsFromConfig(message, contentGroupings, 'content'); + let contentGroupingsParam = getParamsFromConfig(message, contentGroupings); contentGroupingsParam = removeUndefinedAndNullValues(contentGroupingsParam); const customParams = { @@ -446,13 +420,10 @@ function processPaymentRelatedEvent(message, destination) { let { enhancedEcommerce } = destination.Config; enhancedEcommerce = enhancedEcommerce || false; let pa; - switch (message.event.toLowerCase()) { - case Event.CHECKOUT_STEP_COMPLETED.name: - pa = 'checkout_option'; - break; - default: - pa = 'checkout'; - break; + if (message.event.toLowerCase() === Event.CHECKOUT_STEP_COMPLETED.name) { + pa = 'checkout_option'; + } else { + pa = 'checkout'; } if (enhancedEcommerce) { return { @@ -751,6 +722,38 @@ function processEComGenericEvent(message, destination) { return parameters; } +function updateCustomParamsUsingCategory(category, customParams, message, destination) { + switch (category.name) { + case ConfigCategory.PRODUCT_LIST.name: + Object.assign(customParams, processProductListEvent(message, destination)); + break; + case ConfigCategory.PROMOTION.name: + Object.assign(customParams, processPromotionEvent(message, destination)); + break; + case ConfigCategory.PRODUCT.name: + Object.assign(customParams, processProductEvent(message, destination)); + break; + case ConfigCategory.TRANSACTION.name: + Object.assign(customParams, processTransactionEvent(message, destination)); + break; + case ConfigCategory.PAYMENT.name: + Object.assign(customParams, processPaymentRelatedEvent(message, destination)); + break; + case ConfigCategory.REFUND.name: + Object.assign(customParams, processRefundEvent(message, destination)); + break; + case ConfigCategory.ECOM_GENERIC.name: + Object.assign(customParams, processEComGenericEvent(message, destination)); + break; + case ConfigCategory.SHARING.name: + Object.assign(customParams, processSharingEvent(message)); + break; + default: + Object.assign(customParams, processNonEComGenericEvent(message, destination)); + break; + } +} + // Generic process function which invokes specific handler functions depending on message type // and event type where applicable function processSingleMessage(message, destination) { @@ -806,35 +809,7 @@ function processSingleMessage(message, destination) { } customParams.ec = setCategory || 'EnhancedEcommerce'; customParams.ev = formatValue(eventValue); - switch (category.name) { - case ConfigCategory.PRODUCT_LIST.name: - Object.assign(customParams, processProductListEvent(message, destination)); - break; - case ConfigCategory.PROMOTION.name: - Object.assign(customParams, processPromotionEvent(message, destination)); - break; - case ConfigCategory.PRODUCT.name: - Object.assign(customParams, processProductEvent(message, destination)); - break; - case ConfigCategory.TRANSACTION.name: - Object.assign(customParams, processTransactionEvent(message, destination)); - break; - case ConfigCategory.PAYMENT.name: - Object.assign(customParams, processPaymentRelatedEvent(message, destination)); - break; - case ConfigCategory.REFUND.name: - Object.assign(customParams, processRefundEvent(message, destination)); - break; - case ConfigCategory.ECOM_GENERIC.name: - Object.assign(customParams, processEComGenericEvent(message, destination)); - break; - case ConfigCategory.SHARING.name: - Object.assign(customParams, processSharingEvent(message)); - break; - default: - Object.assign(customParams, processNonEComGenericEvent(message, destination)); - break; - } + updateCustomParamsUsingCategory(category, customParams, message, destination); } else { category = ConfigCategory.NON_ECOM; customParams = processNonEComGenericEvent(message, destination); diff --git a/src/v0/destinations/ga/utils.js b/src/v0/destinations/ga/utils.js index 08819fe62024..c49679275269 100644 --- a/src/v0/destinations/ga/utils.js +++ b/src/v0/destinations/ga/utils.js @@ -38,6 +38,44 @@ const validatePayloadSize = (finalPayload) => { } }; +const setContextualFields = (payload, message, params) => { + const rawPayload = { ...payload }; + if (message.context) { + const { campaign, userAgent, locale, app, screen } = message.context; + rawPayload.ua = params.ua || userAgent; + rawPayload.ul = params.ul || locale; + if (app) { + rawPayload.an = params.an || app.name; + rawPayload.av = params.av || app.version; + rawPayload.aiid = params.aiid || app.namespace; + } + if (campaign) { + const { name, source, medium, content, term, campaignId } = campaign; + rawPayload.cn = params.cn || name; + rawPayload.cs = params.cs || source; + rawPayload.cm = params.cm || medium; + rawPayload.cc = params.cc || content; + rawPayload.ck = params.ck || term; + rawPayload.ci = campaignId; + } + + if (screen) { + const { width, height } = screen; + if (width && height) { + rawPayload.sr = `${width}x${height}`; + } + + const { innerWidth, innerHeight } = screen; + if (innerWidth && innerHeight) { + rawPayload.vp = `${innerWidth}x${innerHeight}`; + } + } + } + + return rawPayload; +}; + module.exports = { validatePayloadSize, + setContextualFields, }; diff --git a/src/v0/destinations/ga/utils.test.js b/src/v0/destinations/ga/utils.test.js new file mode 100644 index 000000000000..08dda9286bf9 --- /dev/null +++ b/src/v0/destinations/ga/utils.test.js @@ -0,0 +1,57 @@ +const { setContextualFields } = require('./utils'); + +const getTestMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + context: { + device: { + token: 1234, + }, + os: { + token: 5678, + }, + app: { + name: 'name', + version: 'version', + namespace: 'namespace', + }, + campaign: { + name: 'name', + source: 'source', + medium: 'medium', + content: 'content', + term: 'term', + campaignId: 'campaignId', + }, + screen: { + width: 'width', + height: 'height', + innerHeight: 'innerHeight', + innerWidth: 'innerWidth', + }, + }, + }; + return message; +}; + +describe('setContextualFields', () => { + it('correct flow', () => { + let expectedOutput = { + aiid: 'namespace', + an: 'name', + av: 'version', + cc: 'content', + ci: 'campaignId', + ck: 'term', + cm: 'medium', + cn: 'name', + cs: 'source', + sr: 'widthxheight', + ua: undefined, + ul: undefined, + vp: 'innerWidthxinnerHeight', + }; + expect(setContextualFields({}, getTestMessage(), {})).toEqual(expectedOutput); + }); +}); diff --git a/src/v0/destinations/ga360/transform.js b/src/v0/destinations/ga360/transform.js index 222238528f39..a9d4f6b2103d 100644 --- a/src/v0/destinations/ga360/transform.js +++ b/src/v0/destinations/ga360/transform.js @@ -231,16 +231,16 @@ function responseBuilderSimple(parameters, message, hitType, mappingJson, destin const params = removeUndefinedAndNullValues(parameters); // Get dimensions from destination config - let dimensionsParam = getParamsFromConfig(message, dimensions, 'dimensions'); + let dimensionsParam = getParamsFromConfig(message, dimensions); dimensionsParam = removeUndefinedAndNullValues(dimensionsParam); // Get metrics from destination config - let metricsParam = getParamsFromConfig(message, metrics, 'metrics'); + let metricsParam = getParamsFromConfig(message, metrics); metricsParam = removeUndefinedAndNullValues(metricsParam); // Get contentGroupings from destination config - let contentGroupingsParam = getParamsFromConfig(message, contentGroupings, 'content'); + let contentGroupingsParam = getParamsFromConfig(message, contentGroupings); contentGroupingsParam = removeUndefinedAndNullValues(contentGroupingsParam); const customParams = { @@ -378,13 +378,10 @@ function processPaymentRelatedEvent(message, destination) { let { enhancedEcommerce } = destination.Config; enhancedEcommerce = enhancedEcommerce || false; let pa; - switch (message.event.toLowerCase()) { - case Event.CHECKOUT_STEP_COMPLETED.name: - pa = 'checkout_option'; - break; - default: - pa = 'checkout'; - break; + if (message.event.toLowerCase() === Event.CHECKOUT_STEP_COMPLETED.name) { + pa = 'checkout_option'; + } else { + pa = 'checkout'; } if (enhancedEcommerce) { return { @@ -672,6 +669,38 @@ function processEComGenericEvent(message, destination) { return parameters; } +function updateCustomParamsUsingCategory(category, customParams, message, destination) { + switch (category.name) { + case ConfigCategory.PRODUCT_LIST.name: + Object.assign(customParams, processProductListEvent(message, destination)); + break; + case ConfigCategory.PROMOTION.name: + Object.assign(customParams, processPromotionEvent(message, destination)); + break; + case ConfigCategory.PRODUCT.name: + Object.assign(customParams, processProductEvent(message, destination)); + break; + case ConfigCategory.TRANSACTION.name: + Object.assign(customParams, processTransactionEvent(message, destination)); + break; + case ConfigCategory.PAYMENT.name: + Object.assign(customParams, processPaymentRelatedEvent(message, destination)); + break; + case ConfigCategory.REFUND.name: + Object.assign(customParams, processRefundEvent(message, destination)); + break; + case ConfigCategory.ECOM_GENERIC.name: + Object.assign(customParams, processEComGenericEvent(message, destination)); + break; + case ConfigCategory.SHARING.name: + Object.assign(customParams, processSharingEvent(message)); + break; + default: + Object.assign(customParams, processNonEComGenericEvent(message, destination)); + break; + } +} + // Generic process function which invokes specific handler functions depending on message type // and event type where applicable function processSingleMessage(message, destination) { @@ -725,35 +754,7 @@ function processSingleMessage(message, destination) { } customParams.ec = setCategory || 'EnhancedEcommerce'; customParams.ev = formatValue(eventValue); - switch (category.name) { - case ConfigCategory.PRODUCT_LIST.name: - Object.assign(customParams, processProductListEvent(message, destination)); - break; - case ConfigCategory.PROMOTION.name: - Object.assign(customParams, processPromotionEvent(message, destination)); - break; - case ConfigCategory.PRODUCT.name: - Object.assign(customParams, processProductEvent(message, destination)); - break; - case ConfigCategory.TRANSACTION.name: - Object.assign(customParams, processTransactionEvent(message, destination)); - break; - case ConfigCategory.PAYMENT.name: - Object.assign(customParams, processPaymentRelatedEvent(message, destination)); - break; - case ConfigCategory.REFUND.name: - Object.assign(customParams, processRefundEvent(message, destination)); - break; - case ConfigCategory.ECOM_GENERIC.name: - Object.assign(customParams, processEComGenericEvent(message, destination)); - break; - case ConfigCategory.SHARING.name: - Object.assign(customParams, processSharingEvent(message)); - break; - default: - Object.assign(customParams, processNonEComGenericEvent(message, destination)); - break; - } + updateCustomParamsUsingCategory(category, customParams, message, destination); } else { category = ConfigCategory.NON_ECOM; customParams = processNonEComGenericEvent(message, destination); diff --git a/src/v0/destinations/ga4/data/GA4GenerateLeadConfig.json b/src/v0/destinations/ga4/data/GA4GenerateLeadConfig.json index 62c3758fd5fe..901476c0f37c 100644 --- a/src/v0/destinations/ga4/data/GA4GenerateLeadConfig.json +++ b/src/v0/destinations/ga4/data/GA4GenerateLeadConfig.json @@ -1,38 +1,38 @@ [ - { - "destKey": "currency", - "sourceKeys": "properties.currency", - "metadata": { - "defaultValue": "USD" - }, - "required": false + { + "destKey": "currency", + "sourceKeys": "properties.currency", + "metadata": { + "defaultValue": "USD" }, - { - "destKey": "value", - "sourceKeys": [ - "properties.value", - "properties.total", - "properties.price", - "properties.revenue" - ], - "metadata": { - "type": "toNumber" - }, - "required": true + "required": false + }, + { + "destKey": "value", + "sourceKeys": [ + "properties.value", + "properties.total", + "properties.price", + "properties.revenue" + ], + "metadata": { + "type": "toNumber" }, - { - "destKey": "engagement_time_msec", - "sourceKeys": [ - "traits.engagementTimeMsec", - "properties.engagementTimeMsec", - "context.traits.engagementTimeMsec", - "traits.engagement_time_msec", - "properties.engagement_time_msec", - "context.traits.engagement_time_msec" - ], - "metadata": { - "defaultValue": 1 - }, - "required": false - } -] \ No newline at end of file + "required": true + }, + { + "destKey": "engagement_time_msec", + "sourceKeys": [ + "traits.engagementTimeMsec", + "properties.engagementTimeMsec", + "context.traits.engagementTimeMsec", + "traits.engagement_time_msec", + "properties.engagement_time_msec", + "context.traits.engagement_time_msec" + ], + "metadata": { + "defaultValue": 1 + }, + "required": false + } +] diff --git a/src/v0/destinations/ga4/data/GA4LoginSignupConfig.json b/src/v0/destinations/ga4/data/GA4LoginSignupConfig.json index b533fb06bbcb..300ca00d8f46 100644 --- a/src/v0/destinations/ga4/data/GA4LoginSignupConfig.json +++ b/src/v0/destinations/ga4/data/GA4LoginSignupConfig.json @@ -1,25 +1,22 @@ [ - { - "destKey": "method", - "sourceKeys": [ - "traits.method", - "properties.method" - ], - "required": false + { + "destKey": "method", + "sourceKeys": ["traits.method", "properties.method"], + "required": false + }, + { + "destKey": "engagement_time_msec", + "sourceKeys": [ + "traits.engagementTimeMsec", + "properties.engagementTimeMsec", + "context.traits.engagementTimeMsec", + "traits.engagement_time_msec", + "properties.engagement_time_msec", + "context.traits.engagement_time_msec" + ], + "metadata": { + "defaultValue": 1 }, - { - "destKey": "engagement_time_msec", - "sourceKeys": [ - "traits.engagementTimeMsec", - "properties.engagementTimeMsec", - "context.traits.engagementTimeMsec", - "traits.engagement_time_msec", - "properties.engagement_time_msec", - "context.traits.engagement_time_msec" - ], - "metadata": { - "defaultValue": 1 - }, - "required": false - } -] \ No newline at end of file + "required": false + } +] diff --git a/src/v0/destinations/ga4/networkHandler.js b/src/v0/destinations/ga4/networkHandler.js index 7671513d2603..e90d2c30953b 100644 --- a/src/v0/destinations/ga4/networkHandler.js +++ b/src/v0/destinations/ga4/networkHandler.js @@ -58,12 +58,12 @@ const responseHandler = (destinationResponse, dest) => { }; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = proxyRequest; this.prepareProxy = prepareProxyRequest; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/ga4/transform.js b/src/v0/destinations/ga4/transform.js index 272534b21b56..50851770b027 100644 --- a/src/v0/destinations/ga4/transform.js +++ b/src/v0/destinations/ga4/transform.js @@ -39,6 +39,7 @@ const { getGA4CustomParameters, GA4_PARAMETERS_EXCLUSION, } = require('./utils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * returns client_id @@ -270,7 +271,7 @@ const responseBuilder = (message, { Config }) => { } response.headers = { HOST: 'www.google-analytics.com', - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.params = { api_secret: Config.apiSecret, diff --git a/src/v0/destinations/ga4/utils.js b/src/v0/destinations/ga4/utils.js index 8758d9daacea..6f965ba2144a 100644 --- a/src/v0/destinations/ga4/utils.js +++ b/src/v0/destinations/ga4/utils.js @@ -70,12 +70,7 @@ const removeReservedParameterPrefixNames = (parameter) => { } Object.keys(parameter).forEach((key) => { - const valFound = reservedPrefixesNames.some((prefix) => { - if (key.toLowerCase().startsWith(prefix)) { - return true; - } - return false; - }); + const valFound = reservedPrefixesNames.some((prefix) => key.toLowerCase().startsWith(prefix)); // reject if found if (valFound) { @@ -111,12 +106,7 @@ const removeReservedUserPropertyPrefixNames = (userProperties) => { } Object.keys(userProperties).forEach((key) => { - const valFound = reservedPrefixesNames.some((prefix) => { - if (key.toLowerCase().startsWith(prefix)) { - return true; - } - return false; - }); + const valFound = reservedPrefixesNames.some((prefix) => key.toLowerCase().startsWith(prefix)); // reject if found if (valFound) { @@ -160,12 +150,7 @@ const isReservedWebCustomPrefixName = (event) => { const reservedPrefixesNames = ['_', 'firebase_', 'ga_', 'google_', 'gtag.']; // As soon as a single true is returned, .some() will itself return true and stop - return reservedPrefixesNames.some((prefix) => { - if (event.toLowerCase().startsWith(prefix)) { - return true; - } - return false; - }); + return reservedPrefixesNames.some((prefix) => event.toLowerCase().startsWith(prefix)); }; const GA4_ITEM_EXCLUSION = [ diff --git a/src/v0/destinations/gainsight/transform.js b/src/v0/destinations/gainsight/transform.js index 6d31e54e9495..f58fc0d56660 100644 --- a/src/v0/destinations/gainsight/transform.js +++ b/src/v0/destinations/gainsight/transform.js @@ -29,6 +29,7 @@ const { getConfigOrThrowError, } = require('./util'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Person Object is created or updated. Upsert API makes PUT request for both cases @@ -67,7 +68,7 @@ const identifyResponseBuilder = (message, { Config }) => { response.body.JSON = removeUndefinedAndNullValues(payload); response.headers = { Accesskey: accessKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.endpoint = ENDPOINTS.identifyEndpoint(Config.domain); return response; @@ -119,7 +120,7 @@ const groupResponseBuilder = async (message, { Config }) => { response.endpoint = ENDPOINTS.identifyEndpoint(Config.domain); response.headers = { Accesskey: accessKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = responsePayload; return response; @@ -164,7 +165,7 @@ const trackResponseBuilder = (message, { Config }) => { response.endpoint = ENDPOINTS.trackEndpoint(Config.domain); response.headers = { ...config, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, eventName: get(eventNameMap, event), eventVersion: get(eventVersionMap, event), }; diff --git a/src/v0/destinations/gainsight/util.js b/src/v0/destinations/gainsight/util.js index 2627a02396a3..665aad3aea8f 100644 --- a/src/v0/destinations/gainsight/util.js +++ b/src/v0/destinations/gainsight/util.js @@ -4,6 +4,7 @@ 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'); const searchGroup = async (groupName, Config) => { let resp; @@ -14,7 +15,7 @@ const searchGroup = async (groupName, Config) => { { headers: { Accesskey: Config.accessKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }, ); @@ -47,7 +48,7 @@ const createGroup = async (payload, Config) => { { headers: { Accesskey: Config.accessKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }, ); @@ -80,7 +81,7 @@ const updateGroup = async (payload, Config) => { { headers: { Accesskey: Config.accessKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, params: { keys: 'Name', diff --git a/src/v0/destinations/gainsight_px/transform.js b/src/v0/destinations/gainsight_px/transform.js index 8cbd3981815c..141cef276fae 100644 --- a/src/v0/destinations/gainsight_px/transform.js +++ b/src/v0/destinations/gainsight_px/transform.js @@ -30,6 +30,7 @@ const { identifyMapping, } = require('./config'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Create/Update a User with user attributes @@ -43,7 +44,7 @@ const identifyResponseBuilder = async (message, { Config }) => { const response = defaultRequestConfig(); response.headers = { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; const { success: isPresent } = await objectExists(userId, Config, 'user'); @@ -143,7 +144,7 @@ const newGroupResponseBuilder = async (message, { Config }) => { response.method = defaultPutRequestConfig.requestMethod; response.headers = { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.endpoint = `${ENDPOINTS.USERS_ENDPOINT}/${userId}`; response.body.JSON = { @@ -211,7 +212,7 @@ const groupResponseBuilder = async (message, { Config }) => { response.method = defaultPutRequestConfig.requestMethod; response.headers = { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.endpoint = `${ENDPOINTS.USERS_ENDPOINT}/${userId}`; response.body.JSON = { @@ -252,7 +253,7 @@ const trackResponseBuilder = (message, { Config }) => { response.body.JSON = removeUndefinedAndNullValues(payload); response.headers = { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.endpoint = ENDPOINTS.CUSTOM_EVENTS_ENDPOINT; return response; diff --git a/src/v0/destinations/gainsight_px/util.js b/src/v0/destinations/gainsight_px/util.js index 3365ab9bf288..44e2c621ef81 100644 --- a/src/v0/destinations/gainsight_px/util.js +++ b/src/v0/destinations/gainsight_px/util.js @@ -3,6 +3,7 @@ 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'); const handleErrorResponse = (error, customErrMessage, expectedErrStatus, defaultStatus = 400) => { let errMessage = ''; @@ -50,7 +51,7 @@ const objectExists = async (id, Config, objectType) => { response = await axios.get(url, { headers: { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }); if (response && response.status === 200) { @@ -77,7 +78,7 @@ const createAccount = async (payload, Config) => { response = await axios.post(ENDPOINTS.ACCOUNTS_ENDPOINT, payload, { headers: { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }); if (response && response.status === 201) { @@ -105,7 +106,7 @@ const updateAccount = async (accountId, payload, Config) => { response = await axios.put(`${ENDPOINTS.ACCOUNTS_ENDPOINT}/${accountId}`, payload, { headers: { 'X-APTRINSIC-API-KEY': Config.apiKey, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, }); if (response && response.status === 204) { diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js index 0f399b679776..f42056bc9709 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js @@ -24,13 +24,8 @@ const tags = require('../../util/tags'); * @returns */ const getAuthErrCategory = (code, response) => { - switch (code) { - case 401: - if (!get(response, 'error.details')) return REFRESH_TOKEN; - return ''; - default: - return ''; - } + if (code === 401 && !get(response, 'error.details')) return REFRESH_TOKEN; + return ''; }; /** diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/transform.js b/src/v0/destinations/google_adwords_enhanced_conversions/transform.js index 28d5670a240f..96ef0890016e 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/transform.js +++ b/src/v0/destinations/google_adwords_enhanced_conversions/transform.js @@ -17,6 +17,7 @@ const { } = require('../../util/errorTypes'); const { trackMapping, BASE_ENDPOINT } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * This function is helping to update the mappingJson. @@ -65,7 +66,7 @@ const responseBuilder = async (metadata, message, { Config }, payload) => { const accessToken = getAccessToken(metadata); response.headers = { Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'developer-token': getValueFromMessage(metadata, 'secret.developer_token'), }; response.params = { event, customerId: filteredCustomerId }; @@ -109,10 +110,7 @@ const processTrackEvent = async (metadata, message, destination) => { payload.conversionAdjustments[0].adjustmentType = 'ENHANCEMENT'; // Removing the null values from userIdentifier const arr = payload.conversionAdjustments[0].userIdentifiers; - payload.conversionAdjustments[0].userIdentifiers = arr.filter((item) => { - if (item) return true; - return false; - }); + payload.conversionAdjustments[0].userIdentifiers = arr.filter((item) => !!item); return responseBuilder(metadata, message, destination, payload); }; diff --git a/src/v0/destinations/google_adwords_offline_conversions/config.js b/src/v0/destinations/google_adwords_offline_conversions/config.js index 0f321f06a64d..1d77af02e680 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/config.js +++ b/src/v0/destinations/google_adwords_offline_conversions/config.js @@ -28,8 +28,8 @@ const CONFIG_CATEGORIES = { name: 'TrackAddStoreConversionsConfig', }, TRACK_STORE_ADDRESS_IDENTIFIER: { - name: 'storeAddoperationAddressMap' - } + name: 'storeAddoperationAddressMap', + }, }; const CONVERSION_ACTION_ID_CACHE_TTL = process.env.CONVERSION_ACTION_ID_CACHE_TTL @@ -58,5 +58,4 @@ module.exports = { MAPPING_CONFIG[CONFIG_CATEGORIES.TRACK_STORE_CONVERSION_CONFIG_ADD_CONVERSION.name], trackAddStoreAddressConversionsMapping: MAPPING_CONFIG[CONFIG_CATEGORIES.TRACK_STORE_ADDRESS_IDENTIFIER.name], - }; diff --git a/src/v0/destinations/google_adwords_offline_conversions/data/TrackAddStoreConversionsConfig.json b/src/v0/destinations/google_adwords_offline_conversions/data/TrackAddStoreConversionsConfig.json index 60f0d4cc851d..17e77620bc3b 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/data/TrackAddStoreConversionsConfig.json +++ b/src/v0/destinations/google_adwords_offline_conversions/data/TrackAddStoreConversionsConfig.json @@ -1,10 +1,7 @@ [ { "destKey": "operations.create.transaction_attribute.store_attribute.store_code", - "sourceKeys": [ - "properties.store_code", - "properties.storeCode" - ], + "sourceKeys": ["properties.store_code", "properties.storeCode"], "required": false, "metadata": { "type": "toString" @@ -25,10 +22,7 @@ }, { "destKey": "operations.create.transaction_attribute.order_id", - "sourceKeys": [ - "properties.order_id", - "properties.orderId" - ], + "sourceKeys": ["properties.order_id", "properties.orderId"], "required": false, "metadata": { "type": "toString" @@ -56,4 +50,3 @@ } } ] - diff --git a/src/v0/destinations/google_adwords_offline_conversions/data/TrackCreateJobStoreConversionsConfig.json b/src/v0/destinations/google_adwords_offline_conversions/data/TrackCreateJobStoreConversionsConfig.json index 87b78c9303c9..19ba9dbaa232 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/data/TrackCreateJobStoreConversionsConfig.json +++ b/src/v0/destinations/google_adwords_offline_conversions/data/TrackCreateJobStoreConversionsConfig.json @@ -1,24 +1,24 @@ [ - { - "destKey": "enable_match_rate_range_preview", - "sourceKeys": "properties.enable_match_rate_range_preview", - "required": false - }, - { - "destKey": "job.storeSalesMetadata.loyaltyFraction", - "sourceKeys": "properties.loyaltyFraction", - "required": false, - "defaultValue":"1" - }, - { - "destKey": "job.storeSalesMetadata.transaction_upload_fraction", - "sourceKeys": "properties.transaction_upload_fraction", - "required": false, - "defaultValue":"1" - }, - { - "destKey": "job.storeSalesMetadata.custom_key", - "sourceKeys": "properties.custom_key", - "required": false - } -] \ No newline at end of file + { + "destKey": "enable_match_rate_range_preview", + "sourceKeys": "properties.enable_match_rate_range_preview", + "required": false + }, + { + "destKey": "job.storeSalesMetadata.loyaltyFraction", + "sourceKeys": "properties.loyaltyFraction", + "required": false, + "defaultValue": "1" + }, + { + "destKey": "job.storeSalesMetadata.transaction_upload_fraction", + "sourceKeys": "properties.transaction_upload_fraction", + "required": false, + "defaultValue": "1" + }, + { + "destKey": "job.storeSalesMetadata.custom_key", + "sourceKeys": "properties.custom_key", + "required": false + } +] diff --git a/src/v0/destinations/google_adwords_offline_conversions/data/storeAddoperationAddressMap.json b/src/v0/destinations/google_adwords_offline_conversions/data/storeAddoperationAddressMap.json index 0822d9f9c8f3..e499b0e234bc 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/data/storeAddoperationAddressMap.json +++ b/src/v0/destinations/google_adwords_offline_conversions/data/storeAddoperationAddressMap.json @@ -1,66 +1,60 @@ [ - { - "sourceKeys": "city", - "destKey": "city", - "sourceFromGenericMap": true - }, - { - "sourceKeys": "state", - "destKey": "state", - "sourceFromGenericMap": true - }, - { - "sourceKeys": [ - "context.traits.country_code", - "properties.country_code", - "context.traits.countryCode", - "properties.countryCode" - ], - "destKey": "country_code" - }, - { - "sourceKeys": [ - "context.traits.postal_code", - "properties.postal_code", - "context.traits.postalCode", - "properties.postalCode", - "context.traits.zipCode", - "properties.zipCode" - ], - "destKey": "postal_code" - }, - { - "sourceKeys": "firstName", - "destKey": "hashed_first_name", - "sourceFromGenericMap": true, - "metadata": { - "type": [ - "toLower" - ] - } - }, - { - "destKey": "hashed_street_address", - "sourceKeys": [ - "properties.streetAddress", - "context.traits.streetAddress", - "traits.street", - "context.traits.street" - ], - "metadata": { - "type": [ - "toLower" - ] - } - }, - { - "sourceKeys": "lastName", - "destKey": "hashed_last_name", - "metadata": { - "type": [ - "toLower" - ] - }, - "sourceFromGenericMap": true + { + "sourceKeys": "city", + "destKey": "city", + "sourceFromGenericMap": true + }, + { + "sourceKeys": "state", + "destKey": "state", + "sourceFromGenericMap": true + }, + { + "sourceKeys": [ + "context.traits.country_code", + "properties.country_code", + "context.traits.countryCode", + "properties.countryCode" + ], + "destKey": "country_code" + }, + { + "sourceKeys": [ + "context.traits.postal_code", + "properties.postal_code", + "context.traits.postalCode", + "properties.postalCode", + "context.traits.zipCode", + "properties.zipCode" + ], + "destKey": "postal_code" + }, + { + "sourceKeys": "firstName", + "destKey": "hashed_first_name", + "sourceFromGenericMap": true, + "metadata": { + "type": ["toLower"] } -] \ No newline at end of file + }, + { + "destKey": "hashed_street_address", + "sourceKeys": [ + "properties.streetAddress", + "context.traits.streetAddress", + "traits.street", + "context.traits.street" + ], + "metadata": { + "type": ["toLower"] + } + }, + { + "sourceKeys": "lastName", + "destKey": "hashed_last_name", + "metadata": { + "type": ["toLower"] + }, + "sourceFromGenericMap": true + } +] diff --git a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js index 55947de6be78..aa6e6c84f8e5 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js @@ -32,17 +32,15 @@ const conversionCustomVariableCache = new Cache(CONVERSION_CUSTOM_VARIABLE_CACHE * @returns */ const getAuthErrCategory = (status) => { - switch (status) { - case 401: - // UNAUTHORIZED - return REFRESH_TOKEN; - default: - return ''; + if (status === 401) { + // UNAUTHORIZED + return REFRESH_TOKEN; } + return ''; }; const createJob = async (endpoint, headers, payload) => { - const endPoint = `${endpoint}:create` + const endPoint = `${endpoint}:create`; let createJobResponse = await httpPOST(endPoint, payload, { headers }); createJobResponse = processAxiosResponse(createJobResponse); const { response, status } = createJobResponse; @@ -58,7 +56,7 @@ const createJob = async (endpoint, headers, payload) => { }; const addConversionToJob = async (endpoint, headers, jobId, payload) => { - const endPoint = `${endpoint}/${jobId}:addOperations` + const endPoint = `${endpoint}/${jobId}:addOperations`; let addConversionToJobResponse = await httpPOST(endPoint, payload, { headers }); addConversionToJobResponse = processAxiosResponse(addConversionToJobResponse); if (!isHttpStatusSuccess(addConversionToJobResponse.status)) { @@ -70,13 +68,13 @@ const addConversionToJob = async (endpoint, headers, jobId, payload) => { ); } return true; -} +}; const runTheJob = async (endpoint, headers, payload, jobId) => { const endPoint = `${endpoint}/${jobId}:run`; const executeJobResponse = await httpPOST(endPoint, payload, { headers }); return executeJobResponse; -} +}; /** * get all the custom variable for a customerID i.e created @@ -162,10 +160,15 @@ const ProxyRequest = async (request) => { const addPayload = body.JSON.addConversionPayload; // Mapping Conversion Action const conversionId = await getConversionActionId(headers, params); - set(addPayload, 'operations.create.transaction_attribute.conversion_action', conversionId) + set(addPayload, 'operations.create.transaction_attribute.conversion_action', conversionId); await addConversionToJob(endpoint, headers, firstResponse, addPayload); // console.log(JSON.stringify(secondResponse.response.response)); - const thirdResponse = await runTheJob(endpoint, headers, body.JSON.executeJobPayload, firstResponse); + const thirdResponse = await runTheJob( + endpoint, + headers, + body.JSON.executeJobPayload, + firstResponse, + ); return thirdResponse; } // fetch conversionAction @@ -244,12 +247,12 @@ const responseHandler = (destinationResponse) => { ); }; -const networkHandler = function () { +function networkHandler() { this.prepareProxy = prepareProxyRequest; this.proxy = ProxyRequest; this.processAxiosResponse = processAxiosResponse; this.responseHandler = responseHandler; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/google_adwords_offline_conversions/utils.js b/src/v0/destinations/google_adwords_offline_conversions/utils.js index 18928e0a5351..e1cbe8f8db37 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/utils.js +++ b/src/v0/destinations/google_adwords_offline_conversions/utils.js @@ -8,7 +8,9 @@ const { defaultRequestConfig, defaultPostRequestConfig, removeHyphens, - getFieldValueFromMessage + getFieldValueFromMessage, + isDefinedAndNotNullAndNotEmpty, + isDefinedAndNotNull, } = require('../../util'); const { REFRESH_TOKEN } = require('../../../adapters/networkhandler/authConstants'); const { @@ -18,11 +20,16 @@ const { trackAddStoreConversionsMapping, trackAddStoreAddressConversionsMapping, trackClickConversionsMapping, - CLICK_CONVERSION + CLICK_CONVERSION, } = require('./config'); const { processAxiosResponse } = require('../../../adapters/utils/networkUtils'); const Cache = require('../../util/cache'); -const { AbortedError, OAuthSecretError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); +const { + AbortedError, + OAuthSecretError, + ConfigurationError, + InstrumentationError, +} = require('../../util/errorTypes'); const conversionActionIdCache = new Cache(CONVERSION_ACTION_ID_CACHE_TTL); @@ -57,13 +64,11 @@ const getAccessToken = ({ secret }) => { * @returns */ const getAuthErrCategory = (status) => { - switch (status) { - case 401: - // UNAUTHORIZED - return REFRESH_TOKEN; - default: - return ''; + if (status === 401) { + // UNAUTHORIZED + return REFRESH_TOKEN; } + return ''; }; /** @@ -104,6 +109,20 @@ const getConversionActionId = async (headers, params) => { }); }; +const generateItemListFromProducts = (products) => { + const itemList = []; + products.forEach((product) => { + if (Object.keys(product).length > 0) { + itemList.push({ + productId: product.product_id, + quantity: parseInt(product.quantity, 10), + unitPrice: Number(product.price), + }); + } + }); + return itemList; +}; + /** * update mapping Json config to remove 'hashToSha256' * operation from metadata.type and replace it with @@ -124,18 +143,24 @@ const removeHashToSha256TypeFromMappingJson = (mapping) => { }; /** * To construct the address object according to the google ads documentation - * @param {*} message + * @param {*} message */ const buildAndGetAddress = (message, hashUserIdentifier) => { const address = constructPayload(message, trackAddStoreAddressConversionsMapping); - if(address.hashed_last_name){ - address.hashed_last_name = hashUserIdentifier? sha256(address.hashed_last_name).toString(): address.hashed_last_name; + if (address.hashed_last_name) { + address.hashed_last_name = hashUserIdentifier + ? sha256(address.hashed_last_name).toString() + : address.hashed_last_name; } - if(address.hashed_first_name){ - address.hashed_first_name = hashUserIdentifier? sha256(address.hashed_first_name).toString(): address.hashed_first_name; + if (address.hashed_first_name) { + address.hashed_first_name = hashUserIdentifier + ? sha256(address.hashed_first_name).toString() + : address.hashed_first_name; } - if(address.hashed_street_address){ - address.hashed_street_address = hashUserIdentifier? sha256(address.hashed_street_address).toString(): address.hashed_street_address; + if (address.hashed_street_address) { + address.hashed_street_address = hashUserIdentifier + ? sha256(address.hashed_street_address).toString() + : address.hashed_street_address; } return Object.keys(address).length > 0 ? address : null; }; @@ -148,7 +173,7 @@ const requestBuilder = ( metadata, event, filteredCustomerId, - properties + properties, ) => { const { customVariables, subAccount, loginCustomerId } = Config; const response = defaultRequestConfig(); @@ -156,7 +181,7 @@ const requestBuilder = ( response.endpoint = endpoint; response.params = { event, - customerId: filteredCustomerId + customerId: filteredCustomerId, }; if (!payload?.isStoreConversion) { response.params.customVariables = customVariables; @@ -183,26 +208,39 @@ const requestBuilder = ( * This function creates a offlineUserDataJob Payload * and returns the payload */ -const getCreateJobPayload = message => { +const getCreateJobPayload = (message) => { const payload = constructPayload(message, trackCreateStoreConversionsMapping); - set(payload, "job.type", 'STORE_SALES_UPLOAD_FIRST_PARTY'); + set(payload, 'job.type', 'STORE_SALES_UPLOAD_FIRST_PARTY'); if (!payload.job?.storeSalesMetadata?.loyaltyFraction) { - set(payload, "job.storeSalesMetadata.loyaltyFraction", '1'); + set(payload, 'job.storeSalesMetadata.loyaltyFraction', '1'); } if (!payload.job?.storeSalesMetadata?.transaction_upload_fraction) { - set(payload, "job.storeSalesMetadata.transaction_upload_fraction", '1'); + set(payload, 'job.storeSalesMetadata.transaction_upload_fraction', '1'); } return payload; }; +const UserIdentifierFieldNameMap = { + email: 'hashedEmail', + phone: 'hashedPhoneNumber', + address: 'address_info', +}; + +function getExisitingUserIdentifier(userIdentifierInfo, defaultUserIdentifier) { + const result = Object.keys(userIdentifierInfo).find( + (key) => + key !== defaultUserIdentifier && isDefinedAndNotNullAndNotEmpty(userIdentifierInfo[key]), + ); + return result; +} + /** - * This Function create the add conversion payload + * This Function create the add conversion payload * and returns the payload */ const getAddConversionPayload = (message, Config) => { const { properties } = message; - const { validateOnly, hashUserIdentifier, - defaultUserIdentifier } = Config; + const { validateOnly, hashUserIdentifier, defaultUserIdentifier } = Config; const payload = constructPayload(message, trackAddStoreConversionsMapping); payload.enable_partial_failure = false; payload.enable_warnings = false; @@ -217,58 +255,63 @@ const getAddConversionPayload = (message, Config) => { payload.operations.create.transaction_attribute.transaction_date_time = convertedDateTime; // mapping custom_key that should be predefined in google Ui and mentioned when new job is created if (properties.custom_key && properties[properties.custom_key]) { - payload.operations.create.transaction_attribute[properties.custom_key] = properties[properties.custom_key]; + payload.operations.create.transaction_attribute[properties.custom_key] = + properties[properties.custom_key]; } // Converting transaction Cost to micro as mentioned here : https://developers.google.com/google-ads/api/reference/rpc/v13/TransactionAttribute#:~:text=30%2B03%3A00%22-,transaction_amount_micros,-double - payload.operations.create.transaction_attribute.transaction_amount_micros = `${payload.operations.create.transaction_attribute.transaction_amount_micros * 1000000}`; + payload.operations.create.transaction_attribute.transaction_amount_micros = `${ + payload.operations.create.transaction_attribute.transaction_amount_micros * 1000000 + }`; // userIdentifierSource // if userIdentifierSource doesn't exist in properties // then it is taken from the webapp config - let email = getFieldValueFromMessage(message, 'email'); - let phone = getFieldValueFromMessage(message, 'phone'); - const address = buildAndGetAddress(message, hashUserIdentifier); - if (defaultUserIdentifier === 'email' && email) { - email = hashUserIdentifier ? sha256(email).toString() : email; - set(payload, 'operations.create.userIdentifiers[0].hashedEmail', email); - } else if (defaultUserIdentifier === 'phone' && phone) { - phone = hashUserIdentifier ? sha256(phone).toString(): phone; - set(payload, 'operations.create.userIdentifiers[0].hashedPhoneNumber', phone); - } else if (address) { - // priortizing address in case defaultUserIdentifier is not present - set(payload, 'operations.create.userIdentifiers[0].address_info', address); - } else if (email) { - // case when default choosen value is not present - email = hashUserIdentifier ? sha256(email).toString() : email; - set(payload, 'operations.create.userIdentifiers[0].hashedEmail', email); - } else if (phone) { - phone = hashUserIdentifier ? sha256(phone).toString(): phone; - set(payload, 'operations.create.userIdentifiers[0].hashedPhoneNumber', phone); + const email = getFieldValueFromMessage(message, 'email'); + const phone = getFieldValueFromMessage(message, 'phone'); + + const userIdentifierInfo = { + email: hashUserIdentifier && isDefinedAndNotNull(email) ? sha256(email).toString() : email, + phone: hashUserIdentifier && isDefinedAndNotNull(phone) ? sha256(phone).toString() : phone, + address: buildAndGetAddress(message, hashUserIdentifier), + }; + + if (isDefinedAndNotNull(userIdentifierInfo[defaultUserIdentifier])) { + set( + payload, + `operations.create.userIdentifiers[0].${UserIdentifierFieldNameMap[defaultUserIdentifier]}`, + userIdentifierInfo[defaultUserIdentifier], + ); } else { - set(payload, 'operations.create.userIdentifiers[0]', {}); // if no user identifier is present + const keyName = getExisitingUserIdentifier(userIdentifierInfo, defaultUserIdentifier); + if (isDefinedAndNotNull(keyName)) { + set( + payload, + `operations.create.userIdentifiers[0].${UserIdentifierFieldNameMap[keyName]}`, + userIdentifierInfo[keyName], + ); + } else { + set(payload, 'operations.create.userIdentifiers[0]', {}); + } } return payload; }; const getStoreConversionPayload = (message, Config, event) => { const { validateOnly } = Config; - const payload = {}; - payload.event = event; - payload.isStoreConversion = true; - payload.createJobPayload = getCreateJobPayload(message); - payload.addConversionPayload = getAddConversionPayload(message, Config); - payload.executeJobPayload = { validate_only: validateOnly } + const payload = { + event, + isStoreConversion: true, + createJobPayload: getCreateJobPayload(message), + addConversionPayload: getAddConversionPayload(message, Config), + executeJobPayload: { validate_only: validateOnly }, + }; return payload; -} +}; const getClickConversionPayloadAndEndpoint = (message, Config, filteredCustomerId) => { - let email = getFieldValueFromMessage(message, 'email'); - let phone = getFieldValueFromMessage(message, 'phone'); - const { - hashUserIdentifier, - defaultUserIdentifier, - UserIdentifierSource, - conversionEnvironment - } = Config; + const email = getFieldValueFromMessage(message, 'emailOnly'); + const phone = getFieldValueFromMessage(message, 'phone'); + const { hashUserIdentifier, defaultUserIdentifier, UserIdentifierSource, conversionEnvironment } = + Config; const { properties } = message; // click conversions let updatedClickMapping = cloneDeep(trackClickConversionsMapping); @@ -279,7 +322,6 @@ const getClickConversionPayloadAndEndpoint = (message, Config, filteredCustomerI const payload = constructPayload(message, updatedClickMapping); - const endpoint = CLICK_CONVERSION.replace(':customerId', filteredCustomerId); const products = get(message, 'properties.products'); @@ -313,21 +355,28 @@ const getClickConversionPayloadAndEndpoint = (message, Config, filteredCustomerI // either of email or phone should be passed // defaultUserIdentifier depends on the webapp configuration // Ref - https://developers.google.com/google-ads/api/rest/reference/rest/v11/customers/uploadClickConversions#ClickConversion - if (defaultUserIdentifier === 'email' && email) { - email = hashUserIdentifier ? sha256(email).toString() : email; - set(payload, 'conversions[0].userIdentifiers[0].hashedEmail', email); - } else if (defaultUserIdentifier === 'phone' && phone) { - phone = hashUserIdentifier ? sha256(phone).toString() : phone; - set(payload, 'conversions[0].userIdentifiers[0].hashedPhoneNumber', phone); - } else if (email) { - // case when default choosen value is not present - email = hashUserIdentifier ? sha256(email).toString() : email; - set(payload, 'conversions[0].userIdentifiers[0].hashedEmail', email); - } else if (phone) { - phone = hashUserIdentifier ? sha256(phone).toString() : phone; - set(payload, 'conversions[0].userIdentifiers[0].hashedPhoneNumber', phone); - } + const userIdentifierInfo = { + email: hashUserIdentifier && isDefinedAndNotNull(email) ? sha256(email).toString() : email, + phone: hashUserIdentifier && isDefinedAndNotNull(phone) ? sha256(phone).toString() : phone, + }; + + if (isDefinedAndNotNull(userIdentifierInfo[defaultUserIdentifier])) { + set( + payload, + `conversions[0].userIdentifiers[0].${UserIdentifierFieldNameMap[defaultUserIdentifier]}`, + userIdentifierInfo[defaultUserIdentifier], + ); + } else { + const keyName = getExisitingUserIdentifier(userIdentifierInfo, defaultUserIdentifier); + if (isDefinedAndNotNull(keyName)) { + set( + payload, + `conversions[0].userIdentifiers[0].${UserIdentifierFieldNameMap[keyName]}`, + userIdentifierInfo[keyName], + ); + } + } // conversionEnvironment // if conversionEnvironment doesn't exist in properties // then it is taken from the webapp config @@ -335,15 +384,17 @@ const getClickConversionPayloadAndEndpoint = (message, Config, filteredCustomerI set(payload, 'conversions[0].conversionEnvironment', conversionEnvironment); } return { payload, endpoint }; -} +}; module.exports = { validateDestinationConfig, + generateItemListFromProducts, getAccessToken, getConversionActionId, removeHashToSha256TypeFromMappingJson, getStoreConversionPayload, requestBuilder, buildAndGetAddress, - getClickConversionPayloadAndEndpoint -}; \ No newline at end of file + getClickConversionPayloadAndEndpoint, + getExisitingUserIdentifier, +}; diff --git a/src/v0/destinations/google_adwords_offline_conversions/utils.test.js b/src/v0/destinations/google_adwords_offline_conversions/utils.test.js new file mode 100644 index 000000000000..775e123cfeec --- /dev/null +++ b/src/v0/destinations/google_adwords_offline_conversions/utils.test.js @@ -0,0 +1,275 @@ +const { + getClickConversionPayloadAndEndpoint, + buildAndGetAddress, + getExisitingUserIdentifier, +} = require('./utils'); + +const getTestMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + traits: { + email: 'abc@test.com', + firstname: 'rudder', + lastname: 'stack', + phone: 'dummy phone', + address: { + city: 'kolkata', + country: 'India', + state: 'WB', + street: 'T.N.G Road', + }, + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + properties: { + category: 'test', + email: 'test@test.com', + templateId: 1234, + campaignId: 5678, + name: 'pageName', + countryCode: 'IN', + zipCode: '700114', + conversionDateTime: '2022-01-01 12:32:45-08:00', + }, + context: { + device: { + token: 1234, + }, + os: { + token: 5678, + }, + mappedToDestination: false, + externalId: [ + { + id: '12345', + identifierType: 'test_identifier', + }, + ], + }, + }; + return message; +}; + +let userIdentifierInfo = { + email: 'testEmail', + phone: 'testPhone', + address: { + city: 'kolkata', + country_code: 'IN', + hashed_first_name: '37d80f43f43cd48f2e363a2d1f2aee343d7ba0a12a6227ee17b4ef3ede78c204', + hashed_last_name: '6ee08e6eb3bc6f45bc99fcd39fcc479286a1beb0c04d39f204c61762378075d6', + postal_code: '700114', + }, +}; + +let config = { + customerId: '962-581-2972', + subAccount: false, + eventsToOfflineConversionsTypeMapping: [ + { + from: 'Sign up completed', + to: 'click', + }, + { + from: 'Download', + to: 'call', + }, + { + from: 'Promotion Clicked', + to: 'click', + }, + { + from: 'Product Searched', + to: 'call', + }, + ], + eventsToConversionsNamesMapping: [ + { + from: 'Sign up completed', + to: 'Sign-up - click', + }, + { + from: 'Download', + to: 'Page view', + }, + { + from: 'Promotion Clicked', + to: 'Sign-up - click', + }, + { + from: 'Product Searched', + to: 'search', + }, + ], + customVariables: [ + { + from: 'value', + to: 'revenue', + }, + { + from: 'total', + to: 'cost', + }, + ], + UserIdentifierSource: 'THIRD_PARTY', + conversionEnvironment: 'WEB', + hashUserIdentifier: true, + defaultUserIdentifier: 'email', + validateOnly: false, + rudderAccountId: '2EOknn1JNH7WK1MfNku4fGYKkRK', +}; + +describe('buildAndGetAddress util tests', () => { + it('hashUserIdentifier as true', () => { + let expectedOutput = { + city: 'kolkata', + country_code: 'IN', + hashed_first_name: '37d80f43f43cd48f2e363a2d1f2aee343d7ba0a12a6227ee17b4ef3ede78c204', + hashed_last_name: '6ee08e6eb3bc6f45bc99fcd39fcc479286a1beb0c04d39f204c61762378075d6', + postal_code: '700114', + }; + expect(buildAndGetAddress(getTestMessage(), true)).toEqual(expectedOutput); + }); + it('hashUserIdentifier as false', () => { + let expectedOutput = { + city: 'kolkata', + country_code: 'IN', + hashed_first_name: 'rudder', + hashed_last_name: 'stack', + postal_code: '700114', + }; + expect(buildAndGetAddress(getTestMessage(), false)).toEqual(expectedOutput); + }); +}); + +describe('getExisitingUserIdentifier util tests', () => { + it('getExisitingUserIdentifier when default identifier is email and phone is present', () => { + expect(getExisitingUserIdentifier(userIdentifierInfo, 'email')).toEqual('phone'); + }); + + it('getExisitingUserIdentifier when default identifier is email and phone is absent', () => { + let fittingPayload = { ...userIdentifierInfo }; + fittingPayload.phone = undefined; + expect(getExisitingUserIdentifier(fittingPayload, 'email')).toEqual('address'); + }); + it('getExisitingUserIdentifier when default identifier is phone', () => { + expect(getExisitingUserIdentifier(userIdentifierInfo, 'phone')).toEqual('email'); + }); +}); + +describe('getClickConversionPayloadAndEndpoint util tests', () => { + it('getClickConversionPayloadAndEndpoint flow check when default field identifier is present', () => { + let expectedOutput = { + endpoint: 'https://googleads.googleapis.com/v13/customers/9625812972:uploadClickConversions', + payload: { + conversions: [ + { + conversionDateTime: '2022-01-01 12:32:45-08:00', + conversionEnvironment: 'WEB', + userIdentifiers: [ + { + hashedEmail: 'fa922cb41ff930664d4c9ced3c472ce7ecf29a0f8248b7018456e990177fff75', + userIdentifierSource: 'THIRD_PARTY', + }, + ], + }, + ], + }, + }; + expect(getClickConversionPayloadAndEndpoint(getTestMessage(), config, '9625812972')).toEqual( + expectedOutput, + ); + }); + + it('getClickConversionPayloadAndEndpoint flow check when default field identifier is absent', () => { + let fittingPayload = { ...getTestMessage() }; + delete fittingPayload.traits.email; + delete fittingPayload.properties.email; + let expectedOutput = { + endpoint: 'https://googleads.googleapis.com/v13/customers/9625812972:uploadClickConversions', + payload: { + conversions: [ + { + conversionDateTime: '2022-01-01 12:32:45-08:00', + conversionEnvironment: 'WEB', + userIdentifiers: [ + { + hashedPhoneNumber: + '2e0da1dbea5e4dc3ef73fde4de9329dd19f9030b384c169ff776002f45fd9a32', + userIdentifierSource: 'THIRD_PARTY', + }, + ], + }, + ], + }, + }; + expect(getClickConversionPayloadAndEndpoint(fittingPayload, config, '9625812972')).toEqual( + expectedOutput, + ); + }); + + it('getClickConversionPayloadAndEndpoint flow check when both email and phone are absent', () => { + let fittingPayload = { ...getTestMessage() }; + delete fittingPayload.traits.email; + delete fittingPayload.traits.phone; + delete fittingPayload.properties.email; + let expectedOutput = { + endpoint: 'https://googleads.googleapis.com/v13/customers/9625812972:uploadClickConversions', + payload: { + conversions: [ + { + conversionDateTime: '2022-01-01 12:32:45-08:00', + conversionEnvironment: 'WEB', + userIdentifiers: [ + { + hashedPhoneNumber: + '2e0da1dbea5e4dc3ef73fde4de9329dd19f9030b384c169ff776002f45fd9a32', + userIdentifierSource: 'THIRD_PARTY', + }, + ], + }, + ], + }, + }; + expect(() => + getClickConversionPayloadAndEndpoint(fittingPayload, config, '9625812972'), + ).toThrow('Either of email or phone is required for user identifier'); + }); + + it('getClickConversionPayloadAndEndpoint flow check when default field identifier is present and product list present', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [ + { + product_id: 1234, + sku: 'abcd', + name: 'no product array present', + category: 'categoryTest1, categoryTest2', + price: '10', + quantity: '2', + total: '20', + }, + ]; + let expectedOutput = { + endpoint: 'https://googleads.googleapis.com/v13/customers/9625812972:uploadClickConversions', + payload: { + conversions: [ + { + cartData: { items: [{ productId: 1234, quantity: 2, unitPrice: 10 }] }, + conversionDateTime: '2022-01-01 12:32:45-08:00', + conversionEnvironment: 'WEB', + userIdentifiers: [ + { + hashedEmail: 'fa922cb41ff930664d4c9ced3c472ce7ecf29a0f8248b7018456e990177fff75', + userIdentifierSource: 'THIRD_PARTY', + }, + ], + }, + ], + }, + }; + expect(getClickConversionPayloadAndEndpoint(fittingPayload, config, '9625812972')).toEqual( + expectedOutput, + ); + }); +}); diff --git a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js index 9ea522f98fb7..75347a137537 100644 --- a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js +++ b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js @@ -118,13 +118,8 @@ const gaAudienceProxyRequest = async (request) => { * @returns */ const getAuthErrCategory = (code, response) => { - switch (code) { - case 401: - if (!response.error.details) return REFRESH_TOKEN; - return ''; - default: - return ''; - } + if (code === 401 && !response.error.details) return REFRESH_TOKEN; + return ''; }; const gaAudienceRespHandler = (destResponse, stageMsg) => { diff --git a/src/v0/destinations/google_adwords_remarketing_lists/transform.js b/src/v0/destinations/google_adwords_remarketing_lists/transform.js index a0d20b12e4b5..9aaae3dbe3e3 100644 --- a/src/v0/destinations/google_adwords_remarketing_lists/transform.js +++ b/src/v0/destinations/google_adwords_remarketing_lists/transform.js @@ -24,6 +24,7 @@ const { hashAttributes, TYPEOFLIST, } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const hashEncrypt = (object) => { Object.keys(object).forEach((key) => { @@ -73,7 +74,7 @@ const responseBuilder = (metadata, body, { Config }) => { response.params = { listId: Config.listId, customerId: filteredCustomerId }; response.headers = { Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'developer-token': getValueFromMessage(metadata, 'secret.developer_token'), }; if (Config.subAccount) diff --git a/src/v0/destinations/google_cloud_function/util.js b/src/v0/destinations/google_cloud_function/util.js index 6b299b21831e..10c4365b774f 100644 --- a/src/v0/destinations/google_cloud_function/util.js +++ b/src/v0/destinations/google_cloud_function/util.js @@ -1,4 +1,5 @@ const { defaultBatchRequestConfig } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { ConfigurationError } = require('../../util/errorTypes'); const { TRIGGERTYPE } = require('./config'); @@ -28,7 +29,7 @@ const validateDestinationConfig = ({ Config }) => { function addHeader(response, Config) { const { triggerType, apiKeyId, gcloudAuthorization } = Config; - response.headers = { 'content-type': 'application/json' }; + response.headers = { 'content-type': JSON_MIME_TYPE }; if (apiKeyId) { const basicAuth = Buffer.from(`apiKey:${apiKeyId}`).toString('base64'); response.headers.ApiKey = `Basic ${basicAuth}`; diff --git a/src/v0/destinations/googlesheets/transform.js b/src/v0/destinations/googlesheets/transform.js index 67241c0a3140..6cfb3f1d1e7d 100644 --- a/src/v0/destinations/googlesheets/transform.js +++ b/src/v0/destinations/googlesheets/transform.js @@ -68,10 +68,7 @@ const processWithCustomMapping = (message, attributeKeyMapping) => { // Check in free-flowing object level SOURCE_KEYS.some((sourceKey) => { value = getMappingFieldValueFormMessage(message, sourceKey, mapping[fromKey]); - if (value) { - return true; - } - return false; + return !!value; }); } // Set the value if present else set an empty string diff --git a/src/v0/destinations/heap/transform.js b/src/v0/destinations/heap/transform.js index 36843062c4db..32196eb7beec 100644 --- a/src/v0/destinations/heap/transform.js +++ b/src/v0/destinations/heap/transform.js @@ -9,6 +9,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(message, category, destination) { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); @@ -28,8 +29,8 @@ function responseBuilderSimple(message, category, destination) { response.endpoint = category.endPoint; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, }; response.userId = message.anonymousId; response.body.JSON = removeUndefinedAndNullValues(responseBody); diff --git a/src/v0/destinations/hs/HSTransform-v1.js b/src/v0/destinations/hs/HSTransform-v1.js index 4302526d75f7..13eeabbc4556 100644 --- a/src/v0/destinations/hs/HSTransform-v1.js +++ b/src/v0/destinations/hs/HSTransform-v1.js @@ -35,6 +35,7 @@ const { formatPropertyValueForIdentify, getHsSearchId, } = require('./util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * using legacy API @@ -104,7 +105,7 @@ const processLegacyIdentify = async (message, destination, propertyMap) => { response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; // choosing API Type @@ -156,7 +157,7 @@ const processLegacyTrack = async (message, destination, propertyMap) => { response.endpoint = TRACK_ENDPOINT; response.method = defaultGetRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.messageType = 'track'; @@ -349,7 +350,7 @@ const legacyBatchEvents = (destEvents) => { }); batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; // choosing API Type diff --git a/src/v0/destinations/hs/HSTransform-v2.js b/src/v0/destinations/hs/HSTransform-v2.js index b4682aebbb80..8cea4611e55d 100644 --- a/src/v0/destinations/hs/HSTransform-v2.js +++ b/src/v0/destinations/hs/HSTransform-v2.js @@ -42,6 +42,7 @@ const { getEventAndPropertiesFromConfig, getHsSearchId, } = require('./util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const addHsAuthentication = (response, Config) => { // choosing API Type @@ -95,7 +96,7 @@ const processIdentify = async (message, destination, propertyMap) => { type: associationTypeId, }; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.operation = RETL_CREATE_ASSOCIATION_OPERATION; response.source = RETL_SOURCE; @@ -160,7 +161,7 @@ const processIdentify = async (message, destination, propertyMap) => { response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; // choosing API Type @@ -209,7 +210,7 @@ const processTrack = async (message, destination) => { response.endpoint = TRACK_CRM_ENDPOINT; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = removeUndefinedAndNullValues(payload); response.messageType = 'track'; diff --git a/src/v0/destinations/hs/transform.js b/src/v0/destinations/hs/transform.js index cafd2d58f033..3f8010ff492e 100644 --- a/src/v0/destinations/hs/transform.js +++ b/src/v0/destinations/hs/transform.js @@ -70,7 +70,8 @@ const process = async (event) => { // we are batching by default at routerTransform const processRouterDest = async (inputs, reqMetadata) => { - const errorRespEvents = checkInvalidRtTfEvents(inputs); + let tempInputs = inputs; + const errorRespEvents = checkInvalidRtTfEvents(tempInputs); if (errorRespEvents.length > 0) { return errorRespEvents; } @@ -78,21 +79,21 @@ const processRouterDest = async (inputs, reqMetadata) => { const successRespList = []; const errorRespList = []; // using the first destination config for transforming the batch - const { destination } = inputs[0]; + const { destination } = tempInputs[0]; let propertyMap; - const mappedToDestination = get(inputs[0].message, MappedToDestinationKey); - const { objectType } = getDestinationExternalIDInfoForRetl(inputs[0].message, 'HS'); + const mappedToDestination = get(tempInputs[0].message, MappedToDestinationKey); + const { objectType } = getDestinationExternalIDInfoForRetl(tempInputs[0].message, 'HS'); try { if (mappedToDestination && GENERIC_TRUE_VALUES.includes(mappedToDestination?.toString())) { // skip splitting the batches to inserts and updates if object it is an association if (objectType.toLowerCase() !== 'association') { // get info about existing objects and splitting accordingly. - inputs = await splitEventsForCreateUpdate(inputs, destination); + tempInputs = await splitEventsForCreateUpdate(tempInputs, destination); } } else { // reduce the no. of calls for properties endpoint - const traitsFound = inputs.some( + const traitsFound = tempInputs.some( (input) => fetchFinalSetOfTraits(input.message) !== undefined, ); if (traitsFound) { @@ -101,11 +102,11 @@ const processRouterDest = async (inputs, reqMetadata) => { } } catch (error) { // Any error thrown from the above try block applies to all the events - return inputs.map((input) => handleRtTfSingleEventError(input, error, reqMetadata)); + return tempInputs.map((input) => handleRtTfSingleEventError(input, error, reqMetadata)); } await Promise.all( - inputs.map(async (input) => { + tempInputs.map(async (input) => { try { if (input.message.statusCode) { // already transformed event diff --git a/src/v0/destinations/hs/util.js b/src/v0/destinations/hs/util.js index 296ef331c8fc..5af31ec7c4a7 100644 --- a/src/v0/destinations/hs/util.js +++ b/src/v0/destinations/hs/util.js @@ -28,6 +28,7 @@ const { } = require('./config'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * validate destination config and check for existence of data @@ -92,7 +93,7 @@ const getProperties = async (destination) => { // Private Apps const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${Config.accessToken}`, }, }; @@ -274,10 +275,7 @@ const getLookupFieldValue = (message, lookupField) => { // Check in free-flowing object level SOURCE_KEYS.some((sourceKey) => { value = getMappingFieldValueFormMessage(message, sourceKey, lookupField); - if (value) { - return true; - } - return false; + return !!value; }); } const lookupValueInfo = value ? { fieldName: lookupField, value } : null; @@ -327,7 +325,7 @@ const searchContacts = async (message, destination) => { // Private Apps const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${Config.accessToken}`, }, }; @@ -473,7 +471,7 @@ const getExistingData = async (inputs, destination) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${Config.accessToken}`, }, }; diff --git a/src/v0/destinations/indicative/transform.js b/src/v0/destinations/indicative/transform.js index e3bad80ea8c1..81eb19f320ee 100644 --- a/src/v0/destinations/indicative/transform.js +++ b/src/v0/destinations/indicative/transform.js @@ -10,6 +10,7 @@ const { } = require('../../util'); const { getUAInfo } = require('./utils'); const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const handleProperties = (properties) => { const result = {}; @@ -119,7 +120,7 @@ const responseBuilderSimple = (message, category, destination) => { response.method = defaultPostRequestConfig.requestMethod; response.headers = { 'Indicative-Client': 'RudderStack', - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.userId = getFieldValueFromMessage(message, 'userId'); response.body.JSON = responseBody; diff --git a/src/v0/destinations/intercom/config.js b/src/v0/destinations/intercom/config.js index 9382592334fb..7949320c0132 100644 --- a/src/v0/destinations/intercom/config.js +++ b/src/v0/destinations/intercom/config.js @@ -7,7 +7,7 @@ const TRACK_ENDPOINT = `${BASE_ENDPOINT}/events`; // Create, Update a user with a company | Identify const IDENTIFY_ENDPOINT = `${BASE_ENDPOINT}/users`; // create, update, delete a company | Group -// const GROUP_ENDPOINT = `${BASE_ENDPOINT}/companies`; +const GROUP_ENDPOINT = `${BASE_ENDPOINT}/companies`; const ConfigCategory = { TRACK: { @@ -18,11 +18,10 @@ const ConfigCategory = { endpoint: IDENTIFY_ENDPOINT, name: 'INTERCOMIdentifyConfig', }, - // , - // GROUP: { - // endpoint: GROUP_ENDPOINT, - // name: "INTERCOMGroupConfig" - // } + GROUP: { + endpoint: GROUP_ENDPOINT, + name: 'INTERCOMGroupConfig', + }, }; const MappingConfig = getMappingConfig(ConfigCategory, __dirname); diff --git a/src/v0/destinations/intercom/data/INTERCOMGroupConfig.json b/src/v0/destinations/intercom/data/INTERCOMGroupConfig.json index e69de29bb2d1..174f828a56c8 100644 --- a/src/v0/destinations/intercom/data/INTERCOMGroupConfig.json +++ b/src/v0/destinations/intercom/data/INTERCOMGroupConfig.json @@ -0,0 +1,53 @@ +[ + { + "destKey": "company_id", + "sourceKeys": "groupId", + "required": true + }, + { + "destKey": "name", + "sourceKeys": "name", + "sourceFromGenericMap": true, + "required": false + }, + { + "destKey": "plan", + "sourceKeys": ["traits.plan","context.traits.plan"], + "required": false + }, + { + "destKey": "size", + "sourceKeys": ["traits.size","context.traits.size"], + "metadata": { + "type": "toNumber" + }, + "required": false + }, + { + "destKey": "website", + "sourceKeys": "website", + "sourceFromGenericMap": true, + "required": false + }, + { + "destKey": "industry", + "sourceKeys": ["traits.industry","context.traits.industry"], + "required": false + }, + { + "destKey": "monthly_spend", + "sourceKeys": ["traits.monthlySpend","context.traits.monthlySpend"], + "metadata": { + "type": "toNumber" + }, + "required": false + }, + { + "destKey": "remote_created_at", + "sourceKeys": ["traits.remoteCreatedAt","context.traits.remoteCreatedAt"], + "metadata": { + "type": "toNumber" + }, + "required": false + } +] diff --git a/src/v0/destinations/intercom/deleteUsers.js b/src/v0/destinations/intercom/deleteUsers.js index 990ca074cea1..622d55150385 100644 --- a/src/v0/destinations/intercom/deleteUsers.js +++ b/src/v0/destinations/intercom/deleteUsers.js @@ -5,6 +5,7 @@ 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'); // Ref-> https://developers.intercom.com/intercom-api-reference/v1.3/reference/permanently-delete-a-user const userDeletionHandler = async (userAttributes, config) => { @@ -31,7 +32,7 @@ const userDeletionHandler = async (userAttributes, config) => { const requestOptions = { headers: { Authorization: `Bearer ${apiKey}`, - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }, }; const resp = await httpPOST(url, data, requestOptions); diff --git a/src/v0/destinations/intercom/transform.js b/src/v0/destinations/intercom/transform.js index 2df1429536f4..47b33c62115d 100644 --- a/src/v0/destinations/intercom/transform.js +++ b/src/v0/destinations/intercom/transform.js @@ -17,6 +17,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function getCompanyAttribute(company) { const companiesList = []; @@ -89,9 +90,78 @@ function validateTrack(message, payload) { throw new InstrumentationError('Email or userId is mandatory'); } +function attachUserAndCompany(message, Config) { + const email = message.context?.traits?.email; + const { userId } = message; + if (!userId && !email) { + return false; + } + const requestBody = {}; + if (userId) { + requestBody.user_id = userId; + } + if (email) { + requestBody.email = email; + } + const companyObj = { + company_id: message.groupId, + }; + if (message.traits?.name) { + companyObj.name = message.traits.name; + } + requestBody.companies = [companyObj]; + let response = defaultRequestConfig(); + response.method = defaultPostRequestConfig.requestMethod; + response.endpoint = ConfigCategory.IDENTIFY.endpoint; + response.headers = { + 'Content-Type': JSON_MIME_TYPE, + Authorization: `Bearer ${Config.apiKey}`, + Accept: JSON_MIME_TYPE, + 'Intercom-Version': '1.4', + }; + response.body.JSON = requestBody; + return response; +} + +function buildCustomAttributes(message, payload) { + const { traits } = message; + const customAttributes = {}; + const companyReservedKeys = [ + "remoteCreatedAt", + "monthlySpend", + "industry", + "website", + "size", + "plan", + "name" + ]; + + if (traits) { + Object.keys(traits).forEach((key) => { + if (!companyReservedKeys.includes(key) && key !== "userId") { + customAttributes[key] = traits[key]; + } + }) + } + + if (Object.keys(customAttributes).length > 0) { + payload.custom_attributes = customAttributes; + } +} + function validateAndBuildResponse(message, payload, category, destination) { + const respList = []; + let response = defaultRequestConfig(); + response.method = defaultPostRequestConfig.requestMethod; + response.endpoint = category.endpoint; + response.headers = { + 'Content-Type': JSON_MIME_TYPE, + Authorization: `Bearer ${destination.Config.apiKey}`, + Accept: JSON_MIME_TYPE, + 'Intercom-Version': '1.4', + }; + response.userId = message.anonymousId; const messageType = message.type.toLowerCase(); - const response = defaultRequestConfig(); switch (messageType) { case EventType.IDENTIFY: response.body.JSON = removeUndefinedAndNullValues(validateIdentify(message, payload)); @@ -99,20 +169,23 @@ function validateAndBuildResponse(message, payload, category, destination) { case EventType.TRACK: response.body.JSON = removeUndefinedAndNullValues(validateTrack(message, payload)); break; + case EventType.GROUP: { + buildCustomAttributes(message, payload); + response.body.JSON = removeUndefinedAndNullValues(payload); + respList.push(response); + const attachUserAndCompanyResponse = + attachUserAndCompany(message, destination.Config); + if (attachUserAndCompanyResponse) { + attachUserAndCompanyResponse.userId = message.anonymousId; + respList.push(attachUserAndCompanyResponse); + } + break; + } default: throw new InstrumentationError(`Message type ${messageType} not supported`); } - response.method = defaultPostRequestConfig.requestMethod; - response.endpoint = category.endpoint; - response.headers = { - 'Content-Type': 'application/json', - Authorization: `Bearer ${destination.Config.apiKey}`, - Accept: 'application/json', - 'Intercom-Version': '1.4', - }; - response.userId = message.anonymousId; - return response; + return (messageType === EventType.GROUP) ? respList : response; } function processSingleMessage(message, destination) { @@ -130,9 +203,9 @@ function processSingleMessage(message, destination) { case EventType.TRACK: category = ConfigCategory.TRACK; break; - // case EventType.GROUP: - // category = ConfigCategory.GROUP; - // break; + case EventType.GROUP: + category = ConfigCategory.GROUP; + break; default: throw new InstrumentationError(`Message type ${messageType} not supported`); } diff --git a/src/v0/destinations/iterable/transform.js b/src/v0/destinations/iterable/transform.js index be5a7fbf21bc..329b2df8739c 100644 --- a/src/v0/destinations/iterable/transform.js +++ b/src/v0/destinations/iterable/transform.js @@ -1,6 +1,16 @@ const _ = require('lodash'); const get = require('get-value'); -const { getCatalogEndpoint } = require('./util'); +const { + getCatalogEndpoint, + identifyDeviceAction, + identifyBrowserAction, + identifyAction, + pageAction, + screenAction, + trackAction, + trackPurchaseAction, + updateCartAction, +} = require('./util'); const { EventType, MappedToDestinationKey } = require('../../../constants'); const { ConfigCategory, @@ -17,198 +27,42 @@ const { defaultRequestConfig, constructPayload, getSuccessRespEvents, - addExternalIdToTraits, - isAppleFamily, handleRtTfSingleEventError, checkInvalidRtTfEvents, getDestinationExternalIDInfoForRetl, } = require('../../util'); const logger = require('../../../logger'); -const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); - -function validateMandatoryField(payload) { - if (payload.email === undefined && payload.userId === undefined) { - throw new InstrumentationError('userId or email is mandatory for this request'); - } -} +const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function constructPayloadItem(message, category, destination) { - const rawPayloadItemArr = []; + // const rawPayloadItemArr = []; let rawPayload = {}; switch (category.action) { case 'identifyDevice': - rawPayload = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY_DEVICE.name]); - rawPayload.device = constructPayload(message, mappingConfig[ConfigCategory.DEVICE.name]); - rawPayload.preferUserId = true; - if (isAppleFamily(message.context.device.type)) { - rawPayload.device.platform = 'APNS'; - } else { - rawPayload.device.platform = 'GCM'; - } + rawPayload = identifyDeviceAction(message); break; case 'identifyBrowser': - rawPayload = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY_BROWSER.name]); - validateMandatoryField(rawPayload); + rawPayload = identifyBrowserAction(message); break; case 'identify': - // If mapped to destination, Add externalId to traits - if (get(message, MappedToDestinationKey)) { - addExternalIdToTraits(message); - } - rawPayload = constructPayload(message, mappingConfig[category.name]); - rawPayload.preferUserId = true; - rawPayload.mergeNestedObjects = true; - validateMandatoryField(rawPayload); + rawPayload = identifyAction(message, category); break; case 'page': - if (destination.Config.trackAllPages) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else if ( - destination.Config.trackCategorisedPages && - ((message.properties && message.properties.category) || message.category) - ) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else if ( - destination.Config.trackNamedPages && - ((message.properties && message.properties.name) || message.name) - ) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else { - throw new ConfigurationError('Invalid page call'); - } - validateMandatoryField(rawPayload); - if (destination.Config.mapToSingleEvent) { - rawPayload.eventName = 'Loaded a Page'; - } else { - rawPayload.eventName += ' page'; - } - rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); - if (rawPayload.campaignId) { - rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); - } - if (rawPayload.templateId) { - rawPayload.templateId = parseInt(rawPayload.templateId, 10); - } + rawPayload = pageAction(message, destination, category); break; case 'screen': - if (destination.Config.trackAllPages) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else if ( - destination.Config.trackCategorisedPages && - ((message.properties && message.properties.category) || message.category) - ) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else if ( - destination.Config.trackNamedPages && - ((message.properties && message.properties.name) || message.name) - ) { - rawPayload = constructPayload(message, mappingConfig[category.name]); - } else { - throw new ConfigurationError('Invalid screen call'); - } - validateMandatoryField(rawPayload); - if (destination.Config.mapToSingleEvent) { - rawPayload.eventName = 'Loaded a Screen'; - } else { - rawPayload.eventName += ' screen'; - } - rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); - if (rawPayload.campaignId) { - rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); - } - if (rawPayload.templateId) { - rawPayload.templateId = parseInt(rawPayload.templateId, 10); - } + rawPayload = screenAction(message, destination, category); break; case 'track': - rawPayload = constructPayload(message, mappingConfig[category.name]); - validateMandatoryField(rawPayload); - rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); - if (rawPayload.campaignId) { - rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); - } - if (rawPayload.templateId) { - rawPayload.templateId = parseInt(rawPayload.templateId, 10); - } + rawPayload = trackAction(message, category); break; case 'trackPurchase': - rawPayload = constructPayload(message, mappingConfig[category.name]); - rawPayload.user = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY.name]); - validateMandatoryField(rawPayload.user); - rawPayload.user.preferUserId = true; - rawPayload.user.mergeNestedObjects = true; - rawPayload.items = message.properties.products; - if (rawPayload.items && Array.isArray(rawPayload.items)) { - rawPayload.items.forEach((el) => { - const element = constructPayload(el, mappingConfig[ConfigCategory.PRODUCT.name]); - if (element.categories && typeof element.categories === 'string') { - element.categories = element.categories.split(','); - } - element.price = parseFloat(element.price); - element.quantity = parseInt(element.quantity, 10); - const clone = { ...element }; - rawPayloadItemArr.push(clone); - }); - } else { - const element = constructPayload( - message.properties, - mappingConfig[ConfigCategory.PRODUCT.name], - ); - if (element.categories && typeof element.categories === 'string') { - element.categories = element.categories.split(','); - } - element.price = parseFloat(element.price); - element.quantity = parseInt(element.quantity, 10); - const clone = { ...element }; - rawPayloadItemArr.push(clone); - } - - rawPayload.items = rawPayloadItemArr; - rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); - rawPayload.total = parseFloat(rawPayload.total); - if (rawPayload.id) { - rawPayload.id = rawPayload.id.toString(); - } - if (rawPayload.campaignId) { - rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); - } - if (rawPayload.templateId) { - rawPayload.templateId = parseInt(rawPayload.templateId, 10); - } + rawPayload = trackPurchaseAction(message, category); break; case 'updateCart': - rawPayload.user = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY.name]); - validateMandatoryField(rawPayload.user); - rawPayload.user.preferUserId = true; - rawPayload.user.mergeNestedObjects = true; - rawPayload.items = message.properties.products; - if (rawPayload.items && Array.isArray(rawPayload.items)) { - rawPayload.items.forEach((el) => { - const element = constructPayload(el, mappingConfig[ConfigCategory.PRODUCT.name]); - if (element.categories && typeof element.categories === 'string') { - element.categories = element.categories.split(','); - } - element.price = parseFloat(element.price); - element.quantity = parseInt(element.quantity, 10); - const clone = { ...element }; - rawPayloadItemArr.push(clone); - }); - } else { - const element = constructPayload( - message.properties, - mappingConfig[ConfigCategory.PRODUCT.name], - ); - if (element.categories && typeof element.categories === 'string') { - element.categories = element.categories.split(','); - } - element.price = parseFloat(element.price); - element.quantity = parseInt(element.quantity, 10); - const clone = { ...element }; - rawPayloadItemArr.push(clone); - } - - rawPayload.items = rawPayloadItemArr; + rawPayload = updateCartAction(message); break; case 'alias': rawPayload = constructPayload(message, mappingConfig[category.name]); @@ -234,7 +88,7 @@ function responseBuilderSimple(message, category, destination) { response.operation = 'catalogs'; } response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, api_key: destination.Config.apiKey, }; return response; @@ -261,12 +115,28 @@ function responseBuilderSimpleForIdentify(message, category, destination) { } response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, api_key: destination.Config.apiKey, }; return response; } +function getCategoryUsingEventName(event) { + let category; + switch (event) { + case 'order completed': + category = ConfigCategory.TRACK_PURCHASE; + break; + case 'product added': + case 'product removed': + category = ConfigCategory.UPDATE_CART; + break; + default: + category = ConfigCategory.TRACK; + } + return category; +} + function processSingleMessage(message, destination) { const messageType = message.type.toLowerCase(); let category = {}; @@ -292,17 +162,7 @@ function processSingleMessage(message, destination) { break; case EventType.TRACK: event = message.event.toLowerCase(); - switch (event) { - case 'order completed': - category = ConfigCategory.TRACK_PURCHASE; - break; - case 'product added': - case 'product removed': - category = ConfigCategory.UPDATE_CART; - break; - default: - category = ConfigCategory.TRACK; - } + category = getCategoryUsingEventName(event); break; case EventType.ALIAS: category = ConfigCategory.ALIAS; @@ -392,7 +252,7 @@ function batchEvents(arrayChunks) { } batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, api_key: apiKey, }; diff --git a/src/v0/destinations/iterable/util.js b/src/v0/destinations/iterable/util.js index aabe408a3611..6f3bafe48143 100644 --- a/src/v0/destinations/iterable/util.js +++ b/src/v0/destinations/iterable/util.js @@ -1,8 +1,236 @@ -const { getDestinationExternalIDInfoForRetl } = require('../../util'); +const get = require('get-value'); +const { + getDestinationExternalIDInfoForRetl, + constructPayload, + isAppleFamily, + addExternalIdToTraits, +} = require('../../util'); +const { ConfigCategory, mappingConfig } = require('./config'); + +const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { MappedToDestinationKey } = require('../../../constants'); const getCatalogEndpoint = (category, message) => { const externalIdInfo = getDestinationExternalIDInfoForRetl(message, 'ITERABLE'); return `${category.endpoint}/${externalIdInfo.objectType}/items/${externalIdInfo.destinationExternalId}`; }; -module.exports = { getCatalogEndpoint }; +function validateMandatoryField(payload) { + if (payload.email === undefined && payload.userId === undefined) { + throw new InstrumentationError('userId or email is mandatory for this request'); + } +} + +const identifyDeviceAction = (message) => { + let rawPayload = {}; + rawPayload = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY_DEVICE.name]); + rawPayload.device = constructPayload(message, mappingConfig[ConfigCategory.DEVICE.name]); + rawPayload.preferUserId = true; + if (isAppleFamily(message.context.device.type)) { + rawPayload.device.platform = 'APNS'; + } else { + rawPayload.device.platform = 'GCM'; + } + return rawPayload; +}; + +const identifyBrowserAction = (message) => { + const rawPayload = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY_BROWSER.name]); + validateMandatoryField(rawPayload); + return rawPayload; +}; + +const identifyAction = (message, category) => { + // If mapped to destination, Add externalId to traits + if (get(message, MappedToDestinationKey)) { + addExternalIdToTraits(message); + } + const rawPayload = constructPayload(message, mappingConfig[category.name]); + rawPayload.preferUserId = true; + rawPayload.mergeNestedObjects = true; + validateMandatoryField(rawPayload); + return rawPayload; +}; + +const pageAction = (message, destination, category) => { + let rawPayload = {}; + if (destination.Config.trackAllPages) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else if ( + destination.Config.trackCategorisedPages && + ((message.properties && message.properties.category) || message.category) + ) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else if ( + destination.Config.trackNamedPages && + ((message.properties && message.properties.name) || message.name) + ) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else { + throw new ConfigurationError('Invalid page call'); + } + validateMandatoryField(rawPayload); + if (destination.Config.mapToSingleEvent) { + rawPayload.eventName = 'Loaded a Page'; + } else { + rawPayload.eventName += ' page'; + } + rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); + if (rawPayload.campaignId) { + rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); + } + if (rawPayload.templateId) { + rawPayload.templateId = parseInt(rawPayload.templateId, 10); + } + + return rawPayload; +}; + +const screenAction = (message, destination, category) => { + let rawPayload = {}; + if (destination.Config.trackAllPages) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else if ( + destination.Config.trackCategorisedPages && + ((message.properties && message.properties.category) || message.category) + ) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else if ( + destination.Config.trackNamedPages && + ((message.properties && message.properties.name) || message.name) + ) { + rawPayload = constructPayload(message, mappingConfig[category.name]); + } else { + throw new ConfigurationError('Invalid screen call'); + } + validateMandatoryField(rawPayload); + if (destination.Config.mapToSingleEvent) { + rawPayload.eventName = 'Loaded a Screen'; + } else { + rawPayload.eventName += ' screen'; + } + rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); + if (rawPayload.campaignId) { + rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); + } + if (rawPayload.templateId) { + rawPayload.templateId = parseInt(rawPayload.templateId, 10); + } + + return rawPayload; +}; + +const trackAction = (message, category) => { + let rawPayload = {}; + rawPayload = constructPayload(message, mappingConfig[category.name]); + validateMandatoryField(rawPayload); + rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); + if (rawPayload.campaignId) { + rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); + } + if (rawPayload.templateId) { + rawPayload.templateId = parseInt(rawPayload.templateId, 10); + } + + return rawPayload; +}; + +const trackPurchaseAction = (message, category) => { + let rawPayload = {}; + const rawPayloadItemArr = []; + rawPayload = constructPayload(message, mappingConfig[category.name]); + rawPayload.user = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY.name]); + validateMandatoryField(rawPayload.user); + rawPayload.user.preferUserId = true; + rawPayload.user.mergeNestedObjects = true; + rawPayload.items = message.properties.products; + if (rawPayload.items && Array.isArray(rawPayload.items)) { + rawPayload.items.forEach((el) => { + const element = constructPayload(el, mappingConfig[ConfigCategory.PRODUCT.name]); + if (element.categories && typeof element.categories === 'string') { + element.categories = element.categories.split(','); + } + element.price = parseFloat(element.price); + element.quantity = parseInt(element.quantity, 10); + const clone = { ...element }; + rawPayloadItemArr.push(clone); + }); + } else { + const element = constructPayload( + message.properties, + mappingConfig[ConfigCategory.PRODUCT.name], + ); + if (element.categories && typeof element.categories === 'string') { + element.categories = element.categories.split(','); + } + element.price = parseFloat(element.price); + element.quantity = parseInt(element.quantity, 10); + const clone = { ...element }; + rawPayloadItemArr.push(clone); + } + + rawPayload.items = rawPayloadItemArr; + rawPayload.createdAt = new Date(rawPayload.createdAt).getTime(); + rawPayload.total = parseFloat(rawPayload.total); + if (rawPayload.id) { + rawPayload.id = rawPayload.id.toString(); + } + if (rawPayload.campaignId) { + rawPayload.campaignId = parseInt(rawPayload.campaignId, 10); + } + if (rawPayload.templateId) { + rawPayload.templateId = parseInt(rawPayload.templateId, 10); + } + + return rawPayload; +}; + +const updateCartAction = (message) => { + const rawPayload = { + items: message.properties.products, + }; + const rawPayloadItemArr = []; + rawPayload.user = constructPayload(message, mappingConfig[ConfigCategory.IDENTIFY.name]); + validateMandatoryField(rawPayload.user); + rawPayload.user.preferUserId = true; + rawPayload.user.mergeNestedObjects = true; + if (rawPayload.items && Array.isArray(rawPayload.items)) { + rawPayload.items.forEach((el) => { + const element = constructPayload(el, mappingConfig[ConfigCategory.PRODUCT.name]); + if (element.categories && typeof element.categories === 'string') { + element.categories = element.categories.split(','); + } + element.price = parseFloat(element.price); + element.quantity = parseInt(element.quantity, 10); + const clone = { ...element }; + rawPayloadItemArr.push(clone); + }); + } else { + const element = constructPayload( + message.properties, + mappingConfig[ConfigCategory.PRODUCT.name], + ); + if (element.categories && typeof element.categories === 'string') { + element.categories = element.categories.split(','); + } + element.price = parseFloat(element.price); + element.quantity = parseInt(element.quantity, 10); + const clone = { ...element }; + rawPayloadItemArr.push(clone); + } + + rawPayload.items = rawPayloadItemArr; + return rawPayload; +}; + +module.exports = { + getCatalogEndpoint, + identifyDeviceAction, + identifyBrowserAction, + identifyAction, + pageAction, + screenAction, + trackAction, + trackPurchaseAction, + updateCartAction, +}; diff --git a/src/v0/destinations/iterable/util.test.js b/src/v0/destinations/iterable/util.test.js new file mode 100644 index 000000000000..ffcabca27dc0 --- /dev/null +++ b/src/v0/destinations/iterable/util.test.js @@ -0,0 +1,737 @@ +const { + identifyDeviceAction, + identifyBrowserAction, + identifyAction, + pageAction, + screenAction, + trackAction, + trackPurchaseAction, + updateCartAction, +} = require('./util'); + +const { ConfigCategory } = require('./config'); + +const getTestMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + traits: { + email: 'abc@test.com', + name: 'rudder', + address: { + city: 'kolkata', + country: 'India', + }, + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + properties: { + category: 'test', + email: 'test@test.com', + templateId: 1234, + campaignId: 5678, + name: 'pageName', + }, + context: { + device: { + token: 1234, + }, + os: { + token: 5678, + }, + mappedToDestination: false, + externalId: [ + { + id: '12345', + identifierType: 'test_identifier', + }, + ], + }, + }; + return message; +}; + +const getTestEcommMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + traits: { + userId: 'userId', + email: 'abc@test.com', + name: 'rudder', + address: { + city: 'kolkata', + country: 'India', + }, + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + properties: { + product_id: 1234, + sku: 'abcd', + name: 'no product array present', + category: 'categoryTest1, categoryTest2', + price: '10', + quantity: '2', + total: '20', + campaignId: '1111', + templateId: '2222', + }, + context: { + device: { + token: 1234, + }, + os: { + token: 5678, + }, + mappedToDestination: false, + externalId: [ + { + id: '12345', + identifierType: 'test_identifier', + }, + ], + }, + }; + return message; +}; + +describe('iterable utils test', () => { + describe('Unit test cases for iterable identifyDeviceAction', () => { + it('for no device type', async () => { + let expectedOutput = { + device: { + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + platform: 'GCM', + token: 1234, + }, + email: 'abc@test.com', + preferUserId: true, + userId: 'anonId', + }; + expect(identifyDeviceAction(getTestMessage())).toEqual(expectedOutput); + }); + it('For apple family device type', async () => { + const fittingPayload = { ...getTestMessage() }; + fittingPayload.context.device.type = 'ios'; + let expectedOutput = { + device: { + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + platform: 'APNS', + token: 1234, + }, + email: 'abc@test.com', + preferUserId: true, + userId: 'anonId', + }; + expect(identifyDeviceAction(fittingPayload)).toEqual(expectedOutput); + }); + + it('For non apple family device type', async () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.context.device.type = 'android'; + let expectedOutput = { + device: { + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + platform: 'GCM', + token: 1234, + }, + email: 'abc@test.com', + preferUserId: true, + userId: 'anonId', + }; + expect(identifyDeviceAction(fittingPayload)).toEqual(expectedOutput); + }); + }); + describe('Unit test cases for iterable identifyBrowserAction', () => { + it('flow check', async () => { + let expectedOutput = { browserToken: 5678, email: 'abc@test.com', userId: 'anonId' }; + expect(identifyBrowserAction(getTestMessage())).toEqual(expectedOutput); + }); + }); + describe('Unit test cases for iterable identifyAction', () => { + it('flow check without externalId', async () => { + let expectedOutput = { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'anonId', + }; + expect(identifyAction(getTestMessage(), ConfigCategory.IDENTIFY)).toEqual(expectedOutput); + }); + + it('flow check with externalId', async () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.context.mappedToDestination = true; + let expectedOutput = { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + test_identifier: '12345', + timestamp: '2014-05-21T15:54:20Z', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'anonId', + }; + expect(identifyAction(fittingPayload, ConfigCategory.IDENTIFY)).toEqual(expectedOutput); + }); + }); + describe('Unit test cases for iterbale pageAction', () => { + it('For trackAllPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: true, + trackCategorisedPages: false, + trackNamedPages: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName page', + templateId: 1234, + userId: 'anonId', + }; + expect(pageAction(getTestMessage(), destination, ConfigCategory.PAGE)).toEqual( + expectedOutput, + ); + }); + + it('For trackCategorisedPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: true, + trackNamedPages: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName page', + templateId: 1234, + userId: 'anonId', + }; + expect(pageAction(getTestMessage(), destination, ConfigCategory.PAGE)).toEqual( + expectedOutput, + ); + }); + + it('For trackNamedPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName page', + templateId: 1234, + userId: 'anonId', + }; + expect(pageAction(getTestMessage(), destination, ConfigCategory.PAGE)).toEqual( + expectedOutput, + ); + }); + + it('For mapToSingleEvent', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + mapToSingleEvent: true, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'Loaded a Page', + templateId: 1234, + userId: 'anonId', + }; + expect(pageAction(getTestMessage(), destination, ConfigCategory.PAGE)).toEqual( + expectedOutput, + ); + }); + + it('For non-mapToSingleEvent', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + mapToSingleEvent: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName page', + templateId: 1234, + userId: 'anonId', + }; + expect(pageAction(getTestMessage(), destination, ConfigCategory.PAGE)).toEqual( + expectedOutput, + ); + }); + }); + describe('Unit test cases for iterbale screenAction', () => { + it('For trackAllPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: true, + trackCategorisedPages: false, + trackNamedPages: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName screen', + templateId: 1234, + userId: 'anonId', + }; + expect(screenAction(getTestMessage(), destination, ConfigCategory.SCREEN)).toEqual( + expectedOutput, + ); + }); + + it('For trackCategorisedPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: true, + trackNamedPages: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName screen', + templateId: 1234, + userId: 'anonId', + }; + expect(screenAction(getTestMessage(), destination, ConfigCategory.SCREEN)).toEqual( + expectedOutput, + ); + }); + + it('For trackNamedPages', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName screen', + templateId: 1234, + userId: 'anonId', + }; + expect(screenAction(getTestMessage(), destination, ConfigCategory.SCREEN)).toEqual( + expectedOutput, + ); + }); + + it('For mapToSingleEvent', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + mapToSingleEvent: true, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'Loaded a Screen', + templateId: 1234, + userId: 'anonId', + }; + expect(screenAction(getTestMessage(), destination, ConfigCategory.SCREEN)).toEqual( + expectedOutput, + ); + }); + + it('For non-mapToSingleEvent', async () => { + let destination = { + Config: { + apiKey: '12345', + mapToSingleEvent: false, + trackAllPages: false, + trackCategorisedPages: false, + trackNamedPages: true, + mapToSingleEvent: false, + }, + Enabled: true, + }; + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'pageName screen', + templateId: 1234, + userId: 'anonId', + }; + expect(screenAction(getTestMessage(), destination, ConfigCategory.SCREEN)).toEqual( + expectedOutput, + ); + }); + }); + describe('Unit test cases for iterable trackAction', () => { + it('flow check', async () => { + let expectedOutput = { + campaignId: 5678, + createdAt: 1400687660000, + dataFields: { + campaignId: 5678, + category: 'test', + email: 'test@test.com', + name: 'pageName', + templateId: 1234, + }, + email: 'test@test.com', + eventName: 'testEventName', + templateId: 1234, + userId: 'anonId', + }; + expect(trackAction(getTestMessage(), ConfigCategory.TRACK)).toEqual(expectedOutput); + }); + }); + describe('Unit test cases for iterable trackPurchaseAction', () => { + it('flow check without product array', async () => { + let expectedOutput = { + campaignId: 1111, + createdAt: 1400687660000, + dataFields: { + campaignId: '1111', + category: 'categoryTest1, categoryTest2', + name: 'no product array present', + price: '10', + product_id: 1234, + quantity: '2', + sku: 'abcd', + templateId: '2222', + total: '20', + }, + items: [ + { + categories: ['categoryTest1', ' categoryTest2'], + id: 1234, + name: 'no product array present', + price: 10, + quantity: 2, + sku: 'abcd', + }, + ], + templateId: 2222, + total: 20, + user: { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + userId: 'userId', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'userId', + }, + }; + expect(trackPurchaseAction(getTestEcommMessage(), ConfigCategory.TRACK_PURCHASE)).toEqual( + expectedOutput, + ); + }); + + it('flow check with product array', async () => { + let fittingPayload = { ...getTestEcommMessage() }; + fittingPayload.properties.products = [ + { + product_id: 1234, + sku: 'abcd', + name: 'no product array present', + category: 'categoryTest1, categoryTest2', + price: '10', + quantity: '2', + total: '20', + }, + ]; + let expectedOutput = { + campaignId: 1111, + createdAt: 1400687660000, + dataFields: { + campaignId: '1111', + category: 'categoryTest1, categoryTest2', + name: 'no product array present', + price: '10', + product_id: 1234, + products: [ + { + category: 'categoryTest1, categoryTest2', + name: 'no product array present', + price: '10', + product_id: 1234, + quantity: '2', + sku: 'abcd', + total: '20', + }, + ], + quantity: '2', + sku: 'abcd', + templateId: '2222', + total: '20', + }, + items: [ + { + categories: ['categoryTest1', ' categoryTest2'], + id: 1234, + name: 'no product array present', + price: 10, + quantity: 2, + sku: 'abcd', + }, + ], + templateId: 2222, + total: 20, + user: { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + userId: 'userId', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'userId', + }, + }; + expect(trackPurchaseAction(fittingPayload, ConfigCategory.TRACK_PURCHASE)).toEqual( + expectedOutput, + ); + }); + }); + describe('Unit test cases for iterable updateCartAction', () => { + it('flow check without product array', async () => { + let expectedOutput = { + items: [ + { + categories: ['categoryTest1', ' categoryTest2'], + id: 1234, + name: 'no product array present', + price: 10, + quantity: 2, + sku: 'abcd', + }, + ], + user: { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + userId: 'userId', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'userId', + }, + }; + expect(updateCartAction(getTestEcommMessage(), ConfigCategory.UPDATE_CART)).toEqual( + expectedOutput, + ); + }); + + it('flow check with product array', async () => { + let fittingPayload = { ...getTestEcommMessage() }; + fittingPayload.properties.products = [ + { + product_id: 1234, + sku: 'abcd', + name: 'no product array present', + category: 'categoryTest1, categoryTest2', + price: '10', + quantity: '2', + total: '20', + }, + ]; + let expectedOutput = { + items: [ + { + categories: ['categoryTest1', ' categoryTest2'], + id: 1234, + name: 'no product array present', + price: 10, + quantity: 2, + sku: 'abcd', + }, + ], + user: { + dataFields: { + address: { city: 'kolkata', country: 'India' }, + createdAt: '2014-05-21T15:54:20Z', + email: 'abc@test.com', + name: 'rudder', + timestamp: '2014-05-21T15:54:20Z', + userId: 'userId', + }, + email: 'abc@test.com', + mergeNestedObjects: true, + preferUserId: true, + userId: 'userId', + }, + }; + expect(updateCartAction(fittingPayload, ConfigCategory.UPDATE_CART)).toEqual(expectedOutput); + }); + }); +}); diff --git a/src/v0/destinations/june/transform.js b/src/v0/destinations/june/transform.js index f4a64d7f1e49..a33ae04a8e64 100644 --- a/src/v0/destinations/june/transform.js +++ b/src/v0/destinations/june/transform.js @@ -9,6 +9,7 @@ const { } = 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) => { if (payload) { @@ -16,7 +17,7 @@ const responseBuilder = (payload, endpoint, destination) => { const { apiKey } = destination.Config; response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${apiKey}`, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/kafka/transform.js b/src/v0/destinations/kafka/transform.js index d114bef21fca..210469b9e50f 100644 --- a/src/v0/destinations/kafka/transform.js +++ b/src/v0/destinations/kafka/transform.js @@ -47,10 +47,11 @@ const batch = (destEvents) => { // example: input events = [{event1,topic1},{event2,topic1},{event3,topic2}] // out from transformer: {batchedRequest:[{event1},{event2}]}, {batchedRequest:[{event3}]} (2 multilexed responses) for (const events of Object.values(groupedEvents)) { - const response = {}; - response.batchedRequest = events.map((event) => event.message); - response.metadata = events.map((event) => event.metadata); - response.destination = events[0].destination; + const response = { + batchedRequest: events.map((event) => event.message), + metadata: events.map((event) => event.metadata), + destination: events[0].destination, + }; respList.push(response); } diff --git a/src/v0/destinations/keen/transform.js b/src/v0/destinations/keen/transform.js index cfc2fedfdc11..495bc77a821f 100644 --- a/src/v0/destinations/keen/transform.js +++ b/src/v0/destinations/keen/transform.js @@ -12,6 +12,7 @@ const { } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); const { ENDPOINT } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function addAddons(properties, config) { const addons = []; @@ -64,7 +65,7 @@ function buildResponse(eventName, message, destination) { response.endpoint = endpoint; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: destination.Config.writeKey, }; response.userId = message.userId ? message.userId : message.anonymousId; @@ -78,9 +79,10 @@ function processTrack(message, destination) { const eventName = message.event; let { properties } = message; const { userId, anonymousId, context } = message; - const user = {}; - user.userId = userId ? (userId !== '' ? userId : anonymousId) : anonymousId; - user.traits = getFieldValueFromMessage(message, 'traits') || {}; + const user = { + userId: userId ? (userId !== '' ? userId : anonymousId) : anonymousId, + traits: getFieldValueFromMessage(message, 'traits') || {}, + }; properties = { ...properties, user, diff --git a/src/v0/destinations/kissmetrics/transform.js b/src/v0/destinations/kissmetrics/transform.js index 826a15cb5ad8..3e2c5593de9e 100644 --- a/src/v0/destinations/kissmetrics/transform.js +++ b/src/v0/destinations/kissmetrics/transform.js @@ -314,10 +314,11 @@ function processAlias(message, destination) { const { apiKey } = destination.Config; const endpoint = ENDPOINT.ALIAS; - const properties = {}; - properties._k = apiKey; - properties._p = previousId; - properties._n = userId; + const properties = { + _k: apiKey, + _p: previousId, + _n: userId, + }; return buildResponse(message, properties, endpoint); } diff --git a/src/v0/destinations/klaviyo/transform.js b/src/v0/destinations/klaviyo/transform.js index 04296d709e60..1a7259c63ecc 100644 --- a/src/v0/destinations/klaviyo/transform.js +++ b/src/v0/destinations/klaviyo/transform.js @@ -28,6 +28,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Main Identify request handler func @@ -81,7 +82,7 @@ const identifyRequestHandler = async (message, category, destination) => { response.endpoint = `${BASE_ENDPOINT}${category.apiUrl}`; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Accept: 'text/html', }; response.body.JSON = removeUndefinedAndNullValues(payload); @@ -89,7 +90,7 @@ const identifyRequestHandler = async (message, category, destination) => { response.endpoint = `${BASE_ENDPOINT}/api/v1/person/${personId}`; response.method = defaultPutRequestConfig.requestMethod; response.headers = { - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }; response.params = removeUndefinedAndNullValues(propertyPayload); response.params.api_key = destination.Config.privateApiKey; @@ -187,7 +188,7 @@ const trackRequestHandler = (message, category, destination) => { response.endpoint = `${BASE_ENDPOINT}${category.apiUrl}`; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Accept: 'text/html', }; response.body.JSON = removeUndefinedAndNullValues(payload); @@ -232,7 +233,7 @@ const groupRequestHandler = (message, category, destination) => { const subscribeResponse = defaultRequestConfig(); subscribeResponse.endpoint = `${BASE_ENDPOINT}/api/v2/list/${message.groupId}/subscribe`; subscribeResponse.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; subscribeResponse.body.JSON = subscribePayload; subscribeResponse.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/klaviyo/util.js b/src/v0/destinations/klaviyo/util.js index 417f98aa1f6d..f8faa429c36f 100644 --- a/src/v0/destinations/klaviyo/util.js +++ b/src/v0/destinations/klaviyo/util.js @@ -20,6 +20,7 @@ const { } = require('../../../adapters/utils/networkUtils'); const { NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * This function is used to check if the user/profile already exists or not, if already exists unique person_id @@ -43,7 +44,7 @@ const isProfileExist = async (message, { Config }) => { // eslint-disable-next-line no-await-in-loop const profileResponse = await httpGET(`${BASE_ENDPOINT}/api/v2/people/search`, { header: { - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }, params: { api_key: privateApiKey, @@ -109,7 +110,7 @@ const subscribeUserToList = (message, traitsInfo, conf, destination) => { response.method = defaultPostRequestConfig.requestMethod; response.params = { api_key: destination.Config.privateApiKey }; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = removeUndefinedAndNullValues(payload); diff --git a/src/v0/destinations/kustomer/transform.js b/src/v0/destinations/kustomer/transform.js index fd6882ea7c90..1d326758dce9 100644 --- a/src/v0/destinations/kustomer/transform.js +++ b/src/v0/destinations/kustomer/transform.js @@ -14,6 +14,7 @@ const { } = 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 // type of events. @@ -190,7 +191,7 @@ const responseBuilderSimple = async (message, category, destination) => { ? defaultPutRequestConfig.requestMethod : defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${destination.Config.apiKey}`, }; response.body.JSON = { ...payload }; diff --git a/src/v0/destinations/leanplum/transform.js b/src/v0/destinations/leanplum/transform.js index 47dcc85c6845..9a5462f2e553 100644 --- a/src/v0/destinations/leanplum/transform.js +++ b/src/v0/destinations/leanplum/transform.js @@ -8,6 +8,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function preparePayload(message, name, destination) { const mappingJson = mappingConfig[name]; @@ -45,7 +46,7 @@ function responseBuilderSimple(message, category, destination) { response.endpoint = ENDPOINT; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.userId = message.anonymousId; response.body.JSON = preparePayload(message, category.name, destination); diff --git a/src/v0/destinations/lemnisk/data/LEMNISKDIAPITrackConfig.json b/src/v0/destinations/lemnisk/data/LEMNISKDIAPITrackConfig.json index e58a43064283..82493dbf0913 100644 --- a/src/v0/destinations/lemnisk/data/LEMNISKDIAPITrackConfig.json +++ b/src/v0/destinations/lemnisk/data/LEMNISKDIAPITrackConfig.json @@ -1,26 +1,23 @@ [ - { - "destKey": "properties", - "sourceKeys": "properties", - "required": true - }, - { - "destKey": "userId", - "sourceKeys": [ - "userId", - "anonymousId" - ], - "required": true - }, - { - "destKey": "eventname", - "sourceKeys": "event", - "required": false - }, - { - "destKey": "email", - "sourceKeys": "emailOnly", - "sourceFromGenericMap": true, - "required": false - } -] \ No newline at end of file + { + "destKey": "properties", + "sourceKeys": "properties", + "required": true + }, + { + "destKey": "userId", + "sourceKeys": ["userId", "anonymousId"], + "required": true + }, + { + "destKey": "eventname", + "sourceKeys": "event", + "required": false + }, + { + "destKey": "email", + "sourceKeys": "emailOnly", + "sourceFromGenericMap": true, + "required": false + } +] diff --git a/src/v0/destinations/lemnisk/data/LEMNISKPageConfig.json b/src/v0/destinations/lemnisk/data/LEMNISKPageConfig.json index 181873be0d63..e7d882dc3697 100644 --- a/src/v0/destinations/lemnisk/data/LEMNISKPageConfig.json +++ b/src/v0/destinations/lemnisk/data/LEMNISKPageConfig.json @@ -21,7 +21,7 @@ }, { "destKey": "id", - "sourceKeys": ["userId","anonymousId"], + "sourceKeys": ["userId", "anonymousId"], "required": true }, { @@ -41,4 +41,4 @@ "sourceKeys": "name", "required": true } -] \ No newline at end of file +] diff --git a/src/v0/destinations/lemnisk/data/LEMNISKTrackConfig.json b/src/v0/destinations/lemnisk/data/LEMNISKTrackConfig.json index c0b15c28333a..3a92eecd3978 100644 --- a/src/v0/destinations/lemnisk/data/LEMNISKTrackConfig.json +++ b/src/v0/destinations/lemnisk/data/LEMNISKTrackConfig.json @@ -24,7 +24,7 @@ }, { "destKey": "id", - "sourceKeys": ["userId","anonymousId"], + "sourceKeys": ["userId", "anonymousId"], "required": true }, { diff --git a/src/v0/destinations/lemnisk/transform.js b/src/v0/destinations/lemnisk/transform.js index 6ea9c3437d5b..1d6d9a89fb5b 100644 --- a/src/v0/destinations/lemnisk/transform.js +++ b/src/v0/destinations/lemnisk/transform.js @@ -19,6 +19,7 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (message, category, destination, platform) => { let payload; @@ -37,7 +38,7 @@ const responseBuilder = (message, category, destination, platform) => { }; response.endpoint = pl; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; } else { // diapi @@ -60,7 +61,7 @@ const responseBuilder = (message, category, destination, platform) => { } response.endpoint = diapi; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'x-api-passKey': passKey, 'x-api-key': apiKey, }; @@ -107,15 +108,13 @@ const process = (event) => { } } if (platform === 'diapi') { - switch (messageType) { - case EventType.TRACK: - category = DIAPI_CONFIG_CATEGORIES.TRACK; - response = responseBuilder(message, category, destination, platform); - break; - default: - throw new InstrumentationError( - `Event type ${messageType} is not supported in Server Cloud Mode`, - ); + if (messageType === EventType.TRACK) { + category = DIAPI_CONFIG_CATEGORIES.TRACK; + response = responseBuilder(message, category, destination, platform); + } else { + throw new InstrumentationError( + `Event type ${messageType} is not supported in Server Cloud Mode`, + ); } } return response; diff --git a/src/v0/destinations/lytics/transform.js b/src/v0/destinations/lytics/transform.js index 42bef60ffb4a..a8d489fa5f82 100644 --- a/src/v0/destinations/lytics/transform.js +++ b/src/v0/destinations/lytics/transform.js @@ -15,6 +15,7 @@ const { simpleProcessRouterDest, } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilderSimple = (message, category, destination) => { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); @@ -37,7 +38,7 @@ const responseBuilderSimple = (message, category, destination) => { }); response.body.JSON = flattenedPayload; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; }; diff --git a/src/v0/destinations/mailchimp/transform.js b/src/v0/destinations/mailchimp/transform.js index b2b55aa0ffd1..01974040573e 100644 --- a/src/v0/destinations/mailchimp/transform.js +++ b/src/v0/destinations/mailchimp/transform.js @@ -24,6 +24,7 @@ const { } = 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) => { const { apiKey } = Config; @@ -42,7 +43,7 @@ const responseBuilderSimple = (finalPayload, endpoint, Config, audienceId) => { return { ...response, headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }, audienceId, diff --git a/src/v0/destinations/mailchimp/utils.js b/src/v0/destinations/mailchimp/utils.js index d5abb11023fc..0ea7f1ede52d 100644 --- a/src/v0/destinations/mailchimp/utils.js +++ b/src/v0/destinations/mailchimp/utils.js @@ -19,6 +19,7 @@ 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'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const ADDRESS_MANDATORY_FIELDS = ['addr1', 'city', 'state', 'zip']; @@ -203,16 +204,17 @@ const checkIfDoubleOptIn = async (apiKey, datacenterId, audienceId) => { * @returns */ const mergeAdditionalTraitsFields = (traits, mergedFieldPayload) => { + const clonedMergedFieldPayload = { ...mergedFieldPayload }; if (isDefined(traits)) { Object.keys(traits).forEach((traitKey) => { // if any trait field is present, other than the fixed mapping, that is passed as well. if (!MAILCHIMP_IDENTIFY_EXCLUSION.includes(traitKey)) { const tag = filterTagValue(traitKey); - mergedFieldPayload[tag] = traits[traitKey]; + clonedMergedFieldPayload[tag] = traits[traitKey]; } }); } - return mergedFieldPayload; + return clonedMergedFieldPayload; }; /** @@ -223,19 +225,20 @@ const mergeAdditionalTraitsFields = (traits, mergedFieldPayload) => { * @returns */ const validateAddressObject = (mergedAddressPayload) => { - const providedAddressKeys = Object.keys(mergedAddressPayload); + const clonedMergedAddressPayload = { ...mergedAddressPayload }; + const providedAddressKeys = Object.keys(clonedMergedAddressPayload); if (providedAddressKeys.length > 0) { if (checkSubsetOfArray(providedAddressKeys, ADDRESS_MANDATORY_FIELDS)) { ADDRESS_MANDATORY_FIELDS.forEach((addressField) => { if ( - !isDefinedAndNotNullAndNotEmpty(mergedAddressPayload[addressField]) || - typeof mergedAddressPayload[addressField] !== 'string' + !isDefinedAndNotNullAndNotEmpty(clonedMergedAddressPayload[addressField]) || + typeof clonedMergedAddressPayload[addressField] !== 'string' ) { throw new InstrumentationError( `To send as address information, ${addressField} field should be valid string`, ); } else { - mergedAddressPayload[addressField] = `${mergedAddressPayload[addressField]}`; + clonedMergedAddressPayload[addressField] = `${clonedMergedAddressPayload[addressField]}`; } }); } else { @@ -244,7 +247,7 @@ const validateAddressObject = (mergedAddressPayload) => { ); } } - return mergedAddressPayload; + return clonedMergedAddressPayload; }; /** @@ -374,7 +377,7 @@ const generateBatchedPaylaodForArray = (audienceId, events) => { const basicAuth = Buffer.from(`apiKey:${destination.Config.apiKey}`).toString('base64'); batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; diff --git a/src/v0/destinations/mailjet/transform.js b/src/v0/destinations/mailjet/transform.js index 9ac635bf8f38..fa87b3ed2a65 100644 --- a/src/v0/destinations/mailjet/transform.js +++ b/src/v0/destinations/mailjet/transform.js @@ -13,6 +13,7 @@ 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) => { if (payload) { @@ -77,7 +78,7 @@ const generateBatchedPaylaodForArray = (events, combination) => { batchEventResponse.batchedRequest.method = defaultPostRequestConfig.requestMethod; batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${token}`, }; batchEventResponse = { diff --git a/src/v0/destinations/mailmodo/transform.js b/src/v0/destinations/mailmodo/transform.js index e6ea674ecb6f..4f1a3d7e8c25 100644 --- a/src/v0/destinations/mailmodo/transform.js +++ b/src/v0/destinations/mailmodo/transform.js @@ -15,6 +15,7 @@ const { } = require('../../util'); const { deduceAddressFields, extractCustomProperties } = require('./utils'); const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (responseConfgs) => { const { resp, apiKey, endpoint } = responseConfgs; @@ -24,7 +25,7 @@ const responseBuilder = (responseConfgs) => { response.endpoint = `${BASE_URL}${endpoint}`; response.headers = { mmApiKey: `${apiKey}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = removeUndefinedAndNullValues(resp); @@ -139,7 +140,7 @@ function batchEvents(eventsChunk) { batchEventResponse.batchedRequest.endpoint = `${BASE_URL}/addToList/batch`; batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, mmApiKey: apiKey, }; diff --git a/src/v0/destinations/marketo/networkHandler.js b/src/v0/destinations/marketo/networkHandler.js index 059a3491becc..c25a7a246c58 100644 --- a/src/v0/destinations/marketo/networkHandler.js +++ b/src/v0/destinations/marketo/networkHandler.js @@ -24,12 +24,12 @@ const responseHandler = (destinationResponse, destType) => { }; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = proxyRequest; this.prepareProxy = prepareProxyRequest; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/marketo/transform.js b/src/v0/destinations/marketo/transform.js index 4dea58df8264..dc0a904bd2f6 100644 --- a/src/v0/destinations/marketo/transform.js +++ b/src/v0/destinations/marketo/transform.js @@ -30,7 +30,7 @@ const { handleRtTfSingleEventError, } = require('../../util'); const Cache = require('../../util/cache'); -const { USER_LEAD_CACHE_TTL, AUTH_CACHE_TTL } = require('../../util/constant'); +const { USER_LEAD_CACHE_TTL, AUTH_CACHE_TTL, JSON_MIME_TYPE } = require('../../util/constant'); const { marketoResponseHandler, sendGetRequest, @@ -112,7 +112,7 @@ const createOrUpdateLead = async (formattedDestination, token, userId, anonymous { headers: { Authorization: `Bearer ${token}`, - 'Content-type': 'application/json', + 'Content-type': JSON_MIME_TYPE, }, }, ); @@ -413,7 +413,7 @@ const responseWrapper = (response) => { const resp = defaultRequestConfig(); resp.endpoint = response.endPoint; resp.method = defaultPostRequestConfig.requestMethod; - resp.headers = { ...response.headers, 'Content-Type': 'application/json' }; + resp.headers = { ...response.headers, 'Content-Type': JSON_MIME_TYPE }; resp.body.JSON = response.payload; return resp; }; diff --git a/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js b/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js index 0eeecb3aac78..1b87586fc574 100644 --- a/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js +++ b/src/v0/destinations/marketo_bulk_upload/fetchJobStatus.js @@ -15,6 +15,12 @@ const { PlatformError, } = require('../../util/errorTypes'); const stats = require('../../../util/stats'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const FETCH_FAILURE_JOB_STATUS_ERR_MSG = 'Could not fetch failure job status'; +const FAILURE_JOB_STATUS_ERR_MSG = 'Error during fetching failure job status'; +const FETCH_WARNING_JOB_STATUS_ERR_MSG = 'Could not fetch warning job status'; +const WARNING_JOB_STATUS_ERR_MSG = 'Error during fetching warning job status'; const getFailedJobStatus = async (event) => { const { config, importId } = event; @@ -24,7 +30,7 @@ const getFailedJobStatus = async (event) => { // DOC: https://developers.marketo.com/rest-api/bulk-import/bulk-lead-import/#failures const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${accessToken}`, }, }; @@ -47,7 +53,7 @@ const getFailedJobStatus = async (event) => { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch failure job status', 400, resp); + throw new AbortedError(FETCH_FAILURE_JOB_STATUS_ERR_MSG, 400, resp); } if (resp.response) { if ( @@ -72,7 +78,7 @@ const getFailedJobStatus = async (event) => { state: 'Abortable', }); throw new AbortedError( - resp.response.response.statusText || 'Error during fetching failure job status', + resp.response.response.statusText || FAILURE_JOB_STATUS_ERR_MSG, 400, resp, ); @@ -82,7 +88,7 @@ const getFailedJobStatus = async (event) => { state: 'Retryable', }); throw new ThrottledError( - resp.response.response.statusText || 'Error during fetching failure job status', + resp.response.response.statusText || FAILURE_JOB_STATUS_ERR_MSG, resp, ); } @@ -91,7 +97,7 @@ const getFailedJobStatus = async (event) => { state: 'Retryable', }); throw new RetryableError( - resp.response.response.statusText || 'Error during fetching failure job status', + resp.response.response.statusText || FAILURE_JOB_STATUS_ERR_MSG, 500, resp, ); @@ -100,13 +106,13 @@ const getFailedJobStatus = async (event) => { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch failure job status', 400, resp); + throw new AbortedError(FETCH_FAILURE_JOB_STATUS_ERR_MSG, 400, resp); } stats.increment(JOB_STATUS_ACTIVITY, { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch failure job status', 400, resp); + throw new AbortedError(FETCH_FAILURE_JOB_STATUS_ERR_MSG, 400, resp); }; const getWarningJobStatus = async (event) => { @@ -117,7 +123,7 @@ const getWarningJobStatus = async (event) => { // DOC: https://developers.marketo.com/rest-api/bulk-import/bulk-lead-import/#warnings const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${accessToken}`, }, }; @@ -139,7 +145,7 @@ const getWarningJobStatus = async (event) => { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch warning job status', 400, resp); + throw new AbortedError(FETCH_WARNING_JOB_STATUS_ERR_MSG, 400, resp); } if (resp.response) { if ( @@ -164,7 +170,7 @@ const getWarningJobStatus = async (event) => { state: 'Abortable', }); throw new AbortedError( - resp.response.response.statusText || 'Error during fetching warning job status', + resp.response.response.statusText || WARNING_JOB_STATUS_ERR_MSG, 400, resp, ); @@ -174,7 +180,7 @@ const getWarningJobStatus = async (event) => { state: 'Retryable', }); throw new ThrottledError( - resp.response.response.statusText || 'Error during fetching warning job status', + resp.response.response.statusText || WARNING_JOB_STATUS_ERR_MSG, resp, ); } @@ -184,7 +190,7 @@ const getWarningJobStatus = async (event) => { state: 'Retryable', }); throw new RetryableError( - resp.response.response.statusText || 'Error during fetching warning job status', + resp.response.response.statusText || WARNING_JOB_STATUS_ERR_MSG, 500, resp, ); @@ -193,13 +199,13 @@ const getWarningJobStatus = async (event) => { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch warning job status', 400, resp); + throw new AbortedError(FETCH_WARNING_JOB_STATUS_ERR_MSG, 400, resp); } stats.increment(JOB_STATUS_ACTIVITY, { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not fetch warning job status', 400, resp); + throw new AbortedError(FETCH_WARNING_JOB_STATUS_ERR_MSG, 400, resp); }; const responseHandler = async (event, type) => { diff --git a/src/v0/destinations/marketo_bulk_upload/fileUpload.js b/src/v0/destinations/marketo_bulk_upload/fileUpload.js index 0841e23e5794..d18e79e76dc9 100644 --- a/src/v0/destinations/marketo_bulk_upload/fileUpload.js +++ b/src/v0/destinations/marketo_bulk_upload/fileUpload.js @@ -74,7 +74,7 @@ const getHeaderFields = (config, fieldSchemaNames) => { columnFieldsMapping.forEach((colField) => { if (fieldSchemaNames) { - if (fieldSchemaNames && !fieldSchemaNames.includes(colField.to)) { + if (!fieldSchemaNames.includes(colField.to)) { throw new ConfigurationError( `The field ${colField.to} is not present in Marketo Field Schema. Aborting`, ); @@ -89,7 +89,6 @@ const getHeaderFields = (config, fieldSchemaNames) => { const getFileData = async (inputEvents, config, fieldSchemaNames) => { const input = inputEvents; - const jobIds = []; const messageArr = []; let startTime; let endTime; @@ -99,13 +98,12 @@ const getFileData = async (inputEvents, config, fieldSchemaNames) => { input.forEach((i) => { const inputData = i; const jobId = inputData.metadata.job_id; - jobIds.push(`${jobId}`); const data = {}; data[jobId] = inputData.message; messageArr.push(data); }); - const headerArr = getHeaderFields(config, fieldSchemaNames, jobIds); + const headerArr = getHeaderFields(config, fieldSchemaNames); if (isDefinedAndNotNullAndNotEmpty(config.deDuplicationField)) { // dedup starts @@ -193,6 +191,7 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { config, fieldSchemaNames, ); + const FILE_UPLOAD_ERR_MSG = 'Could not upload file'; try { const formReq = new FormData(); const { munchkinId, deDuplicationField } = config; @@ -265,7 +264,7 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { state: 'Retryable', }); throw new RetryableError( - resp.response.data.errors[0].message || 'Could not upload file', + resp.response.data.errors[0].message || FILE_UPLOAD_ERR_MSG, 500, { successfulJobs, unsuccessfulJobs }, ); @@ -282,7 +281,7 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { state: 'Retryable', }); throw new RetryableError( - resp.response.data.errors[0].message || 'Could not upload file', + resp.response.data.errors[0].message || FILE_UPLOAD_ERR_MSG, 500, { successfulJobs, unsuccessfulJobs }, ); @@ -293,7 +292,7 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { state: 'Abortable', }); throw new AbortedError( - resp.response.data.errors[0].message || 'Could not upload file', + resp.response.data.errors[0].message || FILE_UPLOAD_ERR_MSG, 400, { successfulJobs, unsuccessfulJobs }, ); @@ -302,7 +301,7 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { status: 500, state: 'Retryable', }); - throw new ThrottledError(resp.response.response.statusText || 'Could not upload file', { + throw new ThrottledError(resp.response.response.statusText || FILE_UPLOAD_ERR_MSG, { successfulJobs, unsuccessfulJobs, }); @@ -311,11 +310,10 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { status: 500, state: 'Retryable', }); - throw new RetryableError( - resp.response.response.statusText || 'Error during uploading file', - 500, - { successfulJobs, unsuccessfulJobs }, - ); + throw new RetryableError(resp.response.response.statusText || FILE_UPLOAD_ERR_MSG, 500, { + successfulJobs, + unsuccessfulJobs, + }); } } } @@ -324,11 +322,11 @@ const getImportID = async (input, config, fieldSchemaNames, accessToken) => { // TODO check the tags stats.increment(UPLOAD_FILE, { status: err.response?.status || 400, - errorMessage: err.message || 'Error during uploading file', + errorMessage: err.message || FILE_UPLOAD_ERR_MSG, }); const status = err.response?.status || 400; throw new NetworkError( - err.message || 'Error during uploading file', + err.message || FILE_UPLOAD_ERR_MSG, status, { [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), @@ -353,10 +351,11 @@ const responseHandler = async (input, config) => { accessToken, ); if (importId) { - const response = {}; - response.statusCode = 200; - response.importId = importId; - response.pollURL = '/pollStatus'; + const response = { + statusCode: 200, + importId, + pollURL: '/pollStatus', + }; const csvHeader = getHeaderFields(config, fieldSchemaNames).toString(); response.metadata = { successfulJobs, unsuccessfulJobs, csvHeader }; return response; diff --git a/src/v0/destinations/marketo_bulk_upload/poll.js b/src/v0/destinations/marketo_bulk_upload/poll.js index 6111d3a76fac..9d02db21d792 100644 --- a/src/v0/destinations/marketo_bulk_upload/poll.js +++ b/src/v0/destinations/marketo_bulk_upload/poll.js @@ -3,6 +3,7 @@ const { getAccessToken, ABORTABLE_CODES, THROTTLED_CODES, POLL_ACTIVITY } = requ const { httpGET } = require('../../../adapters/network'); const stats = require('../../../util/stats'); const { AbortedError, ThrottledError, RetryableError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const getPollStatus = async (event) => { const accessToken = await getAccessToken(event.config); @@ -12,7 +13,7 @@ const getPollStatus = async (event) => { // DOC: https://developers.marketo.com/rest-api/bulk-import/bulk-lead-import/#polling_job_status const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${accessToken}`, }, }; @@ -21,6 +22,7 @@ const getPollStatus = async (event) => { const pollStatus = await httpGET(pollUrl, requestOptions); const endTime = Date.now(); const requestTime = endTime - startTime; + const POLL_STATUS_ERR_MSG = 'Could not poll status'; if (pollStatus.success) { if (pollStatus.response && pollStatus.response.data.success) { stats.increment(POLL_ACTIVITY, { @@ -58,7 +60,7 @@ const getPollStatus = async (event) => { state: 'Abortable', }); throw new AbortedError( - pollStatus.response.data.errors[0].message || 'Could not poll status', + pollStatus.response.data.errors[0].message || POLL_STATUS_ERR_MSG, 400, pollStatus, ); @@ -69,7 +71,7 @@ const getPollStatus = async (event) => { state: 'Retryable', }); throw new ThrottledError( - pollStatus.response.data.errors[0].message || 'Could not poll status', + pollStatus.response.data.errors[0].message || POLL_STATUS_ERR_MSG, pollStatus, ); } @@ -90,7 +92,7 @@ const getPollStatus = async (event) => { status: 400, state: 'Abortable', }); - throw new AbortedError('Could not poll status', 400, pollStatus); + throw new AbortedError(POLL_STATUS_ERR_MSG, 400, pollStatus); }; const responseHandler = async (event) => { diff --git a/src/v0/destinations/marketo_bulk_upload/transform.js b/src/v0/destinations/marketo_bulk_upload/transform.js index e2435b0b1869..d5764ee6c398 100644 --- a/src/v0/destinations/marketo_bulk_upload/transform.js +++ b/src/v0/destinations/marketo_bulk_upload/transform.js @@ -52,14 +52,11 @@ const processEvent = (message, destination) => { const messageType = message.type.toLowerCase(); let response; // Only identify type of events are processed - switch (messageType) { - case EventType.IDENTIFY: - response = responseBuilderSimple(message, destination); - break; - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + if (messageType === EventType.IDENTIFY) { + response = responseBuilderSimple(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } - return response; }; const process = (event) => processEvent(event.message, event.destination); diff --git a/src/v0/destinations/marketo_bulk_upload/util.js b/src/v0/destinations/marketo_bulk_upload/util.js index 76d5bc0707e7..0e78b72bdc64 100644 --- a/src/v0/destinations/marketo_bulk_upload/util.js +++ b/src/v0/destinations/marketo_bulk_upload/util.js @@ -26,6 +26,7 @@ const getAccessToken = async (config) => { const { clientId, clientSecret, munchkinId } = config; const url = `https://${munchkinId}.mktorest.com/identity/oauth/token?client_id=${clientId}&client_secret=${clientSecret}&grant_type=client_credentials`; const resp = await httpGET(url); + const ACCESS_TOKEN_FETCH_ERR_MSG = 'Error during fetching access token'; if (resp.success) { if (resp.response && resp.response.data && resp.response.data.access_token) { return resp.response.data.access_token; @@ -54,20 +55,20 @@ const getAccessToken = async (config) => { else if (resp.response.response) { if (ABORTABLE_CODES.includes(resp.response.response.status)) { throw new AbortedError( - resp.response.response.statusText || 'Error during fetching access token', + resp.response.response.statusText || ACCESS_TOKEN_FETCH_ERR_MSG, 400, resp, ); } // handle for throttled codes else if (THROTTLED_CODES.includes(resp.response.response.status)) { throw new ThrottledError( - resp.response.response.statusText || 'Error during fetching access token', + resp.response.response.statusText || ACCESS_TOKEN_FETCH_ERR_MSG, resp, ); } // Assuming none we should retry the remaining errors throw new RetryableError( - resp.response.response.statusText || 'Error during fetching access token', + resp.response.response.statusText || ACCESS_TOKEN_FETCH_ERR_MSG, 500, resp, ); diff --git a/src/v0/destinations/marketo_static_list/transform.js b/src/v0/destinations/marketo_static_list/transform.js index 043852ccdac5..7175b5241fb6 100644 --- a/src/v0/destinations/marketo_static_list/transform.js +++ b/src/v0/destinations/marketo_static_list/transform.js @@ -5,7 +5,7 @@ const { defaultDeleteRequestConfig, generateErrorObject, } = require('../../util'); -const { AUTH_CACHE_TTL } = require('../../util/constant'); +const { AUTH_CACHE_TTL, JSON_MIME_TYPE } = require('../../util/constant'); const { getIds, validateMessageType } = require('./util'); const { getDestinationExternalID, @@ -37,7 +37,7 @@ const responseBuilder = (endPoint, leadIds, operation, token) => { } response.headers = { Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; }; diff --git a/src/v0/destinations/mautic/transform.js b/src/v0/destinations/mautic/transform.js index df8d0cadc7d4..12b0d06b6ffa 100644 --- a/src/v0/destinations/mautic/transform.js +++ b/src/v0/destinations/mautic/transform.js @@ -25,6 +25,7 @@ const { InstrumentationError, ConfigurationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = async (payload, endpoint, method, messageType, Config) => { const { userName, password } = Config; @@ -40,7 +41,7 @@ const responseBuilder = async (payload, endpoint, method, messageType, Config) = response.endpoint = endpoint; const basicAuth = Buffer.from(`${userName}:${password}`).toString('base64'); response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; response.method = method; @@ -166,10 +167,8 @@ const process = async (event) => { ); } - // if both are present we will be taking endpoint after checking the domainMethod selected const endpoint = getEndpoint(destination.Config); - // Validating if message type is even given or not if (!message.type) { diff --git a/src/v0/destinations/mautic/utils.js b/src/v0/destinations/mautic/utils.js index 60b3718432b0..915bd29537d4 100644 --- a/src/v0/destinations/mautic/utils.js +++ b/src/v0/destinations/mautic/utils.js @@ -9,6 +9,7 @@ const { } = require('../../../adapters/utils/networkUtils'); const { NetworkError, InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * @param {*} propertyName @@ -168,7 +169,7 @@ const searchContactIds = async (message, Config, baseUrl) => { const basicAuth = Buffer.from(`${userName}:${password}`).toString('base64'); const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }, }; diff --git a/src/v0/destinations/moengage/transform.js b/src/v0/destinations/moengage/transform.js index 65d6d87aedd2..d87d931817a9 100644 --- a/src/v0/destinations/moengage/transform.js +++ b/src/v0/destinations/moengage/transform.js @@ -21,6 +21,7 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(message, category, destination) { const payload = constructPayload(message, MAPPING_CONFIG[category.name]); @@ -42,7 +43,7 @@ function responseBuilderSimple(message, category, destination) { } response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'MOE-APPKEY': apiId, // Basic Authentication encodes a 'username:password' // using base64 and prepends it with the string 'Basic '. diff --git a/src/v0/destinations/monday/transform.js b/src/v0/destinations/monday/transform.js index 51f744bdd375..a702f2660290 100644 --- a/src/v0/destinations/monday/transform.js +++ b/src/v0/destinations/monday/transform.js @@ -14,13 +14,14 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, apiToken) => { if (payload) { const response = defaultRequestConfig(); response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `${apiToken}`, }; response.method = defaultPostRequestConfig.requestMethod; @@ -72,12 +73,10 @@ const processEvent = async (message, destination) => { } const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: - response = await trackResponseBuilder(message, destination); - break; - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + if (messageType === EventType.TRACK) { + response = await trackResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } return response; }; diff --git a/src/v0/destinations/monday/util.js b/src/v0/destinations/monday/util.js index d0dc60be2b7c..7f7d07248053 100644 --- a/src/v0/destinations/monday/util.js +++ b/src/v0/destinations/monday/util.js @@ -5,6 +5,7 @@ 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'); /** * This function is taking the board(received from the lookup call) and groupTitle as parameter @@ -182,7 +183,7 @@ const getBoardDetails = async (url, boardID, apiToken) => { }, { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `${apiToken}`, }, }, diff --git a/src/v0/destinations/monetate/transform.js b/src/v0/destinations/monetate/transform.js index 351cf98597dc..e4d1f28b613d 100644 --- a/src/v0/destinations/monetate/transform.js +++ b/src/v0/destinations/monetate/transform.js @@ -1,167 +1,18 @@ const get = require('get-value'); -const set = require('set-value'); - +const { removeUndefinedValues, simpleProcessRouterDest } = require('../../util'); const { - getValueFromMessage, - defaultRequestConfig, - removeUndefinedValues, - simpleProcessRouterDest, - isDefinedAndNotNull, -} = require('../../util'); + handleProductViewed, + handleProductListViewed, + handleProductAdded, + handleCartViewed, + handleOrderCompleted, + constructPayload, + responseBuilder, +} = require('./utils'); const { EventType } = require('../../../constants'); -const { ENDPOINT, mappingConfig } = require('./config'); +const { mappingConfig } = require('./config'); const { InstrumentationError } = require('../../util/errorTypes'); -const createObject = (type) => { - if (!type) { - throw new InstrumentationError('[createObject] type not defined'); - } - // TODO: check if default makes sense - let retObj = {}; - switch (type.toLowerCase()) { - case 'array': - retObj = []; - break; - case 'object': - retObj = {}; - break; - default: - break; - } - return retObj; -}; - -const getStringValue = (value, key) => { - let val; - if (key === 'sourceKeyValue') { - val = value; - } else if (key.startsWith('sourceKeyValue.')) { - // gets the substring after the first . - // sourceKeyValue.page.url => page.url - const k = key.substring(key.indexOf('.') + 1); - val = get(value, k); - } else { - // leave the sourceKey as it is if cannot be replaced - val = key; - } - return val; -}; - -const getValue = (value, key) => { - let val; - if (typeof key === 'string') { - val = getStringValue(value, key); - } else if (Array.isArray(key)) { - val = []; - key.forEach((k) => { - if (typeof k === 'string') { - const v = getStringValue(value, k); - if (v) { - val.push(v); - } - } else { - // if child element of array is not a string, push it as it is - // TODO : add support for more types - val.push(k); - } - }); - if (val.length === 0) { - val = undefined; - } - } - return val; -}; - -const formatValue = (value, format, required) => { - let formattedVal = {}; - // format is an object in this case - // TODO : Add generic support for more types - if (value && format) { - let sourceKey; - let key; - let val; - const formatKeys = Object.keys(format); - // eslint-disable-next-line no-restricted-syntax - for (const formatKey of formatKeys) { - key = formatKey; - // Object.keys(format).forEach(key => { - sourceKey = format[key]; - val = getValue(value, sourceKey); - if (val) { - formattedVal[key] = val; - } else if (required) { - // return undefined if val doesn't exist.All keys for targetFormat are required. - // TODO : make this configurable from JSON - formattedVal = undefined; - break; - } - } - } - return formattedVal; -}; - -const customMetadataHandler = (payload, destKey, value, metadata) => { - // make sure payload.destKey exists and is of correct type - if (!get(payload, destKey) && metadata.targetType) { - payload[destKey] = createObject(metadata.targetType); - } - // populate payload - if (metadata.isTargetTypePrimite) { - // set value directly if it is primitive - // TODO : call format value for here, we can use the function alredy defined in utils - set(payload, destKey, value); - } else { - // value is not a primitive type - // TODO: add else or refactor for better code cov - const targetValue = formatValue(value, metadata.targetFormat, metadata.targetFormatRequired); - if (metadata.action && payload[destKey][metadata.action] && targetValue) { - payload[destKey][metadata.action](targetValue); - } - } -}; - -function responseBuilder(body, destination) { - const destinationConfig = destination.Config || {}; - const response = defaultRequestConfig(); - - // adding monetate channel to body - body.channel = destinationConfig.monetateChannel; - - response.endpoint = ENDPOINT + destinationConfig.retailerShortName; - response.body.JSON = body; - response.headers = { - 'Content-Type': 'application/json', - }; - - return response; -} - -const constructPayload = (message, mappingJson) => { - // Mapping JSON should be an array - if (Array.isArray(mappingJson) && mappingJson.length > 0) { - const payload = {}; - - mappingJson.forEach((mapping) => { - const { sourceKeys, destKey, required, metadata } = mapping; - // get the value from event - const value = getValueFromMessage(message, sourceKeys); - if (value) { - // set the value only if correct - if (metadata) { - customMetadataHandler(payload, destKey, value, metadata); - } else { - set(payload, destKey, value); - } - } else if (required) { - // throw error if reqired value is missing - throw new InstrumentationError(`Missing required value from ${JSON.stringify(sourceKeys)}`); - } - }); - return payload; - } - return null; -}; - function track(message, destination) { const rawPayload = constructPayload(message, mappingConfig.MONETATETrack); @@ -174,135 +25,31 @@ function track(message, destination) { // Add Ecomm Events if applicable const evName = message.event; const properties = message.properties || {}; + let updatedPayload = {}; if (evName) { - if (evName === 'Product Viewed') { - if (properties.product_id) { - const sku = properties.sku || ''; - rawPayload.events.push({ - eventType: 'monetate:context:ProductDetailView', - products: [ - { - productId: properties.product_id, - sku, - }, - ], - }); - } else { - throw new InstrumentationError("'product_id' is a required field for Product Viewed"); - } - } else if (evName === 'Product List Viewed') { - if (properties.products && Array.isArray(properties.products)) { - const viewedProducts = properties.products.filter((product) => product.product_id); - if (viewedProducts.length !== properties.products.length) { - throw new InstrumentationError( - "'product_id' is a required field for all products for Product List Viewed", - ); - } - rawPayload.events.push({ - eventType: 'monetate:context:ProductThumbnailView', - products: properties.products.map((product) => product.product_id.toString()), - }); - } else { - throw new InstrumentationError("'products' missing or not array in Product List Viewed"); - } - } else if (evName === 'Product Added') { - const currency = properties.currency || 'USD'; - const sku = properties.sku || ''; - if ( - properties.product_id && - properties.quantity && - Number.isInteger(properties.quantity) && - properties.cart_value - ) { - rawPayload.events.push({ - eventType: 'monetate:context:Cart', - cartLines: [ - { - pid: properties.product_id ? properties.product_id.toString() : '', - sku, - quantity: properties.quantity, - value: properties.cart_value ? properties.cart_value.toString() : '', - currency, - }, - ], - }); - } else { - throw new InstrumentationError( - "'product_id', 'quantity', 'cart_value' are required fields and 'quantity' should be a number for Product Added", - ); - } - } else if (evName === 'Cart Viewed') { - if (properties.products && Array.isArray(properties.products)) { - const cartProducts = properties.products.filter( - (product) => - product.quantity && - Number.isInteger(product.quantity) && - isDefinedAndNotNull(product.price) && - typeof product.price === 'number' && - product.product_id, - ); - if (cartProducts.length !== properties.products.length) { - throw new InstrumentationError( - "'quantity', 'price' and 'product_id' are required fields and 'quantity' and 'price' should be a number for all products for Cart Viewed", - ); - } - rawPayload.events.push({ - eventType: 'monetate:context:Cart', - cartLines: properties.products.map((product) => { - const cartValue = (product.quantity * product.price).toFixed(2); - const currency = product.currency || properties.currency || 'USD'; - const sku = product.sku || ''; - return { - pid: product.product_id ? product.product_id.toString() : '', - sku, - quantity: product.quantity, - value: cartValue ? cartValue.toString() : '', - currency, - }; - }), - }); - } - } else if (evName === 'Order Completed') { - const purchaseId = properties.order_id; - const { products } = properties; - if (purchaseId && products && Array.isArray(products)) { - const purchaseLines = products.filter( - (product) => - product.quantity && - Number.isInteger(product.quantity) && - isDefinedAndNotNull(product.price) && - typeof product.price === 'number' && - product.product_id, - ); - if (purchaseLines.length !== products.length) { - throw new InstrumentationError( - "'quantity', 'price' and 'product_id' are required fields and 'quantity' and 'price' should be a number for all products for Order Completed", - ); - } - rawPayload.events.push({ - eventType: 'monetate:context:Purchase', - purchaseId, - purchaseLines: purchaseLines.map((product) => { - const valueStr = (product.quantity * product.price).toFixed(2); - const currency = product.currency || properties.currency || 'USD'; - const sku = product.sku || ''; - return { - pid: product.product_id ? product.product_id.toString() : '', - sku, - quantity: product.quantity, - value: valueStr ? valueStr.toString() : '', - currency, - }; - }), - }); - } - } else { - // The Engine API does not currently support custom events. - // For lifecycle events, we would prefer to add them to our spec, - // rather than support free-form custom events. Nevertheless, if - // custom event support is added to the Engine API, the following - // block can be uncommented. - /* + switch (evName) { + case 'Product Viewed': + updatedPayload = { ...handleProductViewed(properties, rawPayload) }; + break; + case 'Product List Viewed': + updatedPayload = { ...handleProductListViewed(properties, rawPayload) }; + break; + case 'Product Added': + updatedPayload = { ...handleProductAdded(properties, rawPayload) }; + break; + case 'Cart Viewed': + updatedPayload = { ...handleCartViewed(properties, rawPayload) }; + break; + case 'Order Completed': + updatedPayload = { ...handleOrderCompleted(properties, rawPayload) }; + break; + default: + // The Engine API does not currently support custom events. + // For lifecycle events, we would prefer to add them to our spec, + // rather than support free-form custom events. Nevertheless, if + // custom event support is added to the Engine API, the following + // block can be uncommented. + /* rawPayload.events.push({ "eventType": "monetate:context:CustomEvents", "customEvents": [{ @@ -311,10 +58,12 @@ function track(message, destination) { }], }); */ + updatedPayload = { ...rawPayload }; + break; } } - return responseBuilder(removeUndefinedValues(rawPayload), destination); + return responseBuilder(removeUndefinedValues(updatedPayload), destination); } function page(message, destination) { diff --git a/src/v0/destinations/monetate/utils.js b/src/v0/destinations/monetate/utils.js new file mode 100644 index 000000000000..7facc2617d70 --- /dev/null +++ b/src/v0/destinations/monetate/utils.js @@ -0,0 +1,305 @@ +const set = require('set-value'); +const get = require('get-value'); +const { InstrumentationError } = require('../../util/errorTypes'); +const { isDefinedAndNotNull, defaultRequestConfig, getValueFromMessage } = require('../../util'); +const { ENDPOINT } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const createObject = (type) => { + if (!type) { + throw new InstrumentationError('[createObject] type not defined'); + } + // TODO: check if default makes sense + let retObj = {}; + switch (type.toLowerCase()) { + case 'array': + retObj = []; + break; + case 'object': + retObj = {}; + break; + default: + break; + } + return retObj; +}; + +const getStringValue = (value, key) => { + let val; + if (key === 'sourceKeyValue') { + val = value; + } else if (key.startsWith('sourceKeyValue.')) { + // gets the substring after the first . + // sourceKeyValue.page.url => page.url + const k = key.substring(key.indexOf('.') + 1); + val = get(value, k); + } else { + // leave the sourceKey as it is if cannot be replaced + val = key; + } + return val; +}; + +const getValue = (value, key) => { + let val; + if (typeof key === 'string') { + val = getStringValue(value, key); + } else if (Array.isArray(key)) { + val = []; + key.forEach((k) => { + if (typeof k === 'string') { + const v = getStringValue(value, k); + if (v) { + val.push(v); + } + } else { + // if child element of array is not a string, push it as it is + // TODO : add support for more types + val.push(k); + } + }); + if (val.length === 0) { + val = undefined; + } + } + return val; +}; + +const formatValue = (value, format, required) => { + let formattedVal = {}; + // format is an object in this case + // TODO : Add generic support for more types + if (value && format) { + let sourceKey; + let key; + let val; + const formatKeys = Object.keys(format); + // eslint-disable-next-line no-restricted-syntax + for (const formatKey of formatKeys) { + key = formatKey; + // Object.keys(format).forEach(key => { + sourceKey = format[key]; + val = getValue(value, sourceKey); + if (val) { + formattedVal[key] = val; + } else if (required) { + // return undefined if val doesn't exist.All keys for targetFormat are required. + // TODO : make this configurable from JSON + formattedVal = undefined; + break; + } + } + } + return formattedVal; +}; + +const customMetadataHandler = (payload, destKey, value, metadata) => { + const clonedPayload = { ...payload }; + // make sure payload.destKey exists and is of correct type + if (!get(clonedPayload, destKey) && metadata.targetType) { + clonedPayload[destKey] = createObject(metadata.targetType); + } + // populate payload + if (metadata.isTargetTypePrimite) { + // set value directly if it is primitive + // TODO : call format value for here, we can use the function alredy defined in utils + set(clonedPayload, destKey, value); + } else { + // value is not a primitive type + // TODO: add else or refactor for better code cov + const targetValue = formatValue(value, metadata.targetFormat, metadata.targetFormatRequired); + if (metadata.action && clonedPayload[destKey][metadata.action] && targetValue) { + clonedPayload[destKey][metadata.action](targetValue); + } + } + return clonedPayload; +}; + +function responseBuilder(body, destination) { + const destinationConfig = destination.Config || {}; + const response = defaultRequestConfig(); + + // adding monetate channel to body + const clonedBody = { ...body }; + clonedBody.channel = destinationConfig.monetateChannel; + + response.endpoint = ENDPOINT + destinationConfig.retailerShortName; + response.body.JSON = clonedBody; + response.headers = { + 'Content-Type': JSON_MIME_TYPE, + }; + + return response; +} + +const constructPayload = (message, mappingJson) => { + // Mapping JSON should be an array + if (Array.isArray(mappingJson) && mappingJson.length > 0) { + let payload = {}; + + mappingJson.forEach((mapping) => { + const { sourceKeys, destKey, required, metadata } = mapping; + // get the value from event + const value = getValueFromMessage(message, sourceKeys); + if (value) { + // set the value only if correct + if (metadata) { + payload = customMetadataHandler(payload, destKey, value, metadata); + } else { + set(payload, destKey, value); + } + } else if (required) { + // throw error if reqired value is missing + throw new InstrumentationError(`Missing required value from ${JSON.stringify(sourceKeys)}`); + } + }); + return payload; + } + return null; +}; + +const handleProductViewed = (properties, rawPayload) => { + if (properties.product_id) { + const sku = properties.sku || ''; + rawPayload.events.push({ + eventType: 'monetate:context:ProductDetailView', + products: [ + { + productId: properties.product_id, + sku, + }, + ], + }); + } else { + throw new InstrumentationError("'product_id' is a required field for Product Viewed"); + } + return rawPayload; +}; + +const handleProductListViewed = (properties, rawPayload) => { + if (properties.products && Array.isArray(properties.products)) { + const viewedProducts = properties.products.filter((product) => product.product_id); + if (viewedProducts.length !== properties.products.length) { + throw new InstrumentationError( + "'product_id' is a required field for all products for Product List Viewed", + ); + } + rawPayload.events.push({ + eventType: 'monetate:context:ProductThumbnailView', + products: properties.products.map((product) => product.product_id.toString()), + }); + } else { + throw new InstrumentationError("'products' missing or not array in Product List Viewed"); + } + return rawPayload; +}; + +const handleProductAdded = (properties, rawPayload) => { + const currency = properties.currency || 'USD'; + const sku = properties.sku || ''; + if ( + properties.product_id && + properties.quantity && + Number.isInteger(properties.quantity) && + properties.cart_value + ) { + rawPayload.events.push({ + eventType: 'monetate:context:Cart', + cartLines: [ + { + pid: properties.product_id ? properties.product_id.toString() : '', + sku, + quantity: properties.quantity, + value: properties.cart_value ? properties.cart_value.toString() : '', + currency, + }, + ], + }); + } else { + throw new InstrumentationError( + "'product_id', 'quantity', 'cart_value' are required fields and 'quantity' should be a number for Product Added", + ); + } + return rawPayload; +}; + +const handleCartViewed = (properties, rawPayload) => { + if (properties.products && Array.isArray(properties.products)) { + const cartProducts = properties.products.filter( + (product) => + product.quantity && + Number.isInteger(product.quantity) && + isDefinedAndNotNull(product.price) && + typeof product.price === 'number' && + product.product_id, + ); + if (cartProducts.length !== properties.products.length) { + throw new InstrumentationError( + "'quantity', 'price' and 'product_id' are required fields and 'quantity' and 'price' should be a number for all products for Cart Viewed", + ); + } + rawPayload.events.push({ + eventType: 'monetate:context:Cart', + cartLines: properties.products.map((product) => { + const cartValue = (product.quantity * product.price).toFixed(2); + const currency = product.currency || properties.currency || 'USD'; + const sku = product.sku || ''; + return { + pid: product.product_id ? product.product_id.toString() : '', + sku, + quantity: product.quantity, + value: cartValue ? cartValue.toString() : '', + currency, + }; + }), + }); + } + return rawPayload; +}; + +const handleOrderCompleted = (properties, rawPayload) => { + const purchaseId = properties.order_id; + const { products } = properties; + if (purchaseId && products && Array.isArray(products)) { + const purchaseLines = products.filter( + (product) => + product.quantity && + Number.isInteger(product.quantity) && + isDefinedAndNotNull(product.price) && + typeof product.price === 'number' && + product.product_id, + ); + if (purchaseLines.length !== products.length) { + throw new InstrumentationError( + "'quantity', 'price' and 'product_id' are required fields and 'quantity' and 'price' should be a number for all products for Order Completed", + ); + } + rawPayload.events.push({ + eventType: 'monetate:context:Purchase', + purchaseId, + purchaseLines: purchaseLines.map((product) => { + const valueStr = (product.quantity * product.price).toFixed(2); + const currency = product.currency || properties.currency || 'USD'; + const sku = product.sku || ''; + return { + pid: product.product_id ? product.product_id.toString() : '', + sku, + quantity: product.quantity, + value: valueStr ? valueStr.toString() : '', + currency, + }; + }), + }); + } + return rawPayload; +}; + +module.exports = { + handleProductViewed, + handleProductListViewed, + handleProductAdded, + handleCartViewed, + handleOrderCompleted, + responseBuilder, + constructPayload, +}; diff --git a/src/v0/destinations/monetate/utils.test.js b/src/v0/destinations/monetate/utils.test.js new file mode 100644 index 000000000000..839f8a7152c8 --- /dev/null +++ b/src/v0/destinations/monetate/utils.test.js @@ -0,0 +1,185 @@ +const { + handleProductViewed, + handleProductListViewed, + handleProductAdded, + handleCartViewed, + handleOrderCompleted, +} = require('./utils'); + +const getTestMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + properties: { + product_id: 123, + category: 'test', + email: 'test@test.com', + templateId: 1234, + campaignId: 5678, + name: 'pageName', + countryCode: 'IN', + zipCode: '700114', + conversionDateTime: '2022-01-01 12:32:45-08:00', + quantity: 2, + price: 123, + order_id: 1234, + }, + }; + return message; +}; + +describe('Monetate utils unit test cases', () => { + describe('handleProductViewed util test cases', () => { + it('flow check', () => { + let expectedOutput = { + events: [ + { + eventType: 'monetate:context:ProductDetailView', + products: [{ productId: 123, sku: '' }], + }, + ], + }; + expect(handleProductViewed(getTestMessage().properties, { events: [] })).toEqual( + expectedOutput, + ); + }); + }); + + describe('handleProductListViewed util test cases', () => { + it('flow check', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [ + { + sku: 'sku 1 for order completed', + price: 8900, + currency: 'INR', + quantity: 1, + product_id: 'p2022222', + }, + { + sku: 'sku 2 for order completed', + price: 90, + quantity: 2, + product_id: 'p201111', + }, + ]; + let expectedOutput = { + events: [ + { eventType: 'monetate:context:ProductThumbnailView', products: ['p2022222', 'p201111'] }, + ], + }; + expect(handleProductListViewed(fittingPayload.properties, { events: [] })).toEqual( + expectedOutput, + ); + }); + }); + + describe('handleProductViewed util test cases', () => { + it('flow check', () => { + const fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.cart_value = 1234; + let expectedOutput = { + events: [ + { + cartLines: [{ currency: 'USD', pid: '123', quantity: 2, sku: '', value: '1234' }], + eventType: 'monetate:context:Cart', + }, + ], + }; + expect(handleProductAdded(fittingPayload.properties, { events: [] })).toEqual(expectedOutput); + }); + }); + + describe('handleCartViewed util test cases', () => { + it('flow check', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [ + { + sku: 'sku 1 for order completed', + price: 8900, + currency: 'INR', + quantity: 1, + product_id: 'p2022222', + }, + { + sku: 'sku 2 for order completed', + price: 90, + quantity: 2, + product_id: 'p201111', + }, + ]; + let expectedOutput = { + events: [ + { + cartLines: [ + { + currency: 'INR', + pid: 'p2022222', + quantity: 1, + sku: 'sku 1 for order completed', + value: '8900.00', + }, + { + currency: 'USD', + pid: 'p201111', + quantity: 2, + sku: 'sku 2 for order completed', + value: '180.00', + }, + ], + eventType: 'monetate:context:Cart', + }, + ], + }; + expect(handleCartViewed(fittingPayload.properties, { events: [] })).toEqual(expectedOutput); + }); + }); + + describe('handleOrderCompleted util test cases', () => { + it('flow check', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.properties.products = [ + { + sku: 'sku 1 for order completed', + price: 8900, + currency: 'INR', + quantity: 1, + product_id: 'p2022222', + }, + { + sku: 'sku 2 for order completed', + price: 90, + quantity: 2, + product_id: 'p201111', + }, + ]; + let expectedOutput = { + events: [ + { + eventType: 'monetate:context:Purchase', + purchaseId: 1234, + purchaseLines: [ + { + currency: 'INR', + pid: 'p2022222', + quantity: 1, + sku: 'sku 1 for order completed', + value: '8900.00', + }, + { + currency: 'USD', + pid: 'p201111', + quantity: 2, + sku: 'sku 2 for order completed', + value: '180.00', + }, + ], + }, + ], + }; + expect(handleOrderCompleted(fittingPayload.properties, { events: [] })).toEqual( + expectedOutput, + ); + }); + }); +}); diff --git a/src/v0/destinations/mp/deleteUsers.js b/src/v0/destinations/mp/deleteUsers.js index 7a8967855803..5ba6f756d1ac 100644 --- a/src/v0/destinations/mp/deleteUsers.js +++ b/src/v0/destinations/mp/deleteUsers.js @@ -7,6 +7,7 @@ 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'); /** * This function will help to delete the users one by one from the userAttributes array. @@ -39,7 +40,7 @@ const userDeletionHandler = async (userAttributes, config) => { }); const headers = { accept: 'text/plain', - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, }; // batchEvents = [[e1,e2,e3,..batchSize],[e1,e2,e3,..batchSize]..] diff --git a/src/v0/destinations/mp/transform.js b/src/v0/destinations/mp/transform.js index 4dc33d22c584..06d2d7247cbe 100644 --- a/src/v0/destinations/mp/transform.js +++ b/src/v0/destinations/mp/transform.js @@ -347,23 +347,24 @@ const processGroupEvents = (message, type, destination) => { }; const processSingleMessage = async (message, destination) => { - if (message.userId) { - message.userId = String(message.userId); + const clonedMessage = { ...message }; + if (clonedMessage.userId) { + clonedMessage.userId = String(clonedMessage.userId); } - if (message.anonymousId) { - message.anonymousId = String(message.anonymousId); + if (clonedMessage.anonymousId) { + clonedMessage.anonymousId = String(clonedMessage.anonymousId); } - if (!message.type) { + if (!clonedMessage.type) { throw new InstrumentationError('Event type is required'); } - switch (message.type) { + switch (clonedMessage.type) { case EventType.TRACK: - return processTrack(message, destination); + return processTrack(clonedMessage, destination); case EventType.SCREEN: case EventType.PAGE: - return processPageOrScreenEvents(message, message.type, destination); + return processPageOrScreenEvents(clonedMessage, clonedMessage.type, destination); case EventType.IDENTIFY: - return processIdentifyEvents(message, message.type, destination); + return processIdentifyEvents(clonedMessage, clonedMessage.type, destination); case EventType.ALIAS: if (destination.Config?.identityMergeApi === 'simplified') { throw new InstrumentationError( @@ -372,10 +373,10 @@ const processSingleMessage = async (message, destination) => { } return processAliasEvents(message, message.type, destination); case EventType.GROUP: - return processGroupEvents(message, message.type, destination); + return processGroupEvents(clonedMessage, clonedMessage.type, destination); default: - throw new InstrumentationError(`Event type ${message.type} is not supported`); + throw new InstrumentationError(`Event type ${clonedMessage.type} is not supported`); } }; diff --git a/src/v0/destinations/ometria/util.js b/src/v0/destinations/ometria/util.js index e489fabbcfbf..304c4fe5b209 100644 --- a/src/v0/destinations/ometria/util.js +++ b/src/v0/destinations/ometria/util.js @@ -97,25 +97,28 @@ const addressMappper = (address) => { const contactPayloadValidator = (payload) => { const updatedPayload = payload; - if (payload['@force_optin'] && typeof payload['@force_optin'] !== 'boolean') { - updatedPayload['@force_optin'] = null; + const FORCE_OPT_IN_KEY = '@force_optin'; + if (payload[FORCE_OPT_IN_KEY] && typeof payload[FORCE_OPT_IN_KEY] !== 'boolean') { + updatedPayload[FORCE_OPT_IN_KEY] = null; logger.error('forceOptin must contain only boolean value.'); } if (payload.phone_number && !isValidPhone(payload.phone_number)) { updatedPayload.phone_number = null; logger.error('phone number format must be E.164.'); } + + const TIMESTAMP_FORMAT_ERR_MSG = 'timestamp format must be ISO 8601'; if (payload.timestamp_acquired && !isValidTimestamp(payload.timestamp_acquired)) { updatedPayload.timestamp_acquired = null; - logger.error('timestamp format must be ISO 8601.'); + logger.error(TIMESTAMP_FORMAT_ERR_MSG); } if (payload.timestamp_subscribed && !isValidTimestamp(payload.timestamp_subscribed)) { updatedPayload.timestamp_subscribed = null; - logger.error('timestamp format must be ISO 8601.'); + logger.error(TIMESTAMP_FORMAT_ERR_MSG); } if (payload.timestamp_unsubscribed && !isValidTimestamp(payload.timestamp_unsubscribed)) { updatedPayload.timestamp_unsubscribed = null; - logger.error('timestamp format must be ISO 8601.'); + logger.error(TIMESTAMP_FORMAT_ERR_MSG); } return updatedPayload; }; diff --git a/src/v0/destinations/one_signal/transform.js b/src/v0/destinations/one_signal/transform.js index af8b36696b0b..db699935f4dd 100644 --- a/src/v0/destinations/one_signal/transform.js +++ b/src/v0/destinations/one_signal/transform.js @@ -18,14 +18,15 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, eventType) => { if (payload) { const response = defaultRequestConfig(); response.endpoint = `${BASE_URL}${endpoint}`; response.headers = { - Accept: 'application/json', - 'Content-Type': 'application/json', + Accept: JSON_MIME_TYPE, + 'Content-Type': JSON_MIME_TYPE, }; if (eventType.toLowerCase() === 'identify' && endpoint === '/players') { response.method = defaultPostRequestConfig.requestMethod; @@ -164,8 +165,9 @@ const groupResponseBuilder = (message, { Config }) => { } endpoint = `${endpoint}/${appId}/users/${externalUserId}`; const payload = {}; - const tags = {}; - tags.groupId = groupId; + const tags = { + groupId, + }; // Populating tags using allowed properties(from dashboard) const properties = getFieldValueFromMessage(message, 'traits'); diff --git a/src/v0/destinations/one_signal/util.js b/src/v0/destinations/one_signal/util.js index 9a7cd9bf1739..4b53949e55c8 100644 --- a/src/v0/destinations/one_signal/util.js +++ b/src/v0/destinations/one_signal/util.js @@ -12,12 +12,8 @@ const deviceTypeMapping = { // This function is used to check for the valid device_type value. device_type value should be integer // and can be from [0 to 14] only. -const validateDeviceType = (deviceType) => { - if (Number.isNaN(deviceType) || deviceType < 0 || deviceType > 14) { - return false; - } - return true; -}; +const validateDeviceType = (deviceType) => + !(Number.isNaN(deviceType) || deviceType < 0 || deviceType > 14); /** * This function is used to populate the tags using the traits diff --git a/src/v0/destinations/optimizely_fullstack/transform.js b/src/v0/destinations/optimizely_fullstack/transform.js index 20e1faae2924..355164b0b9a0 100644 --- a/src/v0/destinations/optimizely_fullstack/transform.js +++ b/src/v0/destinations/optimizely_fullstack/transform.js @@ -9,6 +9,7 @@ const { const { validateConfig, validateEvent } = require('./util'); const { CONFIG_CATEGORIES, MAPPING_CONFIG, getTrackEndPoint } = require('./config'); const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint, destination) => { if (payload) { @@ -16,7 +17,7 @@ const responseBuilder = (payload, endpoint, destination) => { const { sdkKey } = destination.Config; response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'X-Optimizely-SDK-Key': sdkKey, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/pagerduty/transform.js b/src/v0/destinations/pagerduty/transform.js index 50159bc842fb..d7a8848ace43 100644 --- a/src/v0/destinations/pagerduty/transform.js +++ b/src/v0/destinations/pagerduty/transform.js @@ -5,6 +5,7 @@ const { defaultPostRequestConfig, removeUndefinedAndNullValues, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { ConfigurationError, TransformationError, @@ -17,7 +18,7 @@ const responseBuilder = (payload, endpoint) => { const response = defaultRequestConfig(); response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = removeUndefinedAndNullValues(payload); diff --git a/src/v0/destinations/pardot/networkHandler.js b/src/v0/destinations/pardot/networkHandler.js index 1461126686dd..07bb9ae11d33 100644 --- a/src/v0/destinations/pardot/networkHandler.js +++ b/src/v0/destinations/pardot/networkHandler.js @@ -25,12 +25,10 @@ const { NetworkError } = require('../../util/errorTypes'); */ const getAuthErrCategory = (code) => { - switch (code) { - case 184: - return REFRESH_TOKEN; - default: - return ''; + if (code === 184) { + return REFRESH_TOKEN; } + return ''; }; const RETRYABLE_CODES = [85, 116, 120, 121, 183, 184, 214]; @@ -119,12 +117,12 @@ const pardotProxyRequest = async (request) => { return response; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = pardotProxyRequest; this.prepareProxy = prepareProxyReq; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/personalize/transform.js b/src/v0/destinations/personalize/transform.js index bc81eb261233..c8eca2af2ffc 100644 --- a/src/v0/destinations/personalize/transform.js +++ b/src/v0/destinations/personalize/transform.js @@ -12,7 +12,7 @@ const { const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const putEventsHandler = (message, destination) => { - const { properties, anonymousId, event, messageId } = message; + const { properties, anonymousId, event, messageId, context } = message; const { customMappings, trackingId, disableStringify } = destination.Config; if (!event || !isDefinedAndNotNull(event) || isBlank(event)) { @@ -84,7 +84,7 @@ const putEventsHandler = (message, destination) => { : userId, // not using getFieldValueFromMessage(message, "userId") as we want to // prioritize anonymousId over userId - sessionId: anonymousId || userId || message.context?.sessionId, + sessionId: anonymousId || userId || context?.sessionId, trackingId, eventList: [outputEvent], }; diff --git a/src/v0/destinations/pinterest_tag/transform.js b/src/v0/destinations/pinterest_tag/transform.js index 4dbbfb84d08c..4a0f9da21ea7 100644 --- a/src/v0/destinations/pinterest_tag/transform.js +++ b/src/v0/destinations/pinterest_tag/transform.js @@ -36,6 +36,7 @@ const responseBuilderSimple = (finalPayload, { Config }) => { response.endpoint = ENDPOINT; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = removeUndefinedAndNullValues(finalPayload); + response.headers = { 'Content-Type': 'application/json' }; if (apiVersion === API_VERSION.v5) { @@ -145,7 +146,6 @@ const process = (event) => { const generateBatchedPayloadForArray = (events) => { const { batchedRequest } = defaultBatchRequestConfig(); const batchResponseList = events.map((event) => event.body.JSON); - batchedRequest.body.JSON = { data: batchResponseList }; batchedRequest.endpoint = events[0].endpoint; batchedRequest.headers = events[0].headers; diff --git a/src/v0/destinations/posthog/transform.js b/src/v0/destinations/posthog/transform.js index ff20a8688268..0bdb9e1fea32 100644 --- a/src/v0/destinations/posthog/transform.js +++ b/src/v0/destinations/posthog/transform.js @@ -15,6 +15,7 @@ const { 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. const generatePropertyDefination = (message) => { @@ -129,7 +130,7 @@ const responseBuilderSimple = (message, category, destination) => { }/batch`; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON = responseBody; return response; diff --git a/src/v0/destinations/profitwell/transform.js b/src/v0/destinations/profitwell/transform.js index 1aa3c5b3747e..affd2b14dc8d 100644 --- a/src/v0/destinations/profitwell/transform.js +++ b/src/v0/destinations/profitwell/transform.js @@ -1,41 +1,30 @@ -const get = require('get-value'); const { EventType } = require('../../../constants'); -const { getSubscriptionHistory, unixTimestampOrError, isValidPlanCurrency } = require('./utils'); const { - getDestinationExternalID, + getSubscriptionHistory, + unixTimestampOrError, + isValidPlanCurrency, + validatePayloadAndRetunImpIds, + createMissingSubscriptionResponse, + createResponseForSubscribedUser, +} = require('./utils'); +const { defaultRequestConfig, defaultPostRequestConfig, - defaultPutRequestConfig, removeUndefinedAndNullValues, constructPayload, - getFieldValueFromMessage, simpleProcessRouterDest, } = require('../../util'); -const { BASE_ENDPOINT, createPayloadMapping, updatePayloadMapping } = require('./config'); -const { - NetworkError, - ConfigurationError, - InstrumentationError, - NetworkInstrumentationError, -} = require('../../util/errorTypes'); +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'); const identifyResponseBuilder = async (message, { Config }) => { - const userId = getDestinationExternalID(message, 'profitwellUserId'); - const userAlias = getFieldValueFromMessage(message, 'userId'); - - if (!userId && !userAlias) { - throw new InstrumentationError('userId or userAlias is required for identify'); - } - - let subscriptionId = getDestinationExternalID(message, 'profitwellSubscriptionId'); - let subscriptionAlias = - get(message, 'traits.subscriptionAlias') || get(message, 'context.traits.subscriptionAlias'); - - if (!subscriptionId && !subscriptionAlias) { - throw new InstrumentationError('subscriptionId or subscriptionAlias is required for identify'); - } + const { userId, userAlias, subscriptionId, subscriptionAlias } = + validatePayloadAndRetunImpIds(message); + let finalSubscriptionId = subscriptionId; + let finalSubscriptionAlias = subscriptionAlias; const targetUrl = `${BASE_ENDPOINT}/v2/users/${userId || userAlias}/`; const res = await getSubscriptionHistory(targetUrl, { @@ -50,34 +39,21 @@ const identifyResponseBuilder = async (message, { Config }) => { if (res.success) { let subscriptionFound = true; const valFound = res.response.data.some((element) => { - if (userId && userId === element.user_id) { - if (subscriptionId && subscriptionId === element.subscription_id) { - subscriptionId = element.subscription_id; - subscriptionFound = true; - return true; - } - if ( - !subscriptionId && - subscriptionAlias && - subscriptionAlias === element.subscription_alias - ) { - subscriptionAlias = element.subscription_alias; - subscriptionFound = true; - return true; - } - subscriptionFound = false; - } else if (userAlias && userAlias === element.user_alias) { - if (subscriptionId && subscriptionId === element.subscription_id) { - subscriptionId = element.subscription_id; + if ( + (userId && userId === element.user_id) || + (userAlias && userAlias === element.user_alias) + ) { + if (finalSubscriptionId && finalSubscriptionId === element.subscription_id) { + finalSubscriptionId = element.subscription_id; subscriptionFound = true; return true; } if ( - !subscriptionId && - subscriptionAlias && - subscriptionAlias === element.subscription_alias + !finalSubscriptionId && + finalSubscriptionAlias && + finalSubscriptionAlias === element.subscription_alias ) { - subscriptionAlias = element.subscription_alias; + finalSubscriptionAlias = element.subscription_alias; subscriptionFound = true; return true; } @@ -87,84 +63,24 @@ const identifyResponseBuilder = async (message, { Config }) => { }); if (!subscriptionFound) { - // for a given userId, subscriptionId not found - // dropping event if profitwellSubscriptionId (externalId) did not - // match with any subscription_id at destination - if (subscriptionId) { - throw new NetworkInstrumentationError('Profitwell subscription_id not found'); - } - payload = constructPayload(message, createPayloadMapping); - payload = { - ...payload, - user_id: userId, - user_alias: userAlias, - }; - if ( - payload.plan_interval && - !( - payload.plan_interval.toLowerCase() === 'month' || - payload.plan_interval.toLowerCase() === 'year' - ) - ) { - throw new InstrumentationError('invalid format for planInterval. Aborting'); - } - if (payload.plan_currency && !isValidPlanCurrency(payload.plan_currency)) { - payload.plan_currency = null; - } - if ( - payload.status && - !(payload.status.toLowerCase() === 'active' || payload.status.toLowerCase() === 'trialing') - ) { - payload.status = null; - } - payload.effective_date = unixTimestampOrError( - payload.effective_date, - message.timestamp, - message.originalTimestamp, + return createMissingSubscriptionResponse( + userId, + userAlias, + finalSubscriptionId, + finalSubscriptionAlias, + message, + Config, ); - response.method = defaultPostRequestConfig.requestMethod; - response.endpoint = `${BASE_ENDPOINT}/v2/subscriptions/`; - response.headers = { - 'Content-Type': 'application/json', - Authorization: Config.privateApiKey, - }; - response.body.JSON = removeUndefinedAndNullValues(payload); - return response; } // for a given userId, subscription is found at dest. if (valFound) { - payload = constructPayload(message, updatePayloadMapping); - if ( - payload.plan_interval && - !( - payload.plan_interval.toLowerCase() === 'month' || - payload.plan_interval.toLowerCase() === 'year' - ) - ) { - throw new InstrumentationError('invalid format for planInterval. Aborting'); - } - if ( - payload.status && - !(payload.status.toLowerCase() === 'active' || payload.status.toLowerCase() === 'trialing') - ) { - payload.status = null; - } - payload.effective_date = unixTimestampOrError( - payload.effective_date, - message.timestamp, - message.originalTimestamp, + return createResponseForSubscribedUser( + message, + finalSubscriptionId, + finalSubscriptionAlias, + Config, ); - response.method = defaultPutRequestConfig.requestMethod; - response.endpoint = `${BASE_ENDPOINT}/v2/subscriptions/${ - subscriptionId || subscriptionAlias - }/`; - response.headers = { - 'Content-Type': 'application/json', - Authorization: Config.privateApiKey, - }; - response.body.JSON = removeUndefinedAndNullValues(payload); - return response; } } @@ -210,15 +126,11 @@ const identifyResponseBuilder = async (message, { Config }) => { ) { payload.status = null; } - payload.effective_date = unixTimestampOrError( - payload.effective_date, - message.timestamp, - message.originalTimestamp, - ); + payload.effective_date = unixTimestampOrError(payload.effective_date, message.originalTimestamp); response.method = defaultPostRequestConfig.requestMethod; response.endpoint = `${BASE_ENDPOINT}/v2/subscriptions/`; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: Config.privateApiKey, }; response.body.JSON = removeUndefinedAndNullValues(payload); @@ -238,12 +150,10 @@ const process = async (event) => { const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.IDENTIFY: - response = await identifyResponseBuilder(message, destination); - break; - default: - throw new InstrumentationError(`message type ${messageType} not supported`); + if (messageType === EventType.IDENTIFY) { + response = await identifyResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } return response; }; diff --git a/src/v0/destinations/profitwell/utils.js b/src/v0/destinations/profitwell/utils.js index cb9b7d29f971..7fb0bda3b900 100644 --- a/src/v0/destinations/profitwell/utils.js +++ b/src/v0/destinations/profitwell/utils.js @@ -1,6 +1,17 @@ +const get = require('get-value'); const { httpGET } = require('../../../adapters/network'); -const { toUnixTimestamp } = require('../../util'); -const { InstrumentationError } = require('../../util/errorTypes'); +const { + toUnixTimestamp, + getDestinationExternalID, + getFieldValueFromMessage, + defaultRequestConfig, + defaultPostRequestConfig, + defaultPutRequestConfig, + removeUndefinedAndNullValues, + constructPayload, +} = require('../../util'); +const { BASE_ENDPOINT, createPayloadMapping, updatePayloadMapping } = require('./config'); +const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); const CURRENCY_CODES = [ 'aed', @@ -188,8 +199,116 @@ const unixTimestampOrError = (date, timestamp, originalTimestamp) => { const isValidPlanCurrency = (planCurrency) => CURRENCY_CODES.includes(planCurrency.toLowerCase()); +const validatePayloadAndRetunImpIds = (message) => { + const userId = getDestinationExternalID(message, 'profitwellUserId'); + const userAlias = getFieldValueFromMessage(message, 'userId'); + + const subscriptionId = getDestinationExternalID(message, 'profitwellSubscriptionId'); + const subscriptionAlias = + get(message, 'traits.subscriptionAlias') || get(message, 'context.traits.subscriptionAlias'); + + if (!userId && !userAlias) { + throw new InstrumentationError('userId or userAlias is required for identify'); + } + if (!subscriptionId && !subscriptionAlias) { + throw new InstrumentationError('subscriptionId or subscriptionAlias is required for identify'); + } + return { userId, userAlias, subscriptionId, subscriptionAlias }; +}; + +function createMissingSubscriptionResponse( + userId, + userAlias, + subscriptionId, + subscriptionAlias, + message, + Config, +) { + // for a given userId, subscriptionId not found + // dropping event if profitwellSubscriptionId (externalId) did not + // match with any subscription_id at destination + let payload = {}; + const response = defaultRequestConfig(); + if (subscriptionId) { + throw new NetworkInstrumentationError('Profitwell subscription_id not found'); + } + payload = constructPayload(message, createPayloadMapping); + payload = { + ...payload, + user_id: userId, + user_alias: userAlias, + }; + if ( + payload.plan_interval && + !( + payload.plan_interval.toLowerCase() === 'month' || + payload.plan_interval.toLowerCase() === 'year' + ) + ) { + throw new InstrumentationError('invalid format for planInterval. Aborting'); + } + if (payload.plan_currency && !isValidPlanCurrency(payload.plan_currency)) { + payload.plan_currency = null; + } + if ( + payload.status && + !(payload.status.toLowerCase() === 'active' || payload.status.toLowerCase() === 'trialing') + ) { + payload.status = null; + } + payload.effective_date = unixTimestampOrError( + payload.effective_date, + message.timestamp, + message.originalTimestamp, + ); + response.method = defaultPostRequestConfig.requestMethod; + response.endpoint = `${BASE_ENDPOINT}/v2/subscriptions/`; + response.headers = { + 'Content-Type': 'application/json', + Authorization: Config.privateApiKey, + }; + response.body.JSON = removeUndefinedAndNullValues(payload); + return response; +} + +const createResponseForSubscribedUser = (message, subscriptionId, subscriptionAlias, Config) => { + const response = defaultRequestConfig(); + const payload = constructPayload(message, updatePayloadMapping); + if ( + payload.plan_interval && + !( + payload.plan_interval.toLowerCase() === 'month' || + payload.plan_interval.toLowerCase() === 'year' + ) + ) { + throw new InstrumentationError('invalid format for planInterval. Aborting'); + } + if ( + payload.status && + !(payload.status.toLowerCase() === 'active' || payload.status.toLowerCase() === 'trialing') + ) { + payload.status = null; + } + payload.effective_date = unixTimestampOrError( + payload.effective_date, + unixTimestampOrError, + message.originalTimestamp, + ); + response.method = defaultPutRequestConfig.requestMethod; + response.endpoint = `${BASE_ENDPOINT}/v2/subscriptions/${subscriptionId || subscriptionAlias}/`; + response.headers = { + 'Content-Type': 'application/json', + Authorization: Config.privateApiKey, + }; + response.body.JSON = removeUndefinedAndNullValues(payload); + return response; +}; + module.exports = { getSubscriptionHistory, unixTimestampOrError, isValidPlanCurrency, + validatePayloadAndRetunImpIds, + createMissingSubscriptionResponse, + createResponseForSubscribedUser, }; diff --git a/src/v0/destinations/profitwell/utils.test.js b/src/v0/destinations/profitwell/utils.test.js new file mode 100644 index 000000000000..7b954fc02df5 --- /dev/null +++ b/src/v0/destinations/profitwell/utils.test.js @@ -0,0 +1,172 @@ +const { + validatePayloadAndRetunImpIds, + createMissingSubscriptionResponse, + createResponseForSubscribedUser, +} = require('./utils'); + +const getTestMessage = () => { + let message = { + event: 'testEventName', + anonymousId: 'anonId', + traits: { + email: 'abc@test.com', + name: 'rudder', + planId: 'testPlanId', + planInterval: 'month', + value: 'testValue', + effectiveDate: '1609748705', + address: { + city: 'kolkata', + country: 'India', + }, + createdAt: '2014-05-21T15:54:20Z', + timestamp: '2014-05-21T15:54:20Z', + }, + properties: { + category: 'test', + email: 'test@test.com', + templateId: 1234, + campaignId: 5678, + name: 'pageName', + }, + context: { + device: { + token: 1234, + }, + os: { + token: 5678, + }, + mappedToDestination: false, + externalId: [ + { + id: '12345', + identifierType: 'test_identifier', + }, + ], + }, + }; + return message; +}; + +describe('profitwell utils test cases', () => { + describe('createResponseForSubscribedUser', () => { + it('correct flow', async () => { + let expectedOutput = { + body: { + FORM: {}, + JSON: { + effective_date: 1609748705, + plan_id: 'testPlanId', + plan_interval: 'month', + value: 'testValue', + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.profitwell.com/v2/subscriptions/testId/', + files: {}, + headers: { Authorization: 'testApiKey', 'Content-Type': 'application/json' }, + method: 'PUT', + params: {}, + type: 'REST', + version: '1', + }; + expect( + createResponseForSubscribedUser(getTestMessage(), 'testId', 'testAlias', { + privateApiKey: 'testApiKey', + }), + ).toEqual(expectedOutput); + }); + + it('erroneous flow', async () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.traits.effectiveDate = '2019-10-15T09:35:31.288Z'; + expect(() => + createResponseForSubscribedUser(fittingPayload, 'testId', 'testAlias', { + privateApiKey: 'testApiKey', + }), + ).toThrow('Invalid timestamp format for effectiveDate. Aborting'); + }); + }); + + describe('createMissingSubscriptionResponse', () => { + it('correct flow', async () => { + let expectedOutput = { + body: { + FORM: {}, + JSON: { + effective_date: 1609748705, + email: 'abc@test.com', + plan_id: 'testPlanId', + plan_interval: 'month', + user_alias: 'testAlias', + user_id: 'testId', + value: 'testValue', + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.profitwell.com/v2/subscriptions/', + files: {}, + headers: { Authorization: 'testApiKey', 'Content-Type': 'application/json' }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }; + expect( + createMissingSubscriptionResponse('testId', 'testAlias', null, null, getTestMessage(), { + privateApiKey: 'testApiKey', + }), + ).toEqual(expectedOutput); + }); + + it('erroneous flow with wrong plan interval', async () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.traits.planInterval = 'test'; + expect(() => + createMissingSubscriptionResponse('testId', 'testAlias', null, null, fittingPayload, { + privateApiKey: 'testApiKey', + }), + ).toThrow('invalid format for planInterval. Aborting'); + }); + + it('erroneous flow with subscriptionId', async () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.traits.planInterval = 'test'; + expect(() => + createMissingSubscriptionResponse('testId', 'testAlias', 124, fittingPayload, { + privateApiKey: 'testApiKey', + }), + ).toThrow('Profitwell subscription_id not found'); + }); + }); + + describe('validatePayloadAndRetunImpIds', () => { + it('should validate and return correct ids', () => { + let fittingPayload = { ...getTestMessage() }; + fittingPayload.traits.subscriptionAlias = 'testAlias'; + let expectedOutput = { + subscriptionAlias: 'testAlias', + subscriptionId: null, + userAlias: 'anonId', + userId: null, + }; + expect(validatePayloadAndRetunImpIds(fittingPayload)).toEqual(expectedOutput); + }); + + it('should error out if both subscriptionId and subscriptionAlias are absent', () => { + expect(() => validatePayloadAndRetunImpIds(getTestMessage())).toThrow( + 'subscriptionId or subscriptionAlias is required for identify', + ); + }); + + it('should error out if both userId and userAlias are absent', () => { + let fittingPayload = { ...getTestMessage() }; + delete fittingPayload.anonymousId; + expect(() => validatePayloadAndRetunImpIds(fittingPayload)).toThrow( + 'userId or userAlias is required for identify', + ); + }); + }); +}); diff --git a/src/v0/destinations/revenue_cat/transform.js b/src/v0/destinations/revenue_cat/transform.js index 96320e919218..5f165a92789a 100644 --- a/src/v0/destinations/revenue_cat/transform.js +++ b/src/v0/destinations/revenue_cat/transform.js @@ -20,6 +20,7 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const trackResponseBuilder = async (message, category, { Config }) => { if (!Config.xPlatform) { @@ -45,7 +46,7 @@ const trackResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.apiKey); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'X-Platform': `${Config.xPlatform}`, }; response.body.JSON = payload; @@ -62,7 +63,7 @@ const trackResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.apiKey); response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'X-Platform': `${Config.xPlatform}`, }; response.body.JSON = payload; @@ -107,7 +108,7 @@ const identifyResponseBuilder = async (message, category, { Config }) => { const basicAuth = Buffer.from(Config.apiKey); responseGet.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; returnValue.push(responseGet); @@ -118,7 +119,7 @@ const identifyResponseBuilder = async (message, category, { Config }) => { response.headers = { Authorization: `Basic ${basicAuth}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.body.JSON.attributes = payload; returnValue.push(response); diff --git a/src/v0/destinations/rockerbox/transform.js b/src/v0/destinations/rockerbox/transform.js index edd6aaa21440..5369afa7e5c1 100644 --- a/src/v0/destinations/rockerbox/transform.js +++ b/src/v0/destinations/rockerbox/transform.js @@ -53,12 +53,10 @@ const process = (event) => { let response; const messageType = message.type.toLowerCase(); - switch (messageType) { - case EventType.TRACK: - response = responseBuilderSimple(message, CONFIG_CATEGORIES.TRACK, destination); - break; - default: - throw new InstrumentationError(`Message type ${messageType} is not supported`); + if (messageType === EventType.TRACK) { + response = responseBuilderSimple(message, CONFIG_CATEGORIES.TRACK, destination); + } else { + throw new InstrumentationError(`Message type ${messageType} is not supported`); } return response; }; diff --git a/src/v0/destinations/salesforce/networkHandler.js b/src/v0/destinations/salesforce/networkHandler.js index c8160dac0237..622d2ae731cc 100644 --- a/src/v0/destinations/salesforce/networkHandler.js +++ b/src/v0/destinations/salesforce/networkHandler.js @@ -19,12 +19,12 @@ const responseHandler = (destinationResponse, destType) => { }; }; -const networkHandler = function () { +function networkHandler() { this.responseHandler = responseHandler; this.proxy = proxyRequest; this.prepareProxy = prepareProxyRequest; this.processAxiosResponse = processAxiosResponse; -}; +} module.exports = { networkHandler, diff --git a/src/v0/destinations/salesforce/transform.js b/src/v0/destinations/salesforce/transform.js index cdf8d1f34275..85eedec83dd7 100644 --- a/src/v0/destinations/salesforce/transform.js +++ b/src/v0/destinations/salesforce/transform.js @@ -26,6 +26,7 @@ const { const { getAccessToken, salesforceResponseHandler } = require('./utils'); const { handleHttpRequest } = require('../../../adapters/network'); const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); // Basic response builder // We pass the parameterMap with any processing-specific key-value pre-populated @@ -84,7 +85,7 @@ function responseBuilderSimple( const response = defaultRequestConfig(); const header = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: authorizationData.token, }; response.method = defaultPostRequestConfig.requestMethod; diff --git a/src/v0/destinations/segment/transform.js b/src/v0/destinations/segment/transform.js index 33338c977bf5..aac1857c9a8c 100644 --- a/src/v0/destinations/segment/transform.js +++ b/src/v0/destinations/segment/transform.js @@ -6,13 +6,14 @@ const { removeUndefinedAndNullValues, getFieldValueFromMessage, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, segmentConfig) { const basicAuth = Buffer.from(`${segmentConfig.writeKey}:`).toString('base64'); const response = defaultRequestConfig(); const header = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Basic ${basicAuth}`, }; response.method = defaultPostRequestConfig.requestMethod; @@ -51,12 +52,8 @@ function getSegmentConfig(destination, message) { const segmentConfig = {}; const configKeys = Object.keys(destination.Config); configKeys.forEach((key) => { - switch (key) { - case destinationConfigKeys.writeKey: - segmentConfig.writeKey = `${destination.Config[key]}`; - break; - default: - break; + if (key === destinationConfigKeys.writeKey) { + segmentConfig.writeKey = `${destination.Config[key]}`; } }); diff --git a/src/v0/destinations/sendgrid/transform.js b/src/v0/destinations/sendgrid/transform.js index ba44631b29a2..0f944e5f28fd 100644 --- a/src/v0/destinations/sendgrid/transform.js +++ b/src/v0/destinations/sendgrid/transform.js @@ -39,12 +39,13 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, method, endpoint, apiKey) => { if (payload) { const response = defaultRequestConfig(); response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }; response.method = method; @@ -177,7 +178,7 @@ const generateBatchedPaylaodForArray = (events, combination) => { batchEventResponse.batchedRequest.method = defaultPutRequestConfig.requestMethod; batchEventResponse.batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }; batchEventResponse = { diff --git a/src/v0/destinations/sendgrid/util.js b/src/v0/destinations/sendgrid/util.js index 0309e80e07fd..667f4f4176f3 100644 --- a/src/v0/destinations/sendgrid/util.js +++ b/src/v0/destinations/sendgrid/util.js @@ -22,7 +22,7 @@ const { } = require('../../../adapters/utils/networkUtils'); const { httpGET } = require('../../../adapters/network'); const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); -const { AUTH_CACHE_TTL } = require('../../util/constant'); +const { AUTH_CACHE_TTL, JSON_MIME_TYPE } = require('../../util/constant'); const { MAPPING_CONFIG, CONFIG_CATEGORIES } = require('./config'); const customFieldsCache = new Cache(AUTH_CACHE_TTL); @@ -432,7 +432,7 @@ const fetchCustomFields = async (destination) => { return customFieldsCache.get(destination.ID, async () => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }, }; diff --git a/src/v0/destinations/sendinblue/util.js b/src/v0/destinations/sendinblue/util.js index cf47f36d0ef8..b5db737b7b7a 100644 --- a/src/v0/destinations/sendinblue/util.js +++ b/src/v0/destinations/sendinblue/util.js @@ -14,16 +14,17 @@ const { } = require('../../../adapters/utils/networkUtils'); const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const prepareHeader = (apiKey, clientKey = null, trackerApi = false) => { if (trackerApi) { return { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'ma-key': clientKey, }; } return { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, 'api-key': apiKey, }; }; diff --git a/src/v0/destinations/serenytics/transform.js b/src/v0/destinations/serenytics/transform.js index 6b2a73234a45..ee7279e2889d 100644 --- a/src/v0/destinations/serenytics/transform.js +++ b/src/v0/destinations/serenytics/transform.js @@ -58,6 +58,7 @@ const processEvent = (message, destination) => { let STORAGE_URL; let response; let payload; + const CONTEXT_TRAITS_KEY_PATH = 'context.traits'; switch (messageType) { case EventType.TRACK: payload = payloadBuilder( @@ -72,7 +73,7 @@ const processEvent = (message, destination) => { payload = payloadBuilder( message, CONFIG_CATEGORIES.IDENTIFY.name, - ['traits', 'context.traits'], + ['traits', CONTEXT_TRAITS_KEY_PATH], SERENYTICS_IDENTIFY_EXCLUSION_LIST, ); break; @@ -81,7 +82,7 @@ const processEvent = (message, destination) => { payload = payloadBuilder( message, CONFIG_CATEGORIES.GROUP.name, - ['traits', 'context.traits'], + ['traits', CONTEXT_TRAITS_KEY_PATH], [], ); break; @@ -108,7 +109,7 @@ const processEvent = (message, destination) => { payload = payloadBuilder( message, CONFIG_CATEGORIES.ALIAS.name, - ['traits', 'context.traits'], + ['traits', CONTEXT_TRAITS_KEY_PATH], [], ); break; diff --git a/src/v0/destinations/sfmc/transform.js b/src/v0/destinations/sfmc/transform.js index a35955bca5df..ce190c1aaeea 100644 --- a/src/v0/destinations/sfmc/transform.js +++ b/src/v0/destinations/sfmc/transform.js @@ -21,6 +21,9 @@ const { } = require('../../../adapters/utils/networkUtils'); const { NetworkError, ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const CONTACT_KEY_KEY = 'Contact Key'; // DOC: https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/access-token-s2s.htm @@ -34,7 +37,7 @@ const getToken = async (clientId, clientSecret, subdomain) => { client_secret: clientSecret, }, { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }, ); if (resp && resp.data) { @@ -79,7 +82,7 @@ const responseBuilderForIdentifyContacts = (message, subdomain, authToken) => { } response.body.JSON = { attributeSets: [], contactKey }; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${authToken}`, }; return response; @@ -107,7 +110,7 @@ const responseBuilderForInsertData = ( const response = defaultRequestConfig(); response.method = defaultPutRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${authToken}`, }; // multiple primary keys can be set by the user as comma separated. @@ -125,13 +128,13 @@ const responseBuilderForInsertData = ( type === 'identify' || (type === 'track' && primaryKeyArray.length === 1 && - primaryKeyArray.includes('Contact Key') && + primaryKeyArray.includes(CONTACT_KEY_KEY) && !uuid) ) { response.endpoint = `https://${subdomain}.${ENDPOINTS.INSERT_CONTACTS}${externalKey}/rows/Contact Key:${contactKey}`; response.body.JSON = { values: { - 'Contact Key': contactKey, + [CONTACT_KEY_KEY]: contactKey, ...payload, }, }; @@ -151,7 +154,7 @@ const responseBuilderForInsertData = ( primaryKeyArray.forEach((key, index) => { const keyTrimmed = key.trim(); let payloadValue = payload[keyTrimmed]; - if (keyTrimmed === 'Contact Key') { + if (keyTrimmed === CONTACT_KEY_KEY) { // if one of the multiple primary key is "Contact Key" payloadValue = contactKey; } @@ -224,7 +227,7 @@ const responseBuilderSimple = async (message, category, destination) => { category, authToken, 'track', - hashMapPrimaryKey[message.event.toLowerCase()] || 'Contact Key', + hashMapPrimaryKey[message.event.toLowerCase()] || CONTACT_KEY_KEY, hashMapUUID[message.event.toLowerCase()], ); } diff --git a/src/v0/destinations/shynet/transform.js b/src/v0/destinations/shynet/transform.js index 851674005bc5..833616a11ffe 100644 --- a/src/v0/destinations/shynet/transform.js +++ b/src/v0/destinations/shynet/transform.js @@ -8,6 +8,7 @@ const { simpleProcessRouterDest, generateUUID, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const { InstrumentationError } = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig } = require('./config'); @@ -18,7 +19,7 @@ function buildResponse(payload, endpoint) { response.endpoint = endpoint; response.body.JSON = removeUndefinedAndNullValues(payload); response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; } @@ -41,13 +42,10 @@ function process(event) { } const messageType = message.type.toLowerCase(); - - switch (messageType) { - case EventType.PAGE: - return processPage(message, shynetServiceUrl); - default: - throw new InstrumentationError(`Event type "${messageType}" is not supported`); + if (messageType === EventType.PAGE) { + return processPage(message, shynetServiceUrl); } + throw new InstrumentationError(`Event type ${messageType} is not supported`); } const processRouterDest = async (inputs, reqMetadata) => { diff --git a/src/v0/destinations/signl4/transform.js b/src/v0/destinations/signl4/transform.js index 00caaeabafb6..63dc10d73c7c 100644 --- a/src/v0/destinations/signl4/transform.js +++ b/src/v0/destinations/signl4/transform.js @@ -12,13 +12,14 @@ const { TransformationError, InstrumentationError, } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (payload, endpoint) => { if (payload) { const response = defaultRequestConfig(); response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = removeUndefinedAndNullAndEmptyValues(payload); @@ -57,12 +58,10 @@ const processEvent = (message, destination) => { } const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: - response = trackResponseBuilder(message, destination); - break; - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + if (messageType === EventType.TRACK) { + response = trackResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } return response; }; diff --git a/src/v0/destinations/singular/util.js b/src/v0/destinations/singular/util.js index 6de2c846b787..c2a88a9c46e1 100644 --- a/src/v0/destinations/singular/util.js +++ b/src/v0/destinations/singular/util.js @@ -87,14 +87,15 @@ const isSessionEvent = (Config, eventName) => { */ const platformWisePayloadGenerator = (message, sessionEvent) => { let eventAttributes; - let platform = getValueFromMessage(message, 'context.os.name'); + const clonedMessage = { ...message }; + let platform = getValueFromMessage(clonedMessage, 'context.os.name'); const typeOfEvent = sessionEvent ? 'SESSION' : 'EVENT'; if (!platform) { throw new InstrumentationError('Platform name is missing from context.os.name'); } // checking if the os is one of ios, ipados, watchos, tvos if (typeof platform === 'string' && isAppleFamily(platform.toLowerCase())) { - message.context.os.name = 'iOS'; + clonedMessage.context.os.name = 'iOS'; platform = 'iOS'; } platform = platform.toLowerCase(); @@ -103,7 +104,7 @@ const platformWisePayloadGenerator = (message, sessionEvent) => { } const payload = constructPayload( - message, + clonedMessage, MAPPING_CONFIG[CONFIG_CATEGORIES[`${typeOfEvent}_${SUPPORTED_PLATFORM[platform]}`].name], ); @@ -113,21 +114,24 @@ const platformWisePayloadGenerator = (message, sessionEvent) => { if (sessionEvent) { // context.device.adTrackingEnabled = true implies Singular's do not track (dnt) // to be 0 and vice-versa. - const adTrackingEnabled = getValueFromMessage(message, 'context.device.adTrackingEnabled'); + const adTrackingEnabled = getValueFromMessage( + clonedMessage, + 'context.device.adTrackingEnabled', + ); if (adTrackingEnabled === true) { payload.dnt = 0; } else { payload.dnt = 1; } // by default, the value of openuri and install_source should be "", i.e empty string if nothing is passed - payload.openuri = message.properties.url || ''; + payload.openuri = clonedMessage.properties.url || ''; if (platform === 'android' || platform === 'Android') { - payload.install_source = message.properties.referring_application || ''; + payload.install_source = clonedMessage.properties.referring_application || ''; } } else { // Custom Attribues is not supported by session events eventAttributes = extractExtraFields( - message, + clonedMessage, exclusionList[`${SUPPORTED_PLATFORM[platform]}_${typeOfEvent}_EXCLUSION_LIST`], ); eventAttributes = removeUndefinedAndNullValues(eventAttributes); @@ -140,7 +144,7 @@ const platformWisePayloadGenerator = (message, sessionEvent) => { } // Singular maps Connection Type to either wifi or carrier - if (message.context?.network?.wifi) { + if (clonedMessage.context?.network?.wifi) { payload.c = 'wifi'; } else { payload.c = 'carrier'; diff --git a/src/v0/destinations/slack/transform.js b/src/v0/destinations/slack/transform.js index 4c6c5cff27a1..ee58b63dff4c 100644 --- a/src/v0/destinations/slack/transform.js +++ b/src/v0/destinations/slack/transform.js @@ -95,25 +95,7 @@ const processIdentify = (message, destination) => { return buildResponse({ text: resultText }, message, destination); }; -const processTrack = (message, destination) => { - // logger.debug(JSON.stringify(destination)); - const eventChannelConfig = destination.Config.eventChannelSettings; - const eventTemplateConfig = destination.Config.eventTemplateSettings; - - if (!message.event) { - throw new InstrumentationError('Event name is required'); - } - const eventName = message.event; - const channelListToSendThisEvent = new Set(); - const templateListForThisEvent = new Set(); - const traitsList = getWhiteListedTraits(destination); - - // Add global context to regex always - // build the channel list and templatelist for the event, pick the first in case of multiple - // using set to filter out - // document this behaviour - - // building channel list +function buildChannelList(channelListToSendThisEvent, eventChannelConfig, eventName) { eventChannelConfig.forEach((channelConfig) => { const configEventName = channelConfig.eventName ? channelConfig.eventName.trim().length > 0 @@ -145,10 +127,9 @@ const processTrack = (message, destination) => { } } }); +} - const channelListArray = Array.from(channelListToSendThisEvent); - - // building templatelist +function buildtemplateList(templateListForThisEvent, eventTemplateConfig, eventName) { eventTemplateConfig.forEach((templateConfig) => { const configEventName = templateConfig.eventName ? templateConfig.eventName.trim().length > 0 @@ -173,7 +154,32 @@ const processTrack = (message, destination) => { } } }); +} +const processTrack = (message, destination) => { + // logger.debug(JSON.stringify(destination)); + const eventChannelConfig = destination.Config.eventChannelSettings; + const eventTemplateConfig = destination.Config.eventTemplateSettings; + + if (!message.event) { + throw new InstrumentationError('Event name is required'); + } + const eventName = message.event; + const channelListToSendThisEvent = new Set(); + const templateListForThisEvent = new Set(); + const traitsList = getWhiteListedTraits(destination); + + // Add global context to regex always + // build the channel list and templatelist for the event, pick the first in case of multiple + // using set to filter out + // document this behaviour + + // building channel list + buildChannelList(channelListToSendThisEvent, eventChannelConfig, eventName); + const channelListArray = Array.from(channelListToSendThisEvent); + + // building templatelist + buildtemplateList(templateListForThisEvent, eventTemplateConfig, eventName); const templateListArray = Array.from(templateListForThisEvent); logger.debug( diff --git a/src/v0/destinations/snapchat_conversion/transform.js b/src/v0/destinations/snapchat_conversion/transform.js index 94b87b1d1c5e..ca489f546003 100644 --- a/src/v0/destinations/snapchat_conversion/transform.js +++ b/src/v0/destinations/snapchat_conversion/transform.js @@ -1,6 +1,5 @@ const get = require('get-value'); const moment = require('moment'); -const _ = require('lodash'); const { EventType } = require('../../../constants'); const { @@ -34,6 +33,58 @@ const { generateBatchedPayloadForArray, } = require('./util'); const { InstrumentationError, ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +function buildResponse(apiKey, payload) { + const response = defaultRequestConfig(); + response.endpoint = ENDPOINT; + response.headers = { + Authorization: `Bearer ${apiKey}`, + 'Content-Type': JSON_MIME_TYPE, + }; + response.method = defaultPostRequestConfig.requestMethod; + response.body.JSON = removeUndefinedAndNullValues(payload); + return response; +} + +/** + * Seperate out hashing operations into one function + * @param {*} payload + * @param {*} message + * @returns updatedPayload + */ +function populateHashedValues(payload, message) { + const updatedPayload = payload; + const email = getFieldValueFromMessage(message, 'email'); + const phone = getNormalizedPhoneNumber(message); + const ip = message.context?.ip || message.request_ip; + + if (email) { + updatedPayload.hashed_email = getHashedValue(email.toString().toLowerCase().trim()); + } + if (phone) { + updatedPayload.hashed_phone_number = getHashedValue(phone.toString().toLowerCase().trim()); + } + if (ip) { + updatedPayload.hashed_ip_address = getHashedValue(ip.toString().toLowerCase().trim()); + } + // only in case of ios platform this is required + if ( + isAppleFamily(message.context?.device?.type) && + (message.properties?.idfv || message.context?.device?.id) + ) { + updatedPayload.hashed_idfv = getHashedValue( + message.properties?.idfv || message.context?.device?.id, + ); + } + + if (message.properties?.adId || message.context?.device?.advertisingId) { + updatedPayload.hashed_mobile_ad_id = getHashedValue( + message.properties?.adId || message.context?.device?.advertisingId, + ); + } + return updatedPayload; +} // Returns the response for the track event after constructing the payload and setting necessary fields function trackResponseBuilder(message, { Config }, mappedEvent) { @@ -140,35 +191,8 @@ function trackResponseBuilder(message, { Config }, mappedEvent) { throw new InstrumentationError(`Event ${event} doesn't match with Snapchat Events!`); } - if (get(message, 'properties.event_tag')) { - payload.event_tag = message.properties.event_tag; - } - - const email = getFieldValueFromMessage(message, 'email'); - if (email) { - payload.hashed_email = getHashedValue(email.toString().toLowerCase().trim()); - } - const phone = getNormalizedPhoneNumber(message); - if (phone) { - payload.hashed_phone_number = getHashedValue(phone.toString().toLowerCase().trim()); - } - const ip = message.context?.ip || message.request_ip; - if (ip) { - payload.hashed_ip_address = getHashedValue(ip.toString().toLowerCase().trim()); - } - // only in case of ios platform this is required - if ( - isAppleFamily(message.context?.device?.type) && - (message.properties?.idfv || message.context?.device?.id) - ) { - payload.hashed_idfv = getHashedValue(message.properties?.idfv || message.context?.device?.id); - } - - if (message.properties?.adId || message.context?.device?.advertisingId) { - payload.hashed_mobile_ad_id = getHashedValue( - message.properties?.adId || message.context?.device?.advertisingId, - ); - } + payload.event_tag = get(message, 'properties.event_tag'); + payload = populateHashedValues(payload, message); payload.user_agent = message.context?.userAgent?.toString().toLowerCase(); @@ -219,14 +243,7 @@ function trackResponseBuilder(message, { Config }, mappedEvent) { payload = removeUndefinedAndNullValues(payload); // build response - const response = defaultRequestConfig(); - response.endpoint = ENDPOINT; - response.headers = { - Authorization: `Bearer ${apiKey}`, - 'Content-Type': 'application/json', - }; - response.method = defaultPostRequestConfig.requestMethod; - response.body.JSON = removeUndefinedAndNullValues(payload); + const response = buildResponse(apiKey, payload); return response; } @@ -269,22 +286,19 @@ function process(event) { const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: { - const mappedEvents = eventMappingHandler(message, destination); - if (mappedEvents.length > 0) { - response = []; - mappedEvents.forEach((mappedEvent) => { - const res = trackResponseBuilder(message, destination, mappedEvent); - response.push(res); - }); - } else { - response = trackResponseBuilder(message, destination, get(message, 'event')); - } - break; + if (messageType === EventType.TRACK) { + const mappedEvents = eventMappingHandler(message, destination); + if (mappedEvents.length > 0) { + response = []; + mappedEvents.forEach((mappedEvent) => { + const res = trackResponseBuilder(message, destination, mappedEvent); + response.push(res); + }); + } else { + response = trackResponseBuilder(message, destination, get(message, 'event')); } - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } return response; } diff --git a/src/v0/destinations/snapchat_conversion/util.js b/src/v0/destinations/snapchat_conversion/util.js index d39b0253a5d8..ee0329995c17 100644 --- a/src/v0/destinations/snapchat_conversion/util.js +++ b/src/v0/destinations/snapchat_conversion/util.js @@ -8,6 +8,7 @@ const { defaultBatchRequestConfig, } = require('../../util'); const { ENDPOINT } = require('./config'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const channelMapping = { web: 'WEB', @@ -41,10 +42,7 @@ function getNormalizedPhoneNumber(message) { let leadingZero = true; if (phoneNumber) { for (let i = 0; i < phoneNumber.length; i += 1) { - if (Number.isNaN(parseInt(phoneNumber[i], 10))) { - phoneNumber = phoneNumber.replace(phoneNumber[i], ''); - i -= 1; - } else if (phoneNumber[i] === '0' && leadingZero) { + if (Number.isNaN(parseInt(phoneNumber[i], 10)) || (phoneNumber[i] === '0' && leadingZero)) { phoneNumber = phoneNumber.replace(phoneNumber[i], ''); i -= 1; } else { @@ -132,7 +130,7 @@ function generateBatchedPayloadForArray(events, destination) { batchedRequest.endpoint = ENDPOINT; batchedRequest.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }; diff --git a/src/v0/destinations/snapchat_custom_audience/networkHandler.js b/src/v0/destinations/snapchat_custom_audience/networkHandler.js index 9596e955b257..d3461728f809 100644 --- a/src/v0/destinations/snapchat_custom_audience/networkHandler.js +++ b/src/v0/destinations/snapchat_custom_audience/networkHandler.js @@ -38,13 +38,13 @@ const prepareProxyReq = (request) => { * @returns */ const getAuthErrCategory = (code, response) => { - switch (code) { - case 401: - if (!response.error?.details) return REFRESH_TOKEN; - return ''; - default: - return ''; + let authErrCategory; + if (code === 401) { + authErrCategory = !response.error?.details ? REFRESH_TOKEN : ''; + } else { + authErrCategory = ''; } + return authErrCategory; }; const scAudienceProxyRequest = async (request) => { diff --git a/src/v0/destinations/snapchat_custom_audience/transform.js b/src/v0/destinations/snapchat_custom_audience/transform.js index 8d7703375575..1c1611549465 100644 --- a/src/v0/destinations/snapchat_custom_audience/transform.js +++ b/src/v0/destinations/snapchat_custom_audience/transform.js @@ -8,6 +8,7 @@ const { const { ConfigurationError, OAuthSecretError } = require('../../util/errorTypes'); const { BASE_URL, schemaType } = require('./config'); const { validatePayload, validateFields } = require('./utils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * Get access token to be bound to the event req headers @@ -45,7 +46,7 @@ const generateResponse = (groupedData, schema, segmentId, metadata, type) => { const accessToken = getAccessToken(metadata); response.headers = { Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; diff --git a/src/v0/destinations/splitio/transform.js b/src/v0/destinations/splitio/transform.js index 336313361573..ec579e4a4089 100644 --- a/src/v0/destinations/splitio/transform.js +++ b/src/v0/destinations/splitio/transform.js @@ -18,6 +18,7 @@ const { ErrorMessage, } = require('../../util'); const { TransformationError, InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function responseBuilderSimple(payload, category, destination) { if (payload) { @@ -26,7 +27,7 @@ function responseBuilderSimple(payload, category, destination) { response.endpoint = category.endPoint; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${destination.Config.apiKey}`, }; response.body.JSON = removeUndefinedAndNullValues(responseBody); diff --git a/src/v0/destinations/statsig/transform.js b/src/v0/destinations/statsig/transform.js index 500d12ffc1d6..1be72d4095e6 100644 --- a/src/v0/destinations/statsig/transform.js +++ b/src/v0/destinations/statsig/transform.js @@ -2,6 +2,7 @@ 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) { const { message, destination } = event; @@ -29,7 +30,7 @@ function process(event) { response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = message; response.headers = { - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, 'STATSIG-API-KEY': secretKey, }; diff --git a/src/v0/destinations/tiktok_ads/transform.js b/src/v0/destinations/tiktok_ads/transform.js index 77f2f8103fc8..dc18cf58767e 100644 --- a/src/v0/destinations/tiktok_ads/transform.js +++ b/src/v0/destinations/tiktok_ads/transform.js @@ -28,6 +28,10 @@ const { 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'; +const USER_PHONE_NUMBER_KEY_PATH = 'context.user.phone_number'; const getContents = (message) => { const contents = []; @@ -35,15 +39,16 @@ const getContents = (message) => { const { products, content_type, contentType } = properties; if (products && Array.isArray(products) && products.length > 0) { products.forEach((product) => { - const singleProduct = {}; - singleProduct.content_type = - product.contentType || contentType || product.content_type || content_type || 'product'; - singleProduct.content_id = product.product_id; - singleProduct.content_category = product.category; - singleProduct.content_name = product.name; - singleProduct.price = product.price; - singleProduct.quantity = product.quantity; - singleProduct.description = product.description; + const singleProduct = { + content_type: + product.contentType || contentType || product.content_type || content_type || 'product', + content_id: product.product_id, + content_category: product.category, + content_name: product.name, + price: product.price, + quantity: product.quantity, + description: product.description, + }; contents.push(removeUndefinedAndNullValues(singleProduct)); }); } @@ -54,6 +59,7 @@ const checkContentType = (contents, contentType) => { if (Array.isArray(contents)) { contents.forEach((content) => { if (!content.content_type) { + // eslint-disable-next-line no-param-reassign content.content_type = contentType || 'product_group'; } }); @@ -93,14 +99,14 @@ const getTrackResponse = (message, Config, event) => { const traits = getFieldValueFromMessage(message, 'traits'); // taking user properties like email and phone from traits - let email = get(payload, 'context.user.email'); + let email = get(payload, USER_EMAIL_KEY_PATH); if (!isDefinedAndNotNullAndNotEmpty(email) && traits?.email) { - set(payload, 'context.user.email', traits.email); + set(payload, USER_EMAIL_KEY_PATH, traits.email); } - let phone_number = get(payload, 'context.user.phone_number'); + let phone_number = get(payload, USER_PHONE_NUMBER_KEY_PATH); if (!isDefinedAndNotNullAndNotEmpty(phone_number) && traits?.phone) { - set(payload, 'context.user.phone_number', traits.phone); + set(payload, USER_PHONE_NUMBER_KEY_PATH, traits.phone); } payload = { pixel_code, event, ...payload }; @@ -115,12 +121,12 @@ const getTrackResponse = (message, Config, event) => { payload.context.user.external_id = SHA256(external_id.trim()).toString(); } - email = get(payload, 'context.user.email'); + email = get(payload, USER_EMAIL_KEY_PATH); if (isDefinedAndNotNullAndNotEmpty(email)) { payload.context.user.email = SHA256(email.trim().toLowerCase()).toString(); } - phone_number = get(payload, 'context.user.phone_number'); + phone_number = get(payload, USER_PHONE_NUMBER_KEY_PATH); if (isDefinedAndNotNullAndNotEmpty(phone_number)) { payload.context.user.phone_number = SHA256(phone_number.trim()).toString(); } @@ -128,7 +134,7 @@ const getTrackResponse = (message, Config, event) => { const response = defaultRequestConfig(); response.headers = { 'Access-Token': Config.accessToken, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = defaultPostRequestConfig.requestMethod; @@ -192,13 +198,12 @@ const process = async (event) => { const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: - response = await trackResponseBuilder(message, destination); - break; - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + if (messageType === EventType.TRACK) { + response = await trackResponseBuilder(message, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } + return response; }; diff --git a/src/v0/destinations/tiktok_ads_offline_events/transform.js b/src/v0/destinations/tiktok_ads_offline_events/transform.js index 7a6747582a25..0ade5bbfbb88 100644 --- a/src/v0/destinations/tiktok_ads_offline_events/transform.js +++ b/src/v0/destinations/tiktok_ads_offline_events/transform.js @@ -22,6 +22,7 @@ const { PARTNER_NAME, } = require('./config'); const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const getContents = (message) => { const contents = []; @@ -90,7 +91,7 @@ const getTrackResponse = (message, category, Config, event) => { const response = defaultRequestConfig(); response.headers = { 'Access-Token': accessToken, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; response.method = category.method; @@ -141,12 +142,10 @@ const process = (event) => { const messageType = message.type.toLowerCase(); let response; - switch (messageType) { - case EventType.TRACK: - response = trackResponseBuilder(message, CONFIG_CATEGORIES.TRACK, destination); - break; - default: - throw new InstrumentationError(`Event type ${messageType} is not supported`); + if (messageType === EventType.TRACK) { + response = trackResponseBuilder(message, CONFIG_CATEGORIES.TRACK, destination); + } else { + throw new InstrumentationError(`Event type ${messageType} is not supported`); } return response; }; @@ -169,7 +168,7 @@ const createBatch = (events, eventSetId, destination) => { batchedRequest.headers = { 'Access-Token': accessToken, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return batchedRequest; }; diff --git a/src/v0/destinations/trengo/transform.js b/src/v0/destinations/trengo/transform.js index d00fbc935e4f..174db4fe92c2 100644 --- a/src/v0/destinations/trengo/transform.js +++ b/src/v0/destinations/trengo/transform.js @@ -26,6 +26,7 @@ const { } = require('../../util/errorTypes'); const tags = require('../../util/tags'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * @@ -339,8 +340,8 @@ const responseBuilderSimple = async (message, messageType, destination) => { } response.headers = { - 'Content-Type': 'application/json', - Accept: 'application/json', + 'Content-Type': JSON_MIME_TYPE, + Accept: JSON_MIME_TYPE, Authorization: `Bearer ${apiToken}`, }; response.body.JSON = trengoPayload.payload; diff --git a/src/v0/destinations/user/transform.js b/src/v0/destinations/user/transform.js index 66530903c7a7..6cde9c9b8007 100644 --- a/src/v0/destinations/user/transform.js +++ b/src/v0/destinations/user/transform.js @@ -24,13 +24,14 @@ const { } = require('../../util/errorTypes'); const { EventType } = require('../../../constants'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = async (payload, endpoint, method, apiKey) => { if (payload) { const response = defaultRequestConfig(); response.endpoint = endpoint; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, Accept: '*/*;version=2', }; diff --git a/src/v0/destinations/user/utils.js b/src/v0/destinations/user/utils.js index ddc447836404..7f65bf5e5fbb 100644 --- a/src/v0/destinations/user/utils.js +++ b/src/v0/destinations/user/utils.js @@ -20,6 +20,9 @@ const { identifySourceKeys, } = require('./config'); const { InstrumentationError, NetworkInstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const ACCEPT_HEADER_VAL = '*/*;version=2'; /** * Returns updated User.com url @@ -222,9 +225,9 @@ const createCompany = async (message, destination) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -259,9 +262,9 @@ const updateCompany = async (message, destination, company) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -282,9 +285,9 @@ const getUserByUserKey = async (apiKey, userKey, appSubdomain) => { const endpoint = prepareUrl(`${BASE_ENDPOINT}/users/search/?key=${userKey}`, appSubdomain); const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -312,9 +315,9 @@ const getUserByEmail = async (apiKey, email, appSubdomain) => { const endpoint = prepareUrl(`${BASE_ENDPOINT}/users/search/?email=${email}`, appSubdomain); const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -347,9 +350,9 @@ const getUserByPhoneNumber = async (apiKey, phoneNumber, appSubdomain) => { ); const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -388,9 +391,9 @@ const getUserByCustomId = async (message, destination) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; @@ -420,9 +423,9 @@ const getCompanyByCustomId = async (message, destination) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Token ${apiKey}`, - Accept: '*/*;version=2', + Accept: ACCEPT_HEADER_VAL, }, }; diff --git a/src/v0/destinations/userlist/transform.js b/src/v0/destinations/userlist/transform.js index 76986796b16d..20b47c6a3558 100644 --- a/src/v0/destinations/userlist/transform.js +++ b/src/v0/destinations/userlist/transform.js @@ -10,6 +10,7 @@ const { const { endpoint } = require('./config'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); // ------------------------------------------------ // Userlist built a custom endpoint for Rudderstack that processes the messages according to our spec. @@ -34,7 +35,7 @@ function buildResponse(message, destination) { response.endpoint = endpoint; response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Push ${pushKey}`, }; response.body.JSON = message; diff --git a/src/v0/destinations/variance/transform.js b/src/v0/destinations/variance/transform.js index 9d1a397036a6..2c9ed619a8fc 100644 --- a/src/v0/destinations/variance/transform.js +++ b/src/v0/destinations/variance/transform.js @@ -5,6 +5,7 @@ const { defaultRequestConfig, isDefinedAndNotNull, } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); function process(event) { const { message, destination } = event; @@ -18,7 +19,7 @@ function process(event) { response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = message; response.headers = { - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, authorization: authHeader, }; diff --git a/src/v0/destinations/webengage/config.js b/src/v0/destinations/webengage/config.js index b08aafa995ed..1f358b0f2a2d 100644 --- a/src/v0/destinations/webengage/config.js +++ b/src/v0/destinations/webengage/config.js @@ -32,12 +32,11 @@ const WEBENGAGE_IDENTIFY_EXCLUSION = [ 'region', ]; const ENDPOINT = (dataCenter) => { - switch (dataCenter) { - case 'ind': - return 'https://api.in.webengage.com/v1/accounts'; - default: - return 'https://api.webengage.com/v1/accounts'; - } + const endPoint = + dataCenter === 'ind' + ? 'https://api.in.webengage.com/v1/accounts' + : 'https://api.webengage.com/v1/accounts'; + return endPoint; }; const CONFIG_CATEGORIES = { IDENTIFY: { diff --git a/src/v0/destinations/webengage/transform.js b/src/v0/destinations/webengage/transform.js index f7296a2ed3c5..835a486eff54 100644 --- a/src/v0/destinations/webengage/transform.js +++ b/src/v0/destinations/webengage/transform.js @@ -16,6 +16,7 @@ const { extractCustomFields, } = require('../../util'); const { InstrumentationError, TransformationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const responseBuilder = (message, category, { Config }) => { let payload = constructPayload(message, MAPPING_CONFIG[category.name]); @@ -55,7 +56,7 @@ const responseBuilder = (message, category, { Config }) => { const response = defaultRequestConfig(); response.method = defaultPostRequestConfig.requestMethod; response.headers = { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${apiKey}`, }; response.endpoint = endPoint; diff --git a/src/v0/destinations/webhook/transform.js b/src/v0/destinations/webhook/transform.js index 506fd1d7c114..a4a7617f689e 100644 --- a/src/v0/destinations/webhook/transform.js +++ b/src/v0/destinations/webhook/transform.js @@ -18,6 +18,7 @@ const { const { EventType } = require('../../../constants'); const { ConfigurationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const getPropertyParams = (message) => { if (message.type === EventType.IDENTIFY) { @@ -49,7 +50,7 @@ const processEvent = (event) => { response.method = defaultPutRequestConfig.requestMethod; response.body.JSON = message; response.headers = { - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, }; break; } @@ -57,7 +58,7 @@ const processEvent = (event) => { response.method = defaultPatchRequestConfig.requestMethod; response.body.JSON = message; response.headers = { - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, }; break; } @@ -71,7 +72,7 @@ const processEvent = (event) => { response.method = defaultPostRequestConfig.requestMethod; response.body.JSON = message; response.headers = { - 'content-type': 'application/json', + 'content-type': JSON_MIME_TYPE, }; break; } diff --git a/src/v0/destinations/webhook/utils.js b/src/v0/destinations/webhook/utils.js index 0e3fdb399471..b7d166ad7f2d 100644 --- a/src/v0/destinations/webhook/utils.js +++ b/src/v0/destinations/webhook/utils.js @@ -1,13 +1,13 @@ -const { EventType } = require("../../../constants"); -const { getFieldValueFromMessage, flattenJson } = require("../../util"); +const { EventType } = require('../../../constants'); +const { getFieldValueFromMessage, flattenJson } = require('../../util'); -const getPropertyParams = message => { +const getPropertyParams = (message) => { if (message.type === EventType.IDENTIFY) { - return flattenJson(getFieldValueFromMessage(message, "traits")); + return flattenJson(getFieldValueFromMessage(message, 'traits')); } return flattenJson(message.properties); }; module.exports = { - getPropertyParams + getPropertyParams, }; diff --git a/src/v0/destinations/wootric/util.js b/src/v0/destinations/wootric/util.js index ceebb448c46f..8bb3a892ae2d 100644 --- a/src/v0/destinations/wootric/util.js +++ b/src/v0/destinations/wootric/util.js @@ -10,6 +10,7 @@ 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'); const ACCESS_TOKEN_CACHE = new Cache(ACCESS_TOKEN_CACHE_TTL_SECONDS); @@ -32,7 +33,7 @@ const getAccessToken = async (destination) => { const request = { header: { 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }, url: `${BASE_ENDPOINT}/oauth/token?account_token=${accountToken}`, data: qs.stringify({ @@ -86,7 +87,7 @@ const retrieveUserDetails = async (endUserId, externalId, accessToken) => { const requestOptions = { headers: { - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, Authorization: `Bearer ${accessToken}`, }, }; diff --git a/src/v0/destinations/yahoo_dsp/transform.js b/src/v0/destinations/yahoo_dsp/transform.js index 71fe32faed96..8b0875f1a079 100644 --- a/src/v0/destinations/yahoo_dsp/transform.js +++ b/src/v0/destinations/yahoo_dsp/transform.js @@ -13,6 +13,7 @@ const { const { getAccessToken, createPayload } = require('./util'); const { InstrumentationError } = require('../../util/errorTypes'); +const { JSON_MIME_TYPE } = require('../../util/constant'); /** * This function is used for building the final response to be returned. @@ -75,7 +76,7 @@ const responseBuilder = async (message, destination) => { response.headers = { 'X-Auth-Token': accessToken, 'X-Auth-Method': 'OAuth2', - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; return response; }; diff --git a/src/v0/destinations/yahoo_dsp/util.js b/src/v0/destinations/yahoo_dsp/util.js index 38eb2a8d91c2..fa182ffaafe1 100644 --- a/src/v0/destinations/yahoo_dsp/util.js +++ b/src/v0/destinations/yahoo_dsp/util.js @@ -8,6 +8,7 @@ const { ACCESS_TOKEN_CACHE_TTL, AUDIENCE_ATTRIBUTE, DSP_SUPPORTED_OPERATION } = const Cache = require('../../util/cache'); const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); const ACCESS_TOKEN_CACHE = new Cache(ACCESS_TOKEN_CACHE_TTL); @@ -120,7 +121,7 @@ const getAccessToken = async (destination) => { const request = { header: { 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', + Accept: JSON_MIME_TYPE, }, url: 'https://id.b2b.yahooinc.com/identity/oauth2/access_token', data: qs.stringify({ diff --git a/src/v0/destinations/zendesk/transform.js b/src/v0/destinations/zendesk/transform.js index e394ee304b3e..1f10f394b9b2 100644 --- a/src/v0/destinations/zendesk/transform.js +++ b/src/v0/destinations/zendesk/transform.js @@ -32,6 +32,9 @@ const { } = require('../../util/errorTypes'); const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +const CONTEXT_TRAITS_KEY_PATH = 'context.traits'; function responseBuilder(message, headers, payload, endpoint) { const response = defaultRequestConfig(); @@ -187,7 +190,9 @@ function getIdentifyPayload(message, category, destinationConfig, type) { const mappingJson = mappingConfig[category.name]; const traits = - type === 'group' ? get(message, 'context.traits') : getFieldValueFromMessage(message, 'traits'); + type === 'group' + ? get(message, CONTEXT_TRAITS_KEY_PATH) + : getFieldValueFromMessage(message, 'traits'); const payload = constructPayload(traits, mappingJson); if (!payload.user) { @@ -248,7 +253,9 @@ const getUserIdByExternalId = async (message, headers, baseEndpoint) => { async function getUserId(message, headers, baseEndpoint, type) { const traits = - type === 'group' ? get(message, 'context.traits') : getFieldValueFromMessage(message, 'traits'); + type === 'group' + ? get(message, CONTEXT_TRAITS_KEY_PATH) + : getFieldValueFromMessage(message, 'traits'); const userEmail = traits?.email || traits?.primaryEmail; if (!userEmail) { logger.debug(`${NAME}:: Email ID is required for getting zenuserId`); @@ -292,7 +299,9 @@ async function isUserAlreadyAssociated(userId, orgId, headers, baseEndpoint) { async function createUser(message, headers, destinationConfig, baseEndpoint, type) { const traits = - type === 'group' ? get(message, 'context.traits') : getFieldValueFromMessage(message, 'traits'); + type === 'group' + ? get(message, CONTEXT_TRAITS_KEY_PATH) + : getFieldValueFromMessage(message, 'traits'); const { name, email } = traits; const userId = getFieldValueFromMessage(message, 'userId'); @@ -326,7 +335,7 @@ async function createUser(message, headers, destinationConfig, baseEndpoint, typ async function getUserMembershipPayload(message, headers, orgId, destinationConfig, baseEndpoint) { // let zendeskUserID = await getUserId(message.userId, headers); let zendeskUserID = await getUserId(message, headers, baseEndpoint, 'group'); - const traits = get(message, 'context.traits'); + const traits = get(message, CONTEXT_TRAITS_KEY_PATH); if (!zendeskUserID) { if (traits && traits.name && traits.email) { const { zendeskUserId } = await createUser( @@ -522,16 +531,18 @@ async function processTrack(message, destinationConfig, headers, baseEndpoint) { ); } - const eventObject = {}; - eventObject.description = message.event; - eventObject.type = message.event; - eventObject.source = 'Rudder'; - eventObject.properties = message.properties; + const eventObject = { + description: message.event, + type: message.event, + source: 'Rudder', + properties: message.properties, + }; - const profileObject = {}; - profileObject.type = message.event; - profileObject.source = 'Rudder'; - profileObject.identifiers = [{ type: 'email', value: userEmail }]; + const profileObject = { + type: message.event, + source: 'Rudder', + identifiers: [{ type: 'email', value: userEmail }], + }; const eventPayload = { event: eventObject, profile: profileObject }; const eventEndpoint = `${baseEndpoint}users/${zendeskUserID}/events`; @@ -597,7 +608,7 @@ async function processSingleMessage(event) { const baseEndpoint = getBaseEndpoint(destinationConfig.domain); const headers = { Authorization: `Basic ${Buffer.from(unencodedBase64Str).toString('base64')}`, - 'Content-Type': 'application/json', + 'Content-Type': JSON_MIME_TYPE, }; const { message } = event; diff --git a/src/v0/sources/appcenter/transform.js b/src/v0/sources/appcenter/transform.js index 5296ac96002b..c109517901f3 100644 --- a/src/v0/sources/appcenter/transform.js +++ b/src/v0/sources/appcenter/transform.js @@ -7,6 +7,7 @@ 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 guidGenerator = () => { const S4 = () => @@ -56,7 +57,7 @@ const isTestEvent = (event) => !!event?.text; const processTestEvent = (event) => ({ outputToSource: { body: Buffer.from(JSON.stringify(event)).toString('base64'), - contentType: 'application/json', + contentType: JSON_MIME_TYPE, }, statusCode: 200, }); diff --git a/src/v0/sources/canny/transform.js b/src/v0/sources/canny/transform.js index 2a019fe097bf..abc6f491b8d0 100644 --- a/src/v0/sources/canny/transform.js +++ b/src/v0/sources/canny/transform.js @@ -16,17 +16,18 @@ const CannyOperation = { * @param {*} typeOfUser */ function settingIds(message, event, typeOfUser) { + const clonedMessage = { ...message }; try { // setting up userId if (event.object[`${typeOfUser}`]?.userID) { - message.userId = event.object[`${typeOfUser}`].userID; + clonedMessage.userId = event.object[`${typeOfUser}`].userID; } else { // setting up anonymousId if userId is not present - message.anonymousId = sha256(event.object[`${typeOfUser}`]?.email); + clonedMessage.anonymousId = sha256(event.object[`${typeOfUser}`]?.email); } if (event.object[`${typeOfUser}`]?.id) { - message.context.externalId = [ + clonedMessage.context.externalId = [ { type: 'cannyUserId', id: event.object[`${typeOfUser}`].id, @@ -37,6 +38,8 @@ function settingIds(message, event, typeOfUser) { logger?.error(`Missing essential fields from Canny. Error: (${e})`); throw new TransformationError(`Missing essential fields from Canny. Error: (${e})`); } + + return clonedMessage; } /** @@ -58,16 +61,16 @@ function createMessage(event, typeOfUser) { message.context.integration.version = '1.0.0'; - settingIds(message, event, typeOfUser); + const finalMessage = settingIds(message, event, typeOfUser); - checkForRequiredFields(message); + checkForRequiredFields(finalMessage); // deleting already mapped fields - delete message.properties[`${typeOfUser}`]; - delete message.context.traits?.userID; - delete message.context.traits?.id; + delete finalMessage.properties[`${typeOfUser}`]; + delete finalMessage.context.traits?.userID; + delete finalMessage.context.traits?.id; - return message; + return finalMessage; } function process(event) { diff --git a/src/v0/sources/mailmodo/transform.js b/src/v0/sources/mailmodo/transform.js index 43da4c7f4af5..8b36eafa1aaa 100644 --- a/src/v0/sources/mailmodo/transform.js +++ b/src/v0/sources/mailmodo/transform.js @@ -9,6 +9,7 @@ const { TransformationError } = require('../../util/errorTypes'); const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); function settingProperties(event, message) { + const cloneMessage = { ...message }; const flatEvent = event; // deleting object fields(already mapped) before flattening the event @@ -18,7 +19,7 @@ function settingProperties(event, message) { delete flatEvent?.triggerData?.formSubmissionData?.recipientData; // flattening the event and assigning it to properties - message.properties = removeUndefinedAndNullAndEmptyValues(flattenJson(flatEvent)); + cloneMessage.properties = removeUndefinedAndNullAndEmptyValues(flattenJson(flatEvent)); // fields that are already mapped const excludeFields = [ @@ -32,8 +33,10 @@ function settingProperties(event, message) { // deleting already mapped fields excludeFields.forEach((excludeField) => { - delete message?.properties[excludeField]; + delete cloneMessage?.properties[excludeField]; }); + + return cloneMessage; } function process(event) { @@ -83,9 +86,9 @@ function process(event) { ).toISOString(); } - settingProperties(event, message); + const finalMessage = settingProperties(event, message); - return message; + return finalMessage; } module.exports = { process }; diff --git a/src/v0/sources/moengage/transform.js b/src/v0/sources/moengage/transform.js index 280a745fd11d..e5b3c92bfea1 100644 --- a/src/v0/sources/moengage/transform.js +++ b/src/v0/sources/moengage/transform.js @@ -5,4 +5,4 @@ function process(events) { return events; } -exports.process = process; \ No newline at end of file +exports.process = process; diff --git a/src/v0/sources/monday/transform.js b/src/v0/sources/monday/transform.js index eaaeb94698e4..48cddec30143 100644 --- a/src/v0/sources/monday/transform.js +++ b/src/v0/sources/monday/transform.js @@ -3,6 +3,7 @@ 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'); function processNormalEvent(mondayPayload) { const message = new Message(`MONDAY`); @@ -49,7 +50,7 @@ function processChallengeEvent(event) { return { outputToSource: { body: Buffer.from(JSON.stringify(event)).toString('base64'), - contentType: 'application/json', + contentType: JSON_MIME_TYPE, }, statusCode: 200, }; diff --git a/src/v0/sources/shopify/config.js b/src/v0/sources/shopify/config.js index 631f0f3f0567..23fc562f0ecc 100644 --- a/src/v0/sources/shopify/config.js +++ b/src/v0/sources/shopify/config.js @@ -102,7 +102,7 @@ const SUPPORTED_TRACK_EVENTS = [ 'orders_paid', 'orders_partially_fullfilled', ]; -const timeDifferenceForCartEvents = 10000; // in micro seconds as we will be compairing it in timestamp +const timeDifferenceForCartEvents = 10000; // in micro seconds as we will be compairing it in timestamp const useRedisDatabase = process.env.USE_REDIS_DB === 'true' || false; module.exports = { ECOM_TOPICS, diff --git a/src/v0/sources/shopify/transform.js b/src/v0/sources/shopify/transform.js index 37a379f5b6fc..44e4519ff966 100644 --- a/src/v0/sources/shopify/transform.js +++ b/src/v0/sources/shopify/transform.js @@ -169,12 +169,7 @@ const processEvent = async (inputEvent, metricMetadata) => { message = removeUndefinedAndNullValues(message); return message; }; -const isIdentifierEvent = (event) => { - if (event?.event === 'rudderIdentifier') { - return true; - } - return false; -}; +const isIdentifierEvent = (event) => event?.event === 'rudderIdentifier'; const processIdentifierEvent = async (event, metricMetadata) => { if (useRedisDatabase) { const setStartTime = Date.now(); @@ -199,8 +194,8 @@ const processIdentifierEvent = async (event, metricMetadata) => { const process = async (event) => { const metricMetadata = { writeKey: event.query_parameters?.writeKey?.[0], - source: "SHOPIFY" - } + source: 'SHOPIFY', + }; if (isIdentifierEvent(event)) { return processIdentifierEvent(event, metricMetadata); } diff --git a/src/v0/sources/shopify/util.js b/src/v0/sources/shopify/util.js index efcde5b33827..57cfb8856b37 100644 --- a/src/v0/sources/shopify/util.js +++ b/src/v0/sources/shopify/util.js @@ -1,7 +1,13 @@ /* eslint-disable camelcase */ const sha256 = require('sha256'); const stats = require('../../../util/stats'); -const { constructPayload, extractCustomFields, flattenJson, generateUUID, isDefinedAndNotNull } = require('../../util'); +const { + constructPayload, + extractCustomFields, + flattenJson, + generateUUID, + isDefinedAndNotNull, +} = require('../../util'); const { RedisDB } = require('../../../util/redisConnector'); const logger = require('../../../logger'); const { @@ -10,7 +16,7 @@ const { LINE_ITEM_EXCLUSION_FIELDS, PRODUCT_MAPPING_EXCLUSION_FIELDS, RUDDER_ECOM_MAP, - SHOPIFY_TRACK_MAP + SHOPIFY_TRACK_MAP, } = require('./config'); // 30 mins const { TransformationError } = require('../../util/errorTypes'); @@ -161,9 +167,9 @@ const setAnonymousIdorUserIdFromDb = async (message, metricMetadata) => { ...metricMetadata, event, timestamp: Date.now(), - }) + }); if (!userId) { - message.setProperty('userId', "shopify-admin"); + message.setProperty('userId', 'shopify-admin'); } return; } @@ -187,7 +193,7 @@ const setAnonymousIdorUserIdFromDb = async (message, metricMetadata) => { ...metricMetadata, event, timestamp: Date.now(), - }) + }); anonymousIDfromDB = sha256(cartToken).toString().substring(0, 36); } message.setProperty('anonymousId', anonymousIDfromDB); diff --git a/src/v0/sources/signl4/transform.js b/src/v0/sources/signl4/transform.js index a2eb98528736..f569786099aa 100644 --- a/src/v0/sources/signl4/transform.js +++ b/src/v0/sources/signl4/transform.js @@ -2,6 +2,7 @@ const path = require('path'); const fs = require('fs'); const { flattenJson, removeUndefinedAndNullValues, generateUUID } = require('../../util'); const Message = require('../message'); +const { JSON_MIME_TYPE } = require('../../util/constant'); // import mapping json using JSON.parse to preserve object key order const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); @@ -31,7 +32,7 @@ function process(event) { return { outputToSource: { body: Buffer.from(JSON.stringify(event)).toString('base64'), - contentType: 'application/json', + contentType: JSON_MIME_TYPE, }, statusCode: 200, }; diff --git a/src/v0/util/constant.js b/src/v0/util/constant.js index ab5b50525aff..8ea1adde9414 100644 --- a/src/v0/util/constant.js +++ b/src/v0/util/constant.js @@ -8,8 +8,11 @@ const AUTH_CACHE_TTL = process.env.MARKETO_AUTH_CACHE_TTL const API_CALL = 'api_call_count'; +const JSON_MIME_TYPE = 'application/json'; + module.exports = { API_CALL, AUTH_CACHE_TTL, USER_LEAD_CACHE_TTL, + JSON_MIME_TYPE, }; diff --git a/src/v0/util/errorTypes/index.js b/src/v0/util/errorTypes/index.js index 08f0ddfbcea0..01708caa15c7 100644 --- a/src/v0/util/errorTypes/index.js +++ b/src/v0/util/errorTypes/index.js @@ -31,5 +31,5 @@ module.exports = { UnauthorizedError, NetworkInstrumentationError, UnsupportedEventError, - RedisError + RedisError, }; diff --git a/src/v0/util/errorTypes/redisError.js b/src/v0/util/errorTypes/redisError.js index 1c9a5bc75aa1..ec3d49ff2b5e 100644 --- a/src/v0/util/errorTypes/redisError.js +++ b/src/v0/util/errorTypes/redisError.js @@ -2,14 +2,14 @@ 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, - }; + 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); - } + super(message, statusCode || 500, finalStatTags); + } } module.exports = RedisError; diff --git a/src/v0/util/index.js b/src/v0/util/index.js index 16259b0ce166..44b6eec9719b 100644 --- a/src/v0/util/index.js +++ b/src/v0/util/index.js @@ -575,6 +575,234 @@ const getFieldValueFromMessage = (message, sourceKey) => { return null; }; +function checkTimestamp(validateTimestamp, formattedVal) { + const { + allowedPastTimeDifference, + allowedPastTimeUnit, // seconds, minutes, hours + allowedFutureTimeDifference, + allowedFutureTimeUnit, // seconds, minutes, hours + } = validateTimestamp; + + let pastTimeDifference; + let futureTimeDifference; + + const currentTime = moment.unix(moment().format('X')); + const time = moment.unix(moment(formattedVal).format('X')); + + switch (allowedPastTimeUnit) { + case 'seconds': + pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asSeconds()); + break; + case 'minutes': + pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asMinutes()); + break; + case 'hours': + pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asHours()); + break; + default: + break; + } + + if (pastTimeDifference > allowedPastTimeDifference) { + throw new InstrumentationError( + `Allowed timestamp is [${allowedPastTimeDifference} ${allowedPastTimeUnit}] into the past`, + ); + } + + if (pastTimeDifference <= 0) { + switch (allowedFutureTimeUnit) { + case 'seconds': + futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asSeconds()); + break; + case 'minutes': + futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asMinutes()); + break; + case 'hours': + futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asHours()); + break; + default: + break; + } + + if (futureTimeDifference > allowedFutureTimeDifference) { + throw new InstrumentationError( + `Allowed timestamp is [${allowedFutureTimeDifference} ${allowedFutureTimeUnit}] into the future`, + ); + } + } +} + +// handle type and format +function formatValues(formattedVal, formattingType, typeFormat, integrationsObj) { + let curFormattedVal = formattedVal; + switch (formattingType) { + case 'timestamp': + curFormattedVal = formatTimeStamp(formattedVal, typeFormat); + break; + case 'secondTimestamp': + if (!moment(formattedVal, 'x', true).isValid()) { + curFormattedVal = Math.floor(formatTimeStamp(formattedVal, typeFormat) / 1000); + } + break; + case 'microSecondTimestamp': + curFormattedVal = moment.unix(moment(formattedVal).format('X')); + curFormattedVal = + curFormattedVal.toDate().getTime() * 1000 + curFormattedVal.toDate().getMilliseconds(); + break; + case 'flatJson': + curFormattedVal = flattenJson(formattedVal); + break; + case 'encodeURIComponent': + curFormattedVal = encodeURIComponent(JSON.stringify(formattedVal)); + break; + case 'jsonStringify': + curFormattedVal = JSON.stringify(formattedVal); + break; + case 'jsonStringifyOnFlatten': + curFormattedVal = JSON.stringify(flattenJson(formattedVal)); + break; + case 'dobInMMDD': + curFormattedVal = String(formattedVal).slice(5); + curFormattedVal = curFormattedVal.replace('-', '/'); + break; + case 'jsonStringifyOnObject': + // if already a string, will not stringify + // calling stringify on string will add escape characters + if (typeof formattedVal !== 'string') { + curFormattedVal = JSON.stringify(formattedVal); + } + break; + case 'numberForRevenue': + if ( + (typeof formattedVal === 'string' || formattedVal instanceof String) && + formattedVal.charAt(0) === '$' + ) { + curFormattedVal = formattedVal.substring(1); + } + curFormattedVal = Number.parseFloat(Number(curFormattedVal || 0).toFixed(2)); + if (Number.isNaN(curFormattedVal)) { + throw new InstrumentationError('Revenue is not in the correct format'); + } + break; + case 'toString': + curFormattedVal = String(formattedVal); + break; + case 'toNumber': + curFormattedVal = Number(formattedVal); + break; + case 'toFloat': + curFormattedVal = parseFloat(formattedVal); + break; + case 'toInt': + curFormattedVal = parseInt(formattedVal, 10); + break; + case 'toLower': + curFormattedVal = formattedVal.toString().toLowerCase(); + break; + case 'hashToSha256': + curFormattedVal = + integrationsObj && integrationsObj.hashed + ? String(formattedVal) + : hashToSha256(String(formattedVal)); + break; + case 'getFbGenderVal': + curFormattedVal = getFbGenderVal(formattedVal); + break; + case 'getOffsetInSec': + curFormattedVal = getOffsetInSec(formattedVal); + break; + case 'domainUrl': + curFormattedVal = formattedVal.replace('https://', '').replace('http://', ''); + break; + case 'domainUrlV2': { + const url = isValidUrl(formattedVal); + if (!url) { + throw new InstrumentationError(`Invalid URL: ${formattedVal}`); + } + curFormattedVal = url.hostname.replace('www.', ''); + break; + } + case 'IsBoolean': + if (!(typeof formattedVal === 'boolean')) { + logger.debug('Boolean value missing, so dropping it'); + } + break; + case 'trim': + if (typeof formattedVal === 'string') { + curFormattedVal = formattedVal.trim(); + } + break; + default: + break; + } + return curFormattedVal; +} + +function handleExcludes(value, excludes, formattedVal) { + if (typeof value === 'object') { + // exclude the fields from the formattedVal + excludes.forEach((key) => { + // eslint-disable-next-line no-param-reassign + delete formattedVal[key]; + }); + } else { + logger.warn("excludes doesn't work with non-object data type. Ignoring excludes"); + } +} + +function handleTemplate(template, value) { + const hTemplate = Handlebars.compile(template.trim()); + const formattedVal = hTemplate({ value }).trim(); + return formattedVal; +} + +function handleMultikeyMap(multikeyMap, strictMultiMap, formattedVal, destKey) { + // sourceVal is expected to be an array + // if value is present in sourceVal, returns the destVal + // else returns the original value + // Expected multikeyMap value: + // "multikeyMap": [ + // { + // "sourceVal": ["m", "M", "Male", "male"], + // "destVal": "M" + // }, + // { + // "sourceVal": ["f", "F", "Female", "female"], + // "destVal": "F" + // } + // ] + let curFormattedVal = formattedVal; + const finalKeyMap = multikeyMap || strictMultiMap; + let foundVal = false; + if (Array.isArray(finalKeyMap)) { + finalKeyMap.some((map) => { + if (!map.sourceVal || !isDefinedAndNotNull(map.destVal) || !Array.isArray(map.sourceVal)) { + logger.warn('multikeyMap skipped: sourceVal and destVal must be of valid type'); + foundVal = true; + return true; + } + + if (map.sourceVal.includes(formattedVal)) { + curFormattedVal = map.destVal; + foundVal = true; + return true; + } + + return false; + }); + } else { + logger.warn('multikeyMap skipped: multikeyMap must be an array'); + } + if (!foundVal) { + if (strictMultiMap) { + throw new InstrumentationError(`Invalid entry for key ${destKey}`); + } else { + curFormattedVal = undefined; + } + } + return curFormattedVal; +} + // format the value as per the metadata values // Expected metadata keys are: (according to precedence) // - - type, typeFormat: expected data type and its format @@ -586,7 +814,7 @@ const handleMetadataForValue = (value, metadata, destKey, integrationsObj = null return value; } - // get infor from metadata + // get information from metadata const { type, typeFormat, @@ -610,237 +838,32 @@ const handleMetadataForValue = (value, metadata, destKey, integrationsObj = null * validate allowed time difference */ if (validateTimestamp) { - const { - allowedPastTimeDifference, - allowedPastTimeUnit, // seconds, minutes, hours - allowedFutureTimeDifference, - allowedFutureTimeUnit, // seconds, minutes, hours - } = validateTimestamp; - - let pastTimeDifference; - let futureTimeDifference; - - const currentTime = moment.unix(moment().format('X')); - const time = moment.unix(moment(formattedVal).format('X')); - - switch (allowedPastTimeUnit) { - case 'seconds': - pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asSeconds()); - break; - case 'minutes': - pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asMinutes()); - break; - case 'hours': - pastTimeDifference = Math.ceil(moment.duration(currentTime.diff(time)).asHours()); - break; - default: - break; - } - - if (pastTimeDifference > allowedPastTimeDifference) { - throw new InstrumentationError( - `Allowed timestamp is [${allowedPastTimeDifference} ${allowedPastTimeUnit}] into the past`, - ); - } - - if (pastTimeDifference <= 0) { - switch (allowedFutureTimeUnit) { - case 'seconds': - futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asSeconds()); - break; - case 'minutes': - futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asMinutes()); - break; - case 'hours': - futureTimeDifference = Math.ceil(moment.duration(time.diff(currentTime)).asHours()); - break; - default: - break; - } - - if (futureTimeDifference > allowedFutureTimeDifference) { - throw new InstrumentationError( - `Allowed timestamp is [${allowedFutureTimeDifference} ${allowedFutureTimeUnit}] into the future`, - ); - } - } + checkTimestamp(validateTimestamp, formattedVal); } - // handle type and format - function formatValues(formatingType) { - switch (formatingType) { - case 'timestamp': - formattedVal = formatTimeStamp(formattedVal, typeFormat); - break; - case 'secondTimestamp': - if (!moment(formattedVal, 'x', true).isValid()) { - formattedVal = Math.floor(formatTimeStamp(formattedVal, typeFormat) / 1000); - } - break; - case 'microSecondTimestamp': - formattedVal = moment.unix(moment(formattedVal).format('X')); - formattedVal = - formattedVal.toDate().getTime() * 1000 + formattedVal.toDate().getMilliseconds(); - break; - case 'flatJson': - formattedVal = flattenJson(formattedVal); - break; - case 'encodeURIComponent': - formattedVal = encodeURIComponent(JSON.stringify(formattedVal)); - break; - case 'jsonStringify': - formattedVal = JSON.stringify(formattedVal); - break; - case 'jsonStringifyOnFlatten': - formattedVal = JSON.stringify(flattenJson(formattedVal)); - break; - case 'dobInMMDD': - formattedVal = String(formattedVal).slice(5); - formattedVal = formattedVal.replace('-', '/'); - break; - case 'jsonStringifyOnObject': - // if already a string, will not stringify - // calling stringify on string will add escape characters - if (typeof formattedVal !== 'string') { - formattedVal = JSON.stringify(formattedVal); - } - break; - case 'numberForRevenue': - if ( - (typeof formattedVal === 'string' || formattedVal instanceof String) && - formattedVal.charAt(0) === '$' - ) { - formattedVal = formattedVal.substring(1); - } - formattedVal = Number.parseFloat(Number(formattedVal || 0).toFixed(2)); - if (Number.isNaN(formattedVal)) { - throw new InstrumentationError('Revenue is not in the correct format'); - } - break; - case 'toString': - formattedVal = String(formattedVal); - break; - case 'toNumber': - formattedVal = Number(formattedVal); - break; - case 'toFloat': - formattedVal = parseFloat(formattedVal); - break; - case 'toInt': - formattedVal = parseInt(formattedVal, 10); - break; - case 'toLower': - formattedVal = formattedVal.toString().toLowerCase(); - break; - case 'hashToSha256': - formattedVal = - integrationsObj && integrationsObj.hashed - ? String(formattedVal) - : hashToSha256(String(formattedVal)); - break; - case 'getFbGenderVal': - formattedVal = getFbGenderVal(formattedVal); - break; - case 'getOffsetInSec': - formattedVal = getOffsetInSec(formattedVal); - break; - case 'domainUrl': - formattedVal = formattedVal.replace('https://', '').replace('http://', ''); - break; - case 'domainUrlV2': { - const url = isValidUrl(formattedVal); - if (!url) { - throw new InstrumentationError(`Invalid URL: ${formattedVal}`); - } - formattedVal = url.hostname.replace('www.', ''); - break; - } - case 'IsBoolean': - if (!(typeof formattedVal === 'boolean')) { - logger.debug('Boolean value missing, so dropping it'); - } - break; - case 'trim': - if (typeof formattedVal === 'string') { - formattedVal = formattedVal.trim(); - } - break; - default: - break; - } - } if (type) { if (Array.isArray(type)) { type.forEach((eachType) => { - formatValues(eachType); + formattedVal = formatValues(formattedVal, eachType, typeFormat, integrationsObj); }); } else { - formatValues(type); + formattedVal = formatValues(formattedVal, type, typeFormat, integrationsObj); } } // handle template if (template) { - const hTemplate = Handlebars.compile(template.trim()); - formattedVal = hTemplate({ value }).trim(); + formattedVal = handleTemplate(template, value); } // handle excludes if (excludes) { - if (typeof value === 'object') { - // exlude the fields from the formattedVal - excludes.forEach((key) => { - delete formattedVal[key]; - }); - } else { - logger.warn("exludes doesn't work with non-object data type. Ignoring exludes"); - } + handleExcludes(value, excludes, formattedVal); } // handle multikeyMap - // sourceVal is expected to be an array - // if value is present in sourceVal, returns the destVal - // else returns the original value - // Expected multikeyMap value: - // "multikeyMap": [ - // { - // "sourceVal": ["m", "M", "Male", "male"], - // "destVal": "M" - // }, - // { - // "sourceVal": ["f", "F", "Female", "female"], - // "destVal": "F" - // } - // ] if (multikeyMap || strictMultiMap) { - const finalKeyMap = multikeyMap || strictMultiMap; - let foundVal = false; - if (Array.isArray(finalKeyMap)) { - finalKeyMap.some((map) => { - if (!map.sourceVal || !isDefinedAndNotNull(map.destVal) || !Array.isArray(map.sourceVal)) { - logger.warn('multikeyMap skipped: sourceVal and destVal must be of valid type'); - foundVal = true; - return true; - } - - if (map.sourceVal.includes(formattedVal)) { - formattedVal = map.destVal; - foundVal = true; - return true; - } - - return false; - }); - } else { - logger.warn('multikeyMap skipped: multikeyMap must be an array'); - } - if (!foundVal) { - if (strictMultiMap) { - throw new InstrumentationError(`Invalid entry for key ${destKey}`); - } else { - formattedVal = undefined; - } - } + formattedVal = handleMultikeyMap(multikeyMap, strictMultiMap, formattedVal, destKey); } if (allowedKeyCheck) { @@ -1218,9 +1241,11 @@ function deleteObjectProperty(object, pathToObject) { return; } if (typeof pathToObject === 'string') { + // eslint-disable-next-line no-param-reassign pathToObject = pathToObject.split('.'); } for (i = 0; i < pathToObject.length - 1; i += 1) { + // eslint-disable-next-line no-param-reassign object = object[pathToObject[i]]; if (typeof object === 'undefined') { @@ -1228,6 +1253,7 @@ function deleteObjectProperty(object, pathToObject) { } } + // eslint-disable-next-line no-param-reassign delete object[pathToObject.pop()]; } @@ -1301,6 +1327,7 @@ function addExternalIdToTraits(message) { const adduserIdFromExternalId = (message) => { const externalId = get(message, 'context.externalId.0.id'); if (externalId) { + // eslint-disable-next-line no-param-reassign message.userId = externalId; } }; @@ -1577,12 +1604,12 @@ const simpleProcessRouterDest = async (inputs, singleTfFunc, reqMetadata, proces }; /** * This is the sync version of simpleProcessRouterDest - * - * @param {*} inputs - * @param {*} singleTfFunc - * @param {*} reqMetadata - * @param {*} processParams - * @returns + * + * @param {*} inputs + * @param {*} singleTfFunc + * @param {*} reqMetadata + * @param {*} processParams + * @returns */ const simpleProcessRouterDestSync = async (inputs, singleTfFunc, reqMetadata, processParams) => { const errorRespEvents = checkInvalidRtTfEvents(inputs); diff --git a/src/v0/util/tags.js b/src/v0/util/tags.js index a59721b9ff32..95e78825c391 100644 --- a/src/v0/util/tags.js +++ b/src/v0/util/tags.js @@ -50,7 +50,7 @@ const ERROR_TYPES = { ABORTED: 'aborted', OAUTH_SECRET: 'oAuthSecret', UNSUPPORTED: 'unsupported', - REDIS:'redis', + REDIS: 'redis', }; const METADATA = { diff --git a/src/versionedRouter.js b/src/versionedRouter.js index 8e4067335734..b286da38e6c1 100644 --- a/src/versionedRouter.js +++ b/src/versionedRouter.js @@ -53,6 +53,8 @@ const NS_PER_SEC = 1e9; const router = new Router(); +const PAYLOAD_PROC_ERR_MSG = 'Error occurred while processing payload'; + // Router for assistance in profiling router.use(profilingRouter); @@ -510,6 +512,7 @@ async function routerHandleDest(ctx) { respEvents .filter((resp) => 'error' in resp && _.isObject(resp.statTags) && !_.isEmpty(resp.statTags)) .forEach((resp) => { + // eslint-disable-next-line no-param-reassign resp.statTags = { ...resp.statTags, ...defTags, @@ -633,6 +636,7 @@ if (startDestTransformer) { } }); + // eslint-disable-next-line sonarjs/cognitive-complexity router.post('/customTransform', async (ctx) => { const startTime = new Date(); const events = ctx.request.body; @@ -912,8 +916,8 @@ async function handleSource(ctx, version, source) { // }; const resp = { - statusCode: error.status || 400, - error: error.message || 'Error occurred while processing payload.', + statusCode: 400, + error: error.message || PAYLOAD_PROC_ERR_MSG, }; respList.push(resp); @@ -1077,7 +1081,7 @@ router.get('/health', (ctx) => { }); router.get('/features', (ctx) => { - const obj = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../features.json'), 'utf8')); + const obj = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'features.json'), 'utf8')); ctx.body = JSON.stringify(obj); }); @@ -1108,9 +1112,9 @@ const batchHandler = (ctx) => { const allDestEvents = _.groupBy(input, (event) => event.destination.ID); const response = { batchedRequests: [], errors: [] }; - Object.entries(allDestEvents).map(async ([, destEvents]) => { - // TODO: check await needed? + Object.entries(allDestEvents).forEach(([, destEvents]) => { try { + // eslint-disable-next-line no-param-reassign destEvents = processDynamicConfig(destEvents, 'batch'); const destBatchedRequests = destHandler.batch(destEvents); response.batchedRequests.push(...destBatchedRequests); @@ -1178,7 +1182,7 @@ const fileUpload = async (ctx) => { } catch (error) { response = { statusCode: error.response ? error.response.status : 400, - error: error.message || 'Error occurred while processing payload.', + error: error.message || PAYLOAD_PROC_ERR_MSG, metadata: error.response ? error.response.metadata : null, }; errNotificationClient.notify(error, 'File Upload', { @@ -1191,17 +1195,17 @@ const fileUpload = async (ctx) => { return ctx.body; }; -const pollStatus = async (ctx) => { - const getReqMetadata = () => { - try { - const reqBody = ctx.request.body; - return { destType: reqBody?.destType, importId: reqBody?.importId }; - } catch (error) { - // Do nothing - } - return {}; - }; +const jobAndPollStatusReqMetadata = (ctx) => { + try { + const reqBody = ctx.request.body; + return { destType: reqBody?.destType, importId: reqBody?.importId }; + } catch (error) { + // Do nothing + } + return {}; +}; +const pollStatus = async (ctx) => { const { destType } = ctx.request.body; const destFileUploadHandler = getPollStatusHandler('v0', destType.toLowerCase()); let response; @@ -1215,12 +1219,12 @@ const pollStatus = async (ctx) => { } catch (error) { response = { statusCode: error.response ? error.response.status : 400, - error: error.message || 'Error occurred while processing payload.', + error: error.message || PAYLOAD_PROC_ERR_MSG, }; errNotificationClient.notify(error, 'Poll Status', { ...response, ...getCommonMetadata(ctx), - ...getReqMetadata(), + ...jobAndPollStatusReqMetadata(ctx), }); } ctx.body = response; @@ -1228,16 +1232,6 @@ const pollStatus = async (ctx) => { }; const getJobStatus = async (ctx, type) => { - const getReqMetadata = () => { - try { - const reqBody = ctx.request.body; - return { destType: reqBody?.destType, importId: reqBody?.importId }; - } catch (error) { - // Do nothing - } - return {}; - }; - const { destType } = ctx.request.body; const destFileUploadHandler = getJobStatusHandler('v0', destType.toLowerCase()); @@ -1252,12 +1246,12 @@ const getJobStatus = async (ctx, type) => { } catch (error) { response = { statusCode: error.response ? error.response.status : 400, - error: error.message || 'Error occurred while processing payload.', + error: error.message || PAYLOAD_PROC_ERR_MSG, }; errNotificationClient.notify(error, 'Job Status', { ...response, ...getCommonMetadata(ctx), - ...getReqMetadata(), + ...jobAndPollStatusReqMetadata(ctx), }); } ctx.body = response; diff --git a/src/warehouse/config/WHExtractEventTableConfig.js b/src/warehouse/config/WHExtractEventTableConfig.js index 3d420079afab..cab6609f43be 100644 --- a/src/warehouse/config/WHExtractEventTableConfig.js +++ b/src/warehouse/config/WHExtractEventTableConfig.js @@ -1,9 +1,9 @@ -const { getRecordIDForExtract } = require("../util"); +const { getRecordIDForExtract } = require('../util'); const rules = { - id: message => getRecordIDForExtract(message), - received_at: "receivedAt", - event: "event" + id: (message) => getRecordIDForExtract(message), + received_at: 'receivedAt', + event: 'event', }; module.exports = rules; diff --git a/src/warehouse/index.js b/src/warehouse/index.js index ea59ce0cb9fb..6f35c5c082f5 100644 --- a/src/warehouse/index.js +++ b/src/warehouse/index.js @@ -25,7 +25,7 @@ const whGroupColumnMappingRules = require('./config/WHGroupConfig.js'); const whAliasColumnMappingRules = require('./config/WHAliasConfig.js'); const { isDataLakeProvider } = require('./config/helpers'); const { InstrumentationError } = require('../v0/util/errorTypes'); -const whExtractEventTableColumnMappingRules = require("./config/WHExtractEventTableConfig.js"); +const whExtractEventTableColumnMappingRules = require('./config/WHExtractEventTableConfig.js'); const maxColumnsInEvent = parseInt(process.env.WH_MAX_COLUMNS_IN_EVENT || '200', 10); @@ -67,7 +67,7 @@ const rudderReservedColums = { screen: { ...whDefaultColumnMappingRules, ...whScreenColumnMappingRules }, group: { ...whDefaultColumnMappingRules, ...whGroupColumnMappingRules }, alias: { ...whDefaultColumnMappingRules, ...whAliasColumnMappingRules }, - extract: { ...whExtractEventTableColumnMappingRules } + extract: { ...whExtractEventTableColumnMappingRules }, }; function excludeRudderCreatedTableNames(name, skipReservedKeywordsEscaping = false) { @@ -545,7 +545,7 @@ function processWarehouseMessage(message, options) { ? message.integrations[options.provider.toUpperCase()].options : {}; const responses = []; - const eventType = message.type.toLowerCase(); + const eventType = message.type?.toLowerCase(); const skipTracksTable = options.integrationOptions.skipTracksTable || false; const skipReservedKeywordsEscaping = options.integrationOptions.skipReservedKeywordsEscaping || false; @@ -615,7 +615,9 @@ function processWarehouseMessage(message, options) { // return error if event name is missing if (_.toString(commonProps[eventColName]).trim() === '') { - throw new InstrumentationError("cannot create event table with empty event name, event name is missing in the payload") + throw new InstrumentationError( + 'cannot create event table with empty event name, event name is missing in the payload', + ); } // always set commonProps last so that they are not overwritten const eventTableEvent = { @@ -638,7 +640,7 @@ function processWarehouseMessage(message, options) { }; responses.push({ metadata: eventTableMetadata, - data: eventTableEvent + data: eventTableEvent, }); break; } diff --git a/src/warehouse/util.js b/src/warehouse/util.js index df87175dec3f..2ba6f3ebf6f6 100644 --- a/src/warehouse/util.js +++ b/src/warehouse/util.js @@ -82,10 +82,10 @@ const getCloudRecordID = (message, fallbackValue) => { return fallbackValue || null; }; -const getRecordIDForExtract = message => { +const getRecordIDForExtract = (message) => { const { recordId } = message; - if (typeof recordId === "object" || isBlank(recordId)) { - throw new Error("recordId cannot be empty for cloud sources events"); + if (typeof recordId === 'object' || isBlank(recordId)) { + throw new Error('recordId cannot be empty for cloud sources events'); } return recordId; }; @@ -101,5 +101,5 @@ module.exports = { isRudderSourcesEvent, sourceCategoriesToUseRecordId, getCloudRecordID, - getRecordIDForExtract + getRecordIDForExtract, }; diff --git a/test/__mocks__/data/criteo_audience/proxy_response.json b/test/__mocks__/data/criteo_audience/proxy_response.json index fc87870c5cfc..0950419ea765 100644 --- a/test/__mocks__/data/criteo_audience/proxy_response.json +++ b/test/__mocks__/data/criteo_audience/proxy_response.json @@ -6,15 +6,15 @@ "code": "400", "response": { "data": { - "errors": [ - { - "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", - "type": "authorization", - "code": "authorization-token-invalid", - "instance": "/2022-10/audiences/123/contactlist", - "title": "The authorization header is invalid" - } - ] + "errors": [ + { + "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", + "type": "authorization", + "code": "authorization-token-invalid", + "instance": "/2022-10/audiences/123/contactlist", + "title": "The authorization header is invalid" + } + ] }, "status": 401 } @@ -23,13 +23,13 @@ "code": "400", "response": { "data": { - "errors": [ - { - "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", - "type": "authorization", - "code": "audience-invalid" - } - ] + "errors": [ + { + "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", + "type": "authorization", + "code": "audience-invalid" + } + ] }, "status": 404 } @@ -38,13 +38,13 @@ "code": "500", "response": { "data": { - "errors": [ - { - "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", - "type": "authorization", - "code": "audience-invalid" - } - ] + "errors": [ + { + "traceIdentifier": "80a1a0ba3981b04da847d05700752c77", + "type": "authorization", + "code": "audience-invalid" + } + ] }, "status": 503 } @@ -52,8 +52,7 @@ "https://api.criteo.com/2022-10/audiences/34898/contactlist": { "code": "429", "response": { - "data": { - }, + "data": {}, "status": 429 } }, @@ -66,4 +65,4 @@ "status": 410 } } -} \ No newline at end of file +} diff --git a/test/__mocks__/data/criteo_audience/response.json b/test/__mocks__/data/criteo_audience/response.json index 783042714775..e1f0eae3d2d4 100644 --- a/test/__mocks__/data/criteo_audience/response.json +++ b/test/__mocks__/data/criteo_audience/response.json @@ -27,7 +27,7 @@ "instance": "/2022-10/audiences/123/contactlist", "title": "The authorization header is invalid" } - ] - } + ] } - } \ No newline at end of file + } +} diff --git a/test/__mocks__/data/google_adwords_offline_conversion/response.json b/test/__mocks__/data/google_adwords_offline_conversion/response.json index 0f0b3d26291c..d9e763c3ace9 100644 --- a/test/__mocks__/data/google_adwords_offline_conversion/response.json +++ b/test/__mocks__/data/google_adwords_offline_conversion/response.json @@ -1,117 +1,117 @@ { - "https://googleads.googleapis.com/v13/customers/11122233331/offlineUserDataJobs:create": { - "data": { - "resourceName": "customers/111-222-3333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_FOR_ADD_FAILURE" - }, - "status": 200 + "https://googleads.googleapis.com/v13/customers/11122233331/offlineUserDataJobs:create": { + "data": { + "resourceName": "customers/111-222-3333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_FOR_ADD_FAILURE" }, - "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs:create": { - "data": { - "resourceName": "customers/111-222-3333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID" - }, - "status": 200 + "status": 200 + }, + "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs:create": { + "data": { + "resourceName": "customers/111-222-3333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID" }, - "https://googleads.googleapis.com/v13/customers/customerid/offlineUserDataJobs:create": { - "status": 401, - "data": { - "error": { - "code": 401, - "message": "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.", - "status": "UNAUTHENTICATED" - } - } - }, - "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID:addOperations": { - "status": 200, - "data": {} - }, - "https://googleads.googleapis.com/v13/customers/11122233331/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_FOR_ADD_FAILURE:addOperations": { - "status": 400, - "data": { - "error": { - "code": 400, - "message": "Request contains an invalid argument.", - "status": "INVALID_ARGUMENT", - "details": [ + "status": 200 + }, + "https://googleads.googleapis.com/v13/customers/customerid/offlineUserDataJobs:create": { + "status": 401, + "data": { + "error": { + "code": 401, + "message": "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.", + "status": "UNAUTHENTICATED" + } + } + }, + "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID:addOperations": { + "status": 200, + "data": {} + }, + "https://googleads.googleapis.com/v13/customers/11122233331/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_FOR_ADD_FAILURE:addOperations": { + "status": 400, + "data": { + "error": { + "code": 400, + "message": "Request contains an invalid argument.", + "status": "INVALID_ARGUMENT", + "details": [ + { + "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", + "errors": [ + { + "errorCode": { + "offlineUserDataJobError": "INVALID_SHA256_FORMAT" + }, + "message": "The SHA256 encoded value is malformed.", + "location": { + "fieldPathElements": [ + { + "fieldName": "operations", + "index": 0 + }, { - "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", - "errors": [ - { - "errorCode": { - "offlineUserDataJobError": "INVALID_SHA256_FORMAT" - }, - "message": "The SHA256 encoded value is malformed.", - "location": { - "fieldPathElements": [ - { - "fieldName": "operations", - "index": 0 - }, - { - "fieldName": "create" - }, - { - "fieldName": "user_identifiers", - "index": 0 - }, - { - "fieldName": "hashed_email" - } - ] - } - } - ], - "requestId": "68697987" + "fieldName": "create" + }, + { + "fieldName": "user_identifiers", + "index": 0 + }, + { + "fieldName": "hashed_email" } - ] - } - } - }, - "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID:run": { - "status": 200, - "data": { - "name": "customers/111-222-3333/operations/abcd=" - } - }, - "https://googleads.googleapis.com/v13/customers/customerid/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_ADD_FAILURE:addOperations": { - "status": 400, - "data": { - "error": { - "code": 400, - "message": "Request contains an invalid argument.", - "status": "INVALID_ARGUMENT", - "details": [ + ] + } + } + ], + "requestId": "68697987" + } + ] + } + } + }, + "https://googleads.googleapis.com/v13/customers/1112223333/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID:run": { + "status": 200, + "data": { + "name": "customers/111-222-3333/operations/abcd=" + } + }, + "https://googleads.googleapis.com/v13/customers/customerid/offlineUserDataJobs/OFFLINE_USER_DATA_JOB_ID_ADD_FAILURE:addOperations": { + "status": 400, + "data": { + "error": { + "code": 400, + "message": "Request contains an invalid argument.", + "status": "INVALID_ARGUMENT", + "details": [ + { + "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", + "errors": [ + { + "errorCode": { + "dateError": "INVALID_STRING_DATE_TIME_SECONDS" + }, + "message": "2023-02-01 14:34:30z", + "location": { + "fieldPathElements": [ + { + "fieldName": "operations", + "index": 0 + }, + { + "fieldName": "create" + }, + { + "fieldName": "transaction_attribute" + }, { - "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", - "errors": [ - { - "errorCode": { - "dateError": "INVALID_STRING_DATE_TIME_SECONDS" - }, - "message": "2023-02-01 14:34:30z", - "location": { - "fieldPathElements": [ - { - "fieldName": "operations", - "index": 0 - }, - { - "fieldName": "create" - }, - { - "fieldName": "transaction_attribute" - }, - { - "fieldName": "transaction_date_time" - } - ] - } - } - ], - "requestId": "u8e0bxqa8yeFHxzywdRQWA" + "fieldName": "transaction_date_time" } - ] - } - } + ] + } + } + ], + "requestId": "u8e0bxqa8yeFHxzywdRQWA" + } + ] + } } -} \ No newline at end of file + } +} diff --git a/test/__mocks__/data/monday/response.json b/test/__mocks__/data/monday/response.json index 18f58cb66d39..a6445f18ac05 100644 --- a/test/__mocks__/data/monday/response.json +++ b/test/__mocks__/data/monday/response.json @@ -209,4 +209,4 @@ }, "account_id": 16260452 } -} \ No newline at end of file +} diff --git a/test/__mocks__/data/salesforce/proxy_response.json b/test/__mocks__/data/salesforce/proxy_response.json index ddb515c5da61..9f24c722947f 100644 --- a/test/__mocks__/data/salesforce/proxy_response.json +++ b/test/__mocks__/data/salesforce/proxy_response.json @@ -69,4 +69,4 @@ "status": 503 } } -} \ No newline at end of file +} diff --git a/test/__mocks__/data/sources/redis/response.json b/test/__mocks__/data/sources/redis/response.json index fb6c1ae82dc7..2ee1782d7b54 100644 --- a/test/__mocks__/data/sources/redis/response.json +++ b/test/__mocks__/data/sources/redis/response.json @@ -1,3 +1,3 @@ { - "redis_test_get": "redis_test_get_value" -} \ No newline at end of file + "redis_test_get": "redis_test_get_value" +} diff --git a/test/__mocks__/data/sources/shopify/response.json b/test/__mocks__/data/sources/shopify/response.json index 41650ceb001c..c8b0e9c9c0ee 100644 --- a/test/__mocks__/data/sources/shopify/response.json +++ b/test/__mocks__/data/sources/shopify/response.json @@ -8,4 +8,4 @@ "shopify_test_cart": { "anonymousId": "anon_shopify_test1" } -} \ No newline at end of file +} diff --git a/test/__tests__/data/braze_input.json b/test/__tests__/data/braze_input.json index d042148df195..0ff5f449c996 100644 --- a/test/__tests__/data/braze_input.json +++ b/test/__tests__/data/braze_input.json @@ -1164,5 +1164,139 @@ "type": "track", "userId": "finalUserTestCA" } + }, + { + "destination": { + "Config": { + "restApiKey": "9432f11f70f8ce386f5110c8c924b3ec4f825256", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "channel": "web", + "context": { + "traits": { + "address": { + "city": "Mathura", + "country": "India" + }, + "email": "anuj.kumar@gmail.com", + "phone": "9988123321", + "firstName": "anuj", + "lastName": "kumar", + "gender": "male", + "birthday": "01/01/1971", + "avatar": "https://i.kym-cdn.com/entries/icons/mobile/000/034/772/anuj-1.jpg", + "bio": "Tech and tension go together", + "language": "en-IN", + "job": "Director", + "company": "Plinth India" + }, + "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 + }, + "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 + }, + "request_ip": "[::1]:53709", + "type": "identify", + "userId": "ank101" + } + }, + { + "destination": { + "Config": { + "restApiKey": "9432f11f70f8ce386f5110c8c924b3ec4f825256", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "channel": "web", + "context": { + "traits": { + "address": { + "city": "Mathura", + "country": "India" + }, + "email": "anuj.kumar@gmail.com", + "phone": "9988123321", + "firstName": "anuj", + "lastName": "kumar", + "gender": null, + "birthday": "01/01/1971", + "avatar": "https://i.kym-cdn.com/entries/icons/mobile/000/034/772/anuj-1.jpg", + "bio": "Tech and tension go together", + "language": "en-IN", + "job": "Director", + "company": null + }, + "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 + }, + "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 + }, + "request_ip": "[::1]:53709", + "type": "identify", + "userId": "ank101" + } } ] diff --git a/test/__tests__/data/braze_output.json b/test/__tests__/data/braze_output.json index 994bb918eeb5..c6c82fffad08 100644 --- a/test/__tests__/data/braze_output.json +++ b/test/__tests__/data/braze_output.json @@ -671,5 +671,83 @@ }, "version": "1", "endpoint": "https://rest.fra-01.braze.eu/users/track" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.iad-01.braze.com/users/track", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer 9432f11f70f8ce386f5110c8c924b3ec4f825256" + }, + "params": {}, + "body": { + "JSON": { + "attributes": [ + { + "country": "India", + "dob": "01/01/1971", + "email": "anuj.kumar@gmail.com", + "first_name": "anuj", + "gender": "M", + "home_city": "Mathura", + "image_url": "https://i.kym-cdn.com/entries/icons/mobile/000/034/772/anuj-1.jpg", + "last_name": "kumar", + "phone": "9988123321", + "bio": "Tech and tension go together", + "language": "en-IN", + "job": "Director", + "company": "Plinth India", + "external_id": "ank101" + } + ] + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "ank101" + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.iad-01.braze.com/users/track", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer 9432f11f70f8ce386f5110c8c924b3ec4f825256" + }, + "params": {}, + "body": { + "JSON": { + "attributes": [ + { + "country": "India", + "dob": "01/01/1971", + "email": "anuj.kumar@gmail.com", + "first_name": "anuj", + "gender": null, + "home_city": "Mathura", + "image_url": "https://i.kym-cdn.com/entries/icons/mobile/000/034/772/anuj-1.jpg", + "last_name": "kumar", + "phone": "9988123321", + "bio": "Tech and tension go together", + "language": "en-IN", + "job": "Director", + "company": null, + "external_id": "ank101" + } + ] + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "ank101" } ] diff --git a/test/__tests__/data/criteo_audience.json b/test/__tests__/data/criteo_audience.json index 5cce1bc3ac2d..bae8a8750bb4 100644 --- a/test/__tests__/data/criteo_audience.json +++ b/test/__tests__/data/criteo_audience.json @@ -71,11 +71,7 @@ "attributes": { "operation": "add", "identifierType": "email", - "identifiers": [ - "alex@email.com", - "amy@email.com", - "van@email.com" - ], + "identifiers": ["alex@email.com", "amy@email.com", "van@email.com"], "internalIdentifiers": false } } @@ -157,11 +153,7 @@ "attributes": { "operation": "add", "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], "internalIdentifiers": false } } @@ -251,11 +243,7 @@ "attributes": { "operation": "add", "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], "internalIdentifiers": false } } @@ -284,9 +272,7 @@ "attributes": { "operation": "remove", "identifierType": "madid", - "identifiers": [ - "sample_madid" - ], + "identifiers": ["sample_madid"], "internalIdentifiers": false } } @@ -376,11 +362,7 @@ "attributes": { "operation": "add", "identifierType": "identityLink", - "identifiers": [ - "text.com", - "yahoo.com", - "abc.com" - ], + "identifiers": ["text.com", "yahoo.com", "abc.com"], "internalIdentifiers": false } } @@ -409,9 +391,7 @@ "attributes": { "operation": "remove", "identifierType": "identityLink", - "identifiers": [ - "text.com" - ], + "identifiers": ["text.com"], "internalIdentifiers": false } } @@ -502,11 +482,7 @@ "attributes": { "operation": "add", "identifierType": "gum", - "identifiers": [ - "sample_gum1", - "sample_gum2", - "sample_gum3" - ], + "identifiers": ["sample_gum1", "sample_gum2", "sample_gum3"], "internalIdentifiers": false, "gumCallerId": "329739" } @@ -536,9 +512,7 @@ "attributes": { "operation": "remove", "identifierType": "gum", - "identifiers": [ - "sample_gum3" - ], + "identifiers": ["sample_gum3"], "internalIdentifiers": false, "gumCallerId": "329739" } @@ -963,4 +937,4 @@ "error": "Required property for email type audience is not available in an object" } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/criteo_audience_proxy_input.json b/test/__tests__/data/criteo_audience_proxy_input.json index fb93fda18a1a..bf504ec46bf5 100644 --- a/test/__tests__/data/criteo_audience_proxy_input.json +++ b/test/__tests__/data/criteo_audience_proxy_input.json @@ -1,223 +1,201 @@ [ - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34894/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "remove", - "identifierType": "gum", - "identifiers": [ - "sample_gum3" - ], - "internalIdentifiers": false, - "gumCallerId": "329739" - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34894/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "remove", + "identifierType": "gum", + "identifiers": ["sample_gum3"], + "internalIdentifiers": false, + "gumCallerId": "329739" + } } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34895/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + } + }, + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34895/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34896/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + } + }, + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34896/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34897/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + } + }, + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34897/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34898/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + } + }, + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34898/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - } - }, - { - "request": { - "body": { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34899/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + } + }, + { + "request": { + "body": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34899/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/criteo_audience_proxy_output.json b/test/__tests__/data/criteo_audience_proxy_output.json index 846a1d5cd4cd..fcaa7440aeab 100644 --- a/test/__tests__/data/criteo_audience_proxy_output.json +++ b/test/__tests__/data/criteo_audience_proxy_output.json @@ -108,7 +108,7 @@ }, { "output": { - "destinationResponse":{ + "destinationResponse": { "response": { "message": "unknown error" }, @@ -126,4 +126,4 @@ "status": 400 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/criteo_audience_router_input.json b/test/__tests__/data/criteo_audience_router_input.json index af3f4dbe8fd5..25607ca936c7 100644 --- a/test/__tests__/data/criteo_audience_router_input.json +++ b/test/__tests__/data/criteo_audience_router_input.json @@ -1,111 +1,111 @@ [ - { - "destination": { - "Config": { - "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", - "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", - "audienceId": "34893", - "audienceType": "email" - }, - "ID": "iwehr83843" - }, - "metadata": { - "secret": { - "accessToken": "success_access_token" - }, - "jobId": 1 - }, - "message": { - "userId": "user 1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "madid": "sample_madid", - "email": "alex@email.com", - "identityLink": "text.com", - "gum": "sdjfds" - }, - { - "madid": "sample_madid_1", - "email": "amy@email.com", - "identityLink": "yahoo.com", - "gum": "sdjfds" - }, - { - "madid": "sample_madid_2", - "email": "van@email.com", - "identityLink": "abc.com", - "gum": "sdjfds" - } - ] - } + { + "destination": { + "Config": { + "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", + "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", + "audienceId": "34893", + "audienceType": "email" + }, + "ID": "iwehr83843" + }, + "metadata": { + "secret": { + "accessToken": "success_access_token" + }, + "jobId": 1 + }, + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "madid": "sample_madid", + "email": "alex@email.com", + "identityLink": "text.com", + "gum": "sdjfds" }, - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } + { + "madid": "sample_madid_1", + "email": "amy@email.com", + "identityLink": "yahoo.com", + "gum": "sdjfds" }, - "timestamp": "2020-02-02T00:23:09.544Z" + { + "madid": "sample_madid_2", + "email": "van@email.com", + "identityLink": "abc.com", + "gum": "sdjfds" + } + ] + } + }, + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" } + }, + "timestamp": "2020-02-02T00:23:09.544Z" + } + }, + { + "destination": { + "Config": { + "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", + "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", + "audienceId": "34893", + "audienceType": "madid" + }, + "ID": "iwehr83843" }, - { - "destination": { - "Config": { - "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", - "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", - "audienceId": "34893", - "audienceType": "madid" - }, - "ID": "iwehr83843" - }, - "metadata": { - "secret": { - "accessToken": "success_access_token" - }, - "jobId": 2 - }, - "message": { - "userId": "user 1", - "type": "audiencelist", - "properties": { - "listData": { - "add": [ - { - "madid": "sample_madid", - "email": "alex@email.com", - "identityLink": "text.com", - "gum": "sdjfds" - }, - { - "madid": "sample_madid_1", - "email": "amy@email.com", - "identityLink": "yahoo.com", - "gum": "sdjfds" - }, - { - "madid": "sample_madid_2", - "email": "van@email.com", - "identityLink": "abc.com", - "gum": "sdjfds" - } - ], - "remove": [ - { - "madid": "sample_madid", - "email": "alex@email.com", - "identityLink": "text.com", - "gum": "sdjfds" - } - ] - } + "metadata": { + "secret": { + "accessToken": "success_access_token" + }, + "jobId": 2 + }, + "message": { + "userId": "user 1", + "type": "audiencelist", + "properties": { + "listData": { + "add": [ + { + "madid": "sample_madid", + "email": "alex@email.com", + "identityLink": "text.com", + "gum": "sdjfds" }, - "context": { - "ip": "14.5.67.21" + { + "madid": "sample_madid_1", + "email": "amy@email.com", + "identityLink": "yahoo.com", + "gum": "sdjfds" }, - "timestamp": "2020-02-02T00:23:09.544Z" + { + "madid": "sample_madid_2", + "email": "van@email.com", + "identityLink": "abc.com", + "gum": "sdjfds" + } + ], + "remove": [ + { + "madid": "sample_madid", + "email": "alex@email.com", + "identityLink": "text.com", + "gum": "sdjfds" + } + ] } + }, + "context": { + "ip": "14.5.67.21" + }, + "timestamp": "2020-02-02T00:23:09.544Z" } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/criteo_audience_router_output.json b/test/__tests__/data/criteo_audience_router_output.json index 776634ae4b46..6c38b7460b78 100644 --- a/test/__tests__/data/criteo_audience_router_output.json +++ b/test/__tests__/data/criteo_audience_router_output.json @@ -1,145 +1,135 @@ [ - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "email", - "identifiers": [ - "alex@email.com", - "amy@email.com", - "van@email.com" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "email", + "identifiers": ["alex@email.com", "amy@email.com", "van@email.com"], + "internalIdentifiers": false + } } - ], - "metadata": [ - { - "jobId": 1, - "secret": { - "accessToken": "success_access_token" - } - } - ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", - "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", - "audienceId": "34893", - "audienceType": "email" - }, - "ID": "iwehr83843" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 1, + "secret": { + "accessToken": "success_access_token" } - }, - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "add", - "identifierType": "madid", - "identifiers": [ - "sample_madid", - "sample_madid_1", - "sample_madid_2" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", - "headers": { - "Authorization": "Bearer success_access_token", - "Content-Type": "application/json", - "Accept": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "ContactlistAmendment", - "attributes": { - "operation": "remove", - "identifierType": "madid", - "identifiers": [ - "sample_madid" - ], - "internalIdentifiers": false - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + } + ], + "batched": false, + "statusCode": 200, + "destination": { + "Config": { + "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", + "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", + "audienceId": "34893", + "audienceType": "email" + }, + "ID": "iwehr83843" + } + }, + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "add", + "identifierType": "madid", + "identifiers": ["sample_madid", "sample_madid_1", "sample_madid_2"], + "internalIdentifiers": false + } } - ], - "metadata": [ - { - "jobId": 2, - "secret": { - "accessToken": "success_access_token" - } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + }, + { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://api.criteo.com/2022-10/audiences/34893/contactlist", + "headers": { + "Authorization": "Bearer success_access_token", + "Content-Type": "application/json", + "Accept": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "ContactlistAmendment", + "attributes": { + "operation": "remove", + "identifierType": "madid", + "identifiers": ["sample_madid"], + "internalIdentifiers": false + } } - ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", - "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", - "audienceId": "34893", - "audienceType": "madid" - }, - "ID": "iwehr83843" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 2, + "secret": { + "accessToken": "success_access_token" } + } + ], + "batched": false, + "statusCode": 200, + "destination": { + "Config": { + "clientId": "abcdef8-f49-4cd6-b4c5-958b3d66d431", + "clientSecret": "sjhdkhfrz6yc9LrRRIPimE9h53jADLccXTykHCcA6eEoFR4rXQg", + "audienceId": "34893", + "audienceType": "madid" + }, + "ID": "iwehr83843" } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/customerio_input.json b/test/__tests__/data/customerio_input.json index 494755093671..f2676a0b4641 100644 --- a/test/__tests__/data/customerio_input.json +++ b/test/__tests__/data/customerio_input.json @@ -2043,21 +2043,11 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU" - ], - "web": [ - "useNativeSDK" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU"], + "web": ["useNativeSDK"] }, "excludeKeys": [], - "includeKeys": [ - "apiKey", - "siteID", - "datacenterEU" - ], + "includeKeys": ["apiKey", "siteID", "datacenterEU"], "saveDestinationResponse": true, "secretKeys": [], "supportedSourceTypes": [ @@ -2134,21 +2124,11 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU" - ], - "web": [ - "useNativeSDK" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU"], + "web": ["useNativeSDK"] }, "excludeKeys": [], - "includeKeys": [ - "apiKey", - "siteID", - "datacenterEU" - ], + "includeKeys": ["apiKey", "siteID", "datacenterEU"], "saveDestinationResponse": true, "secretKeys": [], "supportedSourceTypes": [ @@ -2265,17 +2245,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2287,12 +2258,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -2406,17 +2372,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2428,12 +2385,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -2547,17 +2499,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2569,12 +2512,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -2688,17 +2626,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2710,12 +2639,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -2826,17 +2750,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2848,12 +2763,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -2968,17 +2878,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -2990,12 +2891,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3109,17 +3005,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3131,12 +3018,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3250,17 +3132,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3272,12 +3145,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3391,17 +3259,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3413,12 +3272,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3529,17 +3383,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3551,12 +3396,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3671,17 +3511,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3693,12 +3524,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3776,17 +3602,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3798,12 +3615,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3881,17 +3693,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -3903,12 +3706,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -3989,17 +3787,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -4011,12 +3800,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -4097,17 +3881,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -4119,12 +3894,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -4207,17 +3977,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -4229,12 +3990,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -4317,17 +4073,8 @@ "DisplayName": "Customer IO", "Config": { "destConfig": { - "defaultConfig": [ - "apiKey", - "siteID", - "datacenterEU", - "deviceTokenEventName" - ], - "web": [ - "useNativeSDK", - "blackListedEvents", - "whiteListedEvents" - ] + "defaultConfig": ["apiKey", "siteID", "datacenterEU", "deviceTokenEventName"], + "web": ["useNativeSDK", "blackListedEvents", "whiteListedEvents"] }, "excludeKeys": [], "includeKeys": [ @@ -4339,12 +4086,7 @@ ], "saveDestinationResponse": true, "secretKeys": [], - "supportedMessageTypes": [ - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -4374,4 +4116,4 @@ "IsProcessorEnabled": true } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/customerio_output.json b/test/__tests__/data/customerio_output.json index 23629d494625..c1a996ac9102 100644 --- a/test/__tests__/data/customerio_output.json +++ b/test/__tests__/data/customerio_output.json @@ -1398,4 +1398,4 @@ "userId": 432, "statusCode": 200 } -] \ No newline at end of file +] diff --git a/test/__tests__/data/customerio_router_input.json b/test/__tests__/data/customerio_router_input.json index 7d238655f398..b0d7b0b009e7 100644 --- a/test/__tests__/data/customerio_router_input.json +++ b/test/__tests__/data/customerio_router_input.json @@ -230,4 +230,4 @@ } } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/customerio_router_output.json b/test/__tests__/data/customerio_router_output.json index 71180613c079..4a050620c791 100644 --- a/test/__tests__/data/customerio_router_output.json +++ b/test/__tests__/data/customerio_router_output.json @@ -172,4 +172,4 @@ } } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/engage.json b/test/__tests__/data/engage.json index 975d9899ebdb..124038b3cfad 100644 --- a/test/__tests__/data/engage.json +++ b/test/__tests__/data/engage.json @@ -20,7 +20,7 @@ } }, "output": { - "error": "Neither externalId or userId is available." + "error": "Neither externalId nor userId is available" } }, { diff --git a/test/__tests__/data/facebook_pixel_router_input.json b/test/__tests__/data/facebook_pixel_router_input.json index 7614f450b4cd..5e9adfcb93df 100644 --- a/test/__tests__/data/facebook_pixel_router_input.json +++ b/test/__tests__/data/facebook_pixel_router_input.json @@ -54,7 +54,7 @@ "blacklistPiiHash": false } ], - "removeExternalId":true, + "removeExternalId": true, "accessToken": "09876", "pixelId": "dfgdfgdgd", "eventsToEvents": [ diff --git a/test/__tests__/data/fb_custom_audience.json b/test/__tests__/data/fb_custom_audience.json index 3ae7da27a852..5795bbfc4e70 100644 --- a/test/__tests__/data/fb_custom_audience.json +++ b/test/__tests__/data/fb_custom_audience.json @@ -808,14 +808,8 @@ "type": "UNKNOWN", "sub_type": "ANYTHING" }, - "schema": [ - "DOBM" - ], - "data": [ - [ - "2" - ] - ] + "schema": ["DOBM"], + "data": [["2"]] } }, "body": { @@ -840,14 +834,8 @@ "type": "UNKNOWN", "sub_type": "ANYTHING" }, - "schema": [ - "DOBM" - ], - "data": [ - [ - "2" - ] - ] + "schema": ["DOBM"], + "data": [["2"]] } }, "body": { @@ -1717,7 +1705,7 @@ "a953f09a1b6b6725b81956e9ad0b1eb49e3ad40004c04307ef8af6246a054116", "3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278", "7931aa2a1bed855457d1ddf6bc06ab4406a9fba0579045a4d6ff78f9c07c440f", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + null, "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", "db0683221aebc02cc034b65ebcf7d1bddd1eb199e33fd23a31931947d13a11bc", "abc", @@ -1807,9 +1795,59 @@ "query": {} } }, - "output": { - "error": "Configured Schema field PHONE is missing in one or more user records" - } + "output": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://graph.facebook.com/v16.0/aud1/users", + "headers": {}, + "params": { + "access_token": "ABC", + "payload": { + "data_source": { + "type": "UNKNOWN", + "sub_type": "ANYTHING" + }, + "schema": [ + "EMAIL", + "DOBM", + "DOBD", + "DOBY", + "PHONE", + "GEN", + "FI", + "MADID", + "ZIP", + "ST", + "COUNTRY" + ], + "data": [ + [ + "85cc9fefa1eff1baab55d10df0cecff2acb25344867a5d0f96e1b1c5e2f10f05", + "a953f09a1b6b6725b81956e9ad0b1eb49e3ad40004c04307ef8af6246a054116", + "3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278", + "7931aa2a1bed855457d1ddf6bc06ab4406a9fba0579045a4d6ff78f9c07c440f", + null, + "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", + "db0683221aebc02cc034b65ebcf7d1bddd1eb199e33fd23a31931947d13a11bc", + "abc", + "4a70fe9aa6436e02c2dea340fbd1e352e4ef2d8ce6ca52ad25d4b95471fc8bf2", + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf" + ] + ] + } + }, + "body": { + "JSON": {}, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ] }, { "description": "Batching according payload size", diff --git a/test/__tests__/data/fb_custom_audience_router_rETL_input.json b/test/__tests__/data/fb_custom_audience_router_rETL_input.json index fc66c141304b..c0c95a2bc33f 100644 --- a/test/__tests__/data/fb_custom_audience_router_rETL_input.json +++ b/test/__tests__/data/fb_custom_audience_router_rETL_input.json @@ -1,77 +1,77 @@ [ { - "message": { - "sentAt" : "2023-03-30 06:42:55.991938402 +0000 UTC", - "userId" : "2MUWghI7u85n91dd1qzGyswpZan-2MUWqbQqvctyfMGqU9QCNadpKNy", - "channel" : "sources", - "messageId" : "4d906837-031d-4d34-b97a-62fdf51b4d3a", - "event" : "Add_Audience", - "context" : { - "destinationFields" : "EMAIL, FN", - "externalId" : [ + "message": { + "sentAt": "2023-03-30 06:42:55.991938402 +0000 UTC", + "userId": "2MUWghI7u85n91dd1qzGyswpZan-2MUWqbQqvctyfMGqU9QCNadpKNy", + "channel": "sources", + "messageId": "4d906837-031d-4d34-b97a-62fdf51b4d3a", + "event": "Add_Audience", + "context": { + "destinationFields": "EMAIL, FN", + "externalId": [ { - "type" : "FB_CUSTOM_AUDIENCE-23848494844100489", - "identifierType" : "EMAIL" + "type": "FB_CUSTOM_AUDIENCE-23848494844100489", + "identifierType": "EMAIL" } ], - "mappedToDestination" : "true", - "sources" : { - "job_run_id" : "cgiiurt8um7k7n5dq480", - "task_run_id" : "cgiiurt8um7k7n5dq48g", - "job_id" : "2MUWghI7u85n91dd1qzGyswpZan", - "version" : "895\/merge" + "mappedToDestination": "true", + "sources": { + "job_run_id": "cgiiurt8um7k7n5dq480", + "task_run_id": "cgiiurt8um7k7n5dq48g", + "job_id": "2MUWghI7u85n91dd1qzGyswpZan", + "version": "895/merge" } }, - "recordId" : "725ad989-6750-4839-b46b-0ddb3b8e5aa2\/1\/10", - "rudderId" : "85c49666-c628-4835-937b-8f1d9ee7a724", - "properties" : { - "listData" : { - "add" : [ + "recordId": "725ad989-6750-4839-b46b-0ddb3b8e5aa2/1/10", + "rudderId": "85c49666-c628-4835-937b-8f1d9ee7a724", + "properties": { + "listData": { + "add": [ { - "EMAIL" : "dede@gmail.com", - "FN" : "vishwa" + "EMAIL": "dede@gmail.com", + "FN": "vishwa" }, { - "EMAIL" : "fchsjjn@gmail.com", - "FN" : "hskks" + "EMAIL": "fchsjjn@gmail.com", + "FN": "hskks" }, { - "EMAIL" : "fghjnbjk@gmail.com", - "FN" : "ghfry" + "EMAIL": "fghjnbjk@gmail.com", + "FN": "ghfry" }, { - "EMAIL" : "gvhjkk@gmail.com", - "FN" : "hbcwqe" + "EMAIL": "gvhjkk@gmail.com", + "FN": "hbcwqe" }, { - "EMAIL" : "qsdwert@egf.com", - "FN" : "dsfds" + "EMAIL": "qsdwert@egf.com", + "FN": "dsfds" }, { - "EMAIL" : "ascscxsaca@com", - "FN" : "scadscdvcda" + "EMAIL": "ascscxsaca@com", + "FN": "scadscdvcda" }, { - "EMAIL" : "abc@gmail.com", - "FN" : "subscribed" + "EMAIL": "abc@gmail.com", + "FN": "subscribed" }, { - "EMAIL" : "ddwnkl@gmail.com", - "FN" : "subscribed" + "EMAIL": "ddwnkl@gmail.com", + "FN": "subscribed" }, { - "EMAIL" : "subscribed@eewrfrd.com", - "FN" : "pending" + "EMAIL": "subscribed@eewrfrd.com", + "FN": "pending" }, { - "EMAIL" : "acsdvdf@ddfvf.com", - "FN" : "pending" + "EMAIL": "acsdvdf@ddfvf.com", + "FN": "pending" } ] } }, - "type" : "audienceList", - "anonymousId" : "63228b51-394e-4ca2-97a0-427f6187480b" + "type": "audienceList", + "anonymousId": "63228b51-394e-4ca2-97a0-427f6187480b" }, "destination": { "Config": { @@ -84,7 +84,7 @@ "skipVerify": false, "subType": "NA", "type": "NA", - "userSchema": [ "EMAIL" ] + "userSchema": ["EMAIL"] }, "secretConfig": {}, "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", @@ -110,33 +110,142 @@ } }, { - "message": { - "sentAt" : "2023-03-30 06:42:55.991938402 +0000 UTC", - "userId" : "2MUWghI7u85n91dd1qzGyswpZan-2MUWqbQqvctyfMGqU9QCNadpKNy", - "channel" : "sources", - "messageId" : "4d906837-031d-4d34-b97a-62fdf51b4d3a", - "event" : "Add_Audience", - "context" : { - "destinationFields" : "EMAIL, DOBM, DOBD, DOBY, PHONE, GEN, FI, MADID, ZIP, ST, COUNTRY", - "externalId" : [ + "message": { + "sentAt": "2023-03-30 06:42:55.991938402 +0000 UTC", + "userId": "2MUWghI7u85n91dd1qzGyswpZan-2MUWqbQqvctyfMGqU9QCNadpKNy", + "channel": "sources", + "messageId": "4d906837-031d-4d34-b97a-62fdf51b4d3a", + "event": "Add_Audience", + "context": { + "externalId": [ { - "type" : "FB_CUSTOM_AUDIENCE-aud1", - "identifierType" : "EMAIL" + "type": "FB_CUSTOM_AUDIENCE-23848494844100489", + "identifierType": "EMAIL" } ], - "mappedToDestination" : "true", - "sources" : { - "job_run_id" : "cgiiurt8um7k7n5dq480", - "task_run_id" : "cgiiurt8um7k7n5dq48g", - "job_id" : "2MUWghI7u85n91dd1qzGyswpZan", - "version" : "895\/merge" + "mappedToDestination": "true", + "sources": { + "job_run_id": "cgiiurt8um7k7n5dq480", + "task_run_id": "cgiiurt8um7k7n5dq48g", + "job_id": "2MUWghI7u85n91dd1qzGyswpZan", + "version": "895/merge" } }, - "recordId" : "725ad989-6750-4839-b46b-0ddb3b8e5aa2\/1\/10", - "rudderId" : "85c49666-c628-4835-937b-8f1d9ee7a724", - "properties" : { - "listData" : { - "add" : [ + "recordId": "725ad989-6750-4839-b46b-0ddb3b8e5aa2/1/10", + "rudderId": "85c49666-c628-4835-937b-8f1d9ee7a724", + "properties": { + "listData": { + "add": [ + { + "EMAIL": "dede@gmail.com", + "FN": "vishwa" + }, + { + "EMAIL": "fchsjjn@gmail.com", + "FN": "hskks" + }, + { + "EMAIL": "fghjnbjk@gmail.com", + "FN": "ghfry" + }, + { + "EMAIL": "gvhjkk@gmail.com", + "FN": "hbcwqe" + }, + { + "EMAIL": "qsdwert@egf.com", + "FN": "dsfds" + }, + { + "EMAIL": "ascscxsaca@com", + "FN": "scadscdvcda" + }, + { + "EMAIL": "abc@gmail.com", + "FN": "subscribed" + }, + { + "EMAIL": "ddwnkl@gmail.com", + "FN": "subscribed" + }, + { + "EMAIL": "subscribed@eewrfrd.com", + "FN": "pending" + }, + { + "EMAIL": "acsdvdf@ddfvf.com", + "FN": "pending" + } + ] + } + }, + "type": "audienceList", + "anonymousId": "63228b51-394e-4ca2-97a0-427f6187480b" + }, + "destination": { + "Config": { + "accessToken": "ABC", + "disableFormat": false, + "isHashRequired": true, + "isRaw": false, + "maxUserCount": "50", + "oneTrustCookieCategories": [], + "skipVerify": false, + "subType": "NA", + "type": "NA", + "userSchema": ["EMAIL"] + }, + "secretConfig": {}, + "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", + "name": "FB_CUSTOM_AUDIENCE", + "enabled": true, + "workspaceId": "1TSN08muJTZwH8iCDmnnRt1pmLd", + "deleted": false, + "createdAt": "2020-12-30T08:39:32.005Z", + "updatedAt": "2021-02-03T16:22:31.374Z", + "destinationDefinition": { + "id": "1aIXqM806xAVm92nx07YwKbRrO9", + "name": "FB_CUSTOM_AUDIENCE", + "displayName": "FB_CUSTOM_AUDIENCE", + "createdAt": "2020-04-09T09:24:31.794Z", + "updatedAt": "2021-01-11T11:03:28.103Z" + }, + "transformations": [], + "isConnectionEnabled": true, + "isProcessorEnabled": true + }, + "metadata": { + "jobId": 2 + } + }, + { + "message": { + "sentAt": "2023-03-30 06:42:55.991938402 +0000 UTC", + "userId": "2MUWghI7u85n91dd1qzGyswpZan-2MUWqbQqvctyfMGqU9QCNadpKNy", + "channel": "sources", + "messageId": "4d906837-031d-4d34-b97a-62fdf51b4d3a", + "event": "Add_Audience", + "context": { + "destinationFields": "EMAIL, DOBM, DOBD, DOBY, PHONE, GEN, FI, MADID, ZIP, ST, COUNTRY", + "externalId": [ + { + "type": "FB_CUSTOM_AUDIENCE-aud1", + "identifierType": "EMAIL" + } + ], + "mappedToDestination": "true", + "sources": { + "job_run_id": "cgiiurt8um7k7n5dq480", + "task_run_id": "cgiiurt8um7k7n5dq48g", + "job_id": "2MUWghI7u85n91dd1qzGyswpZan", + "version": "895/merge" + } + }, + "recordId": "725ad989-6750-4839-b46b-0ddb3b8e5aa2/1/10", + "rudderId": "85c49666-c628-4835-937b-8f1d9ee7a724", + "properties": { + "listData": { + "add": [ { "EMAIL": "shrouti@abc.com", "DOBM": "2", @@ -26088,8 +26197,8 @@ ] } }, - "type" : "audienceList", - "anonymousId" : "63228b51-394e-4ca2-97a0-427f6187480b" + "type": "audienceList", + "anonymousId": "63228b51-394e-4ca2-97a0-427f6187480b" }, "destination": { "Config": { @@ -26139,4 +26248,4 @@ "jobId": 2 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/fb_custom_audience_router_rETL_output.json b/test/__tests__/data/fb_custom_audience_router_rETL_output.json index 485f36cb2386..9d7b448239c7 100644 --- a/test/__tests__/data/fb_custom_audience_router_rETL_output.json +++ b/test/__tests__/data/fb_custom_audience_router_rETL_output.json @@ -10,51 +10,18 @@ "params": { "access_token": "ABC", "payload": { - "schema": [ - "EMAIL", - "FN" - ], + "schema": ["EMAIL", "FN"], "data": [ - [ - "7625cab24612c37df6d2f724721bb38a25095d0295e29b807238ee188b8aca43", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "b2b4abadd72190af54305c0d3abf1977fec4935016bb13ff28040d5712318dfd", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "c4b007d1c3c9a5d31bd4082237a913e8e0db1767225c2a5ef33be2716df005fa", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "94639be1bd9f17c05820164e9d71ef78558f117a9e8bfab43cf8015e08aa0b27", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "39b456cfb4bb07f9e6bb18698aa173171ca49c731fccc4790e9ecea808d24ae6", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "769f73387add781a481ca08300008a08fb2f1816aaed196137efc2e05976d711", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "da2d431121cd10578fd81f8f80344b06db59ea2d05a7b5d27536c8789ddae8f0", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "b100c2ec0718fe6b4805b623aeec6710719d042ceea55f5c8135b010ec1c7b36", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ], - [ - "0c1d1b0ba547a742013366d6fbc8f71dd77f566d94e41ed9f828a74b96928161", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - ] + ["7625cab24612c37df6d2f724721bb38a25095d0295e29b807238ee188b8aca43", null], + ["b2b4abadd72190af54305c0d3abf1977fec4935016bb13ff28040d5712318dfd", null], + ["c4b007d1c3c9a5d31bd4082237a913e8e0db1767225c2a5ef33be2716df005fa", null], + ["94639be1bd9f17c05820164e9d71ef78558f117a9e8bfab43cf8015e08aa0b27", null], + ["39b456cfb4bb07f9e6bb18698aa173171ca49c731fccc4790e9ecea808d24ae6", null], + ["769f73387add781a481ca08300008a08fb2f1816aaed196137efc2e05976d711", null], + ["48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08", null], + ["da2d431121cd10578fd81f8f80344b06db59ea2d05a7b5d27536c8789ddae8f0", null], + ["b100c2ec0718fe6b4805b623aeec6710719d042ceea55f5c8135b010ec1c7b36", null], + ["0c1d1b0ba547a742013366d6fbc8f71dd77f566d94e41ed9f828a74b96928161", null] ] } }, @@ -85,9 +52,41 @@ "skipVerify": false, "subType": "NA", "type": "NA", - "userSchema": [ - "EMAIL" - ] + "userSchema": ["EMAIL"] + }, + "secretConfig": {}, + "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", + "name": "FB_CUSTOM_AUDIENCE", + "enabled": true, + "workspaceId": "1TSN08muJTZwH8iCDmnnRt1pmLd", + "deleted": false, + "createdAt": "2020-12-30T08:39:32.005Z", + "updatedAt": "2021-02-03T16:22:31.374Z", + "destinationDefinition": { + "id": "1aIXqM806xAVm92nx07YwKbRrO9", + "name": "FB_CUSTOM_AUDIENCE", + "displayName": "FB_CUSTOM_AUDIENCE", + "createdAt": "2020-04-09T09:24:31.794Z", + "updatedAt": "2021-01-11T11:03:28.103Z" + }, + "transformations": [], + "isConnectionEnabled": true, + "isProcessorEnabled": true + } + }, + { + "destination": { + "Config": { + "accessToken": "ABC", + "disableFormat": false, + "isHashRequired": true, + "isRaw": false, + "maxUserCount": "50", + "oneTrustCookieCategories": [], + "skipVerify": false, + "subType": "NA", + "type": "NA", + "userSchema": ["EMAIL"] }, "secretConfig": {}, "ID": "1mMy5cqbtfuaKZv1IhVQKnBdVwe", @@ -107,6 +106,18 @@ "transformations": [], "isConnectionEnabled": true, "isProcessorEnabled": true + }, + "error": "context.destinationFields is required property for events mapped to destination ", + "metadata": [ + { + "jobId": 2 + } + ], + "batched": false, + "statusCode": 400, + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" } }, { diff --git a/test/__tests__/data/ga4.json b/test/__tests__/data/ga4.json index 599a3166a454..4fff0d0ed7ff 100644 --- a/test/__tests__/data/ga4.json +++ b/test/__tests__/data/ga4.json @@ -10939,11 +10939,7 @@ "city": "kolkata", "district": "24pgs" }, - "categoryLevels": [ - "Furniture", - "Bedroom Furniture", - "Dressers & Chests" - ], + "categoryLevels": ["Furniture", "Bedroom Furniture", "Dressers & Chests"], "products": [ { "product_id": "1234", @@ -10951,11 +10947,7 @@ "colour": "red", "shape": "rectangle" }, - "productLevels": [ - "test1", - "test2", - "test3" - ] + "productLevels": ["test1", "test2", "test3"] } ] }, @@ -11742,4 +11734,4 @@ "endpoint": "https://www.google-analytics.com/mp/collect" } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/gainsight_px_input.json b/test/__tests__/data/gainsight_px_input.json index 795585277b5b..0ce694e5a67d 100644 --- a/test/__tests__/data/gainsight_px_input.json +++ b/test/__tests__/data/gainsight_px_input.json @@ -645,20 +645,12 @@ "properties": { "description": "Stringify test for object values", "nested": { - "a": [ - 1, - 2, - 3 - ], + "a": [1, 2, 3], "b": { "c": 1 } }, - "arr": [ - 1, - 2, - 3 - ] + "arr": [1, 2, 3] }, "integrations": { "All": true @@ -729,20 +721,12 @@ "properties": { "description": "Stringify test for object values", "nested": { - "a": [ - 1, - 2, - 3 - ], + "a": [1, 2, 3], "b": { "c": 1 } }, - "arr": [ - 1, - 2, - 3 - ], + "arr": [1, 2, 3], "globalContext": { "someKey": "someVal" } @@ -1027,4 +1011,4 @@ "sentAt": "2019-10-14T09:03:22.563Z" } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/gainsight_px_output.json b/test/__tests__/data/gainsight_px_output.json index d0026b2476df..17b27273b64a 100644 --- a/test/__tests__/data/gainsight_px_output.json +++ b/test/__tests__/data/gainsight_px_output.json @@ -117,9 +117,7 @@ "signUpDate": 1624431528295, "createDate": 1571043797562, "title": "engineer", - "propertyKeys": [ - "AP-XABC-123" - ], + "propertyKeys": ["AP-XABC-123"], "location": { "countryName": "USA", "countryCode": "US", @@ -253,9 +251,7 @@ "signUpDate": 1624431528295, "createDate": 1571043797562, "title": "engineer", - "propertyKeys": [ - "AP-XABC-123" - ], + "propertyKeys": ["AP-XABC-123"], "location": { "countryName": "USA", "countryCode": "US", @@ -292,9 +288,7 @@ "signUpDate": 1624431528295, "createDate": 1571043797562, "title": "engineer", - "propertyKeys": [ - "AP-XABC-123" - ], + "propertyKeys": ["AP-XABC-123"], "accountId": "1234", "location": { "countryName": "USA", @@ -335,4 +329,4 @@ }, "files": {} } -] \ No newline at end of file +] diff --git a/test/__tests__/data/google_adwords_offline_conversions.json b/test/__tests__/data/google_adwords_offline_conversions.json index 125ccd36f96a..a0b69b70da03 100644 --- a/test/__tests__/data/google_adwords_offline_conversions.json +++ b/test/__tests__/data/google_adwords_offline_conversions.json @@ -4576,9 +4576,7 @@ "transaction_amount_micros": "100000000", "transaction_date_time": "2019-10-14 11:15:18+00:00" }, - "userIdentifiers": [ - {} - ] + "userIdentifiers": [{}] } }, "validate_only": false @@ -4606,4 +4604,4 @@ } ] } -] \ No newline at end of file +] diff --git a/test/__tests__/data/google_adwords_offline_conversions_proxy_input.json b/test/__tests__/data/google_adwords_offline_conversions_proxy_input.json index 9638f4e5d089..12ed8ad0c177 100644 --- a/test/__tests__/data/google_adwords_offline_conversions_proxy_input.json +++ b/test/__tests__/data/google_adwords_offline_conversions_proxy_input.json @@ -509,4 +509,4 @@ } } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/google_adwords_offline_conversions_proxy_output.json b/test/__tests__/data/google_adwords_offline_conversions_proxy_output.json index 1e421512302c..f6b41dfcbb41 100644 --- a/test/__tests__/data/google_adwords_offline_conversions_proxy_output.json +++ b/test/__tests__/data/google_adwords_offline_conversions_proxy_output.json @@ -8,36 +8,36 @@ "code": 400, "details": [ { - "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", - "errors": [ - { - "errorCode": { - "offlineUserDataJobError": "INVALID_SHA256_FORMAT" - }, - "message": "The SHA256 encoded value is malformed.", - "location": { - "fieldPathElements": [ - { - "fieldName": "operations", - "index": 0 - }, - { - "fieldName": "create" - }, - { - "fieldName": "user_identifiers", - "index": 0 - }, - { - "fieldName": "hashed_email" - } - ] - } - } - ], - "requestId": "68697987" + "@type": "type.googleapis.com/google.ads.googleads.v13.errors.GoogleAdsFailure", + "errors": [ + { + "errorCode": { + "offlineUserDataJobError": "INVALID_SHA256_FORMAT" + }, + "message": "The SHA256 encoded value is malformed.", + "location": { + "fieldPathElements": [ + { + "fieldName": "operations", + "index": 0 + }, + { + "fieldName": "create" + }, + { + "fieldName": "user_identifiers", + "index": 0 + }, + { + "fieldName": "hashed_email" + } + ] + } + } + ], + "requestId": "68697987" } - ], + ], "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT" } @@ -152,4 +152,4 @@ "status": 200 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/hs_input.json b/test/__tests__/data/hs_input.json index 212dbe7097fc..542b68c9c73f 100644 --- a/test/__tests__/data/hs_input.json +++ b/test/__tests__/data/hs_input.json @@ -2991,4 +2991,4 @@ "Enabled": true } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/intercom_input.json b/test/__tests__/data/intercom_input.json index aa108a195a0c..3179223ab156 100644 --- a/test/__tests__/data/intercom_input.json +++ b/test/__tests__/data/intercom_input.json @@ -1017,5 +1017,133 @@ "sendAnonymousId": false } } + }, + { + "message": { + "groupId": "test_company_id_wdasda", + "traits": { + "employees": 450, + "plan": "basic", + "userId": "sdfrsdfsdfsf", + "email": "test@test.com", + "name": "rudderUpdate", + "size": "50", + "industry": "IT", + "monthlySpend": "2131231", + "remoteCreatedAt": "1683017572", + "key1": "val1" + }, + "anonymousId": "sdfrsdfsdfsf", + "integrations": { + "All": true + }, + "type": "group", + "userId": "sdfrsdfsdfsf" + }, + "destination": { + "Config": { + "apiKey": "abcd=", + "appId": "asdasdasd", + "collectContext": false + } + } + }, + { + "message": { + "groupId": "test_company_id", + "traits": { + "plan": "basic", + "name": "rudderUpdate", + "size": 50, + "industry": "IT", + "monthlySpend": "2131231", + "email" : "comanyemail@abc.com" + }, + "anonymousId": "12312312", + "context": { + "app": { + "build": "1.0", + "name": "Test_Example", + "namespace": "com.example.testapp", + "version": "1.0" + }, + "device": { + "id": "58b21c2d-f8d5-4410-a2d0-b268a26b7e33", + "manufacturer": "Apple", + "model": "iPhone", + "name": "iPod touch (7th generation)", + "type": "iOS" + }, + "library": { + "name": "test-ios-library", + "version": "1.0.7" + }, + "locale": "en-US", + "network": { + "bluetooth": false, + "carrier": "unavailable", + "cellular": false, + "wifi": true + }, + "os": { + "name": "iOS", + "version": "14.0" + }, + "screen": { + "density": 2, + "height": 320, + "width": 568 + }, + "timezone": "Asia/Kolkata", + "userAgent": "unknown" + }, + "integrations": { + "All": true + }, + "messageId": "1601493060-39010c49-e6e4-4626-a75c-0dbf1925c9e8", + "type": "group" + }, + "destination": { + "Config": { + "apiKey": "abcd=", + "appId": "asdasdasd", + "collectContext": false + } + } + }, + { + "message": { + "groupId": "test_company_id_wdasda", + "context": { + "traits": { + "email": "testUser@test.com" + } + }, + "traits": { + "employees": 450, + "plan": "basic", + "email": "test@test.com", + "name": "rudderUpdate", + "size": "50", + "industry": "IT", + "website": "url", + "monthlySpend": "2131231", + "remoteCreatedAt": "1683017572", + "key1": "val1" + }, + "anonymousId": "sdfrsdfsdfsf", + "integrations": { + "All": true + }, + "type": "group", + "userId": "sdfrsdfsdfsf" + }, + "destination": { + "Config": { + "apiKey": "abcd=", + "appId": "asdasdasd", + "collectContext": false + } + } } ] diff --git a/test/__tests__/data/intercom_output.json b/test/__tests__/data/intercom_output.json index 00230943ec56..b3090d4f5a5d 100644 --- a/test/__tests__/data/intercom_output.json +++ b/test/__tests__/data/intercom_output.json @@ -377,5 +377,168 @@ { "statusCode": 400, "error": "Email or userId is mandatory" - } + }, + [{ + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "name": "rudderUpdate", + "plan": "basic", + "size": 50, + "industry": "IT", + "company_id": "test_company_id_wdasda", + "monthly_spend": 2131231, + "remote_created_at": 1683017572, + "custom_attributes": { + "key1": "val1", + "employees": 450, + "email": "test@test.com" + } + }, + "JSON_ARRAY": {} + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "sdfrsdfsdfsf", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer abcd=", + "Intercom-Version": "1.4" + }, + "version": "1", + "endpoint": "https://api.intercom.io/companies" + }, + { + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "user_id": "sdfrsdfsdfsf", + "companies": [ + { + "name": "rudderUpdate", + "company_id": "test_company_id_wdasda" + } + ] + }, + "JSON_ARRAY": {} + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "sdfrsdfsdfsf", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer abcd=", + "Intercom-Version": "1.4" + }, + "version": "1", + "endpoint": "https://api.intercom.io/users" + }], + [ + { + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "name": "rudderUpdate", + "size": 50, + "industry": "IT", + "company_id": "test_company_id", + "monthly_spend": 2131231, + "plan": "basic", + "custom_attributes": { + "email" : "comanyemail@abc.com" + } + }, + "JSON_ARRAY": {} + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "12312312", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer abcd=", + "Intercom-Version": "1.4" + }, + "version": "1", + "endpoint": "https://api.intercom.io/companies" + } + ], + [ + { + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "name": "rudderUpdate", + "plan": "basic", + "size": 50, + "industry": "IT", + "company_id": "test_company_id_wdasda", + "monthly_spend": 2131231, + "remote_created_at": 1683017572, + "website": "url", + "custom_attributes": { + "key1": "val1", + "employees": 450, + "email": "test@test.com" + } + }, + "JSON_ARRAY": {} + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "sdfrsdfsdfsf", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer abcd=", + "Intercom-Version": "1.4" + }, + "version": "1", + "endpoint": "https://api.intercom.io/companies" + }, + { + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "user_id": "sdfrsdfsdfsf", + "email": "testUser@test.com", + "companies": [ + { + "name": "rudderUpdate", + "company_id": "test_company_id_wdasda" + } + ] + }, + "JSON_ARRAY": {} + }, + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "sdfrsdfsdfsf", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer abcd=", + "Intercom-Version": "1.4" + }, + "version": "1", + "endpoint": "https://api.intercom.io/users" + } + ] ] diff --git a/test/__tests__/data/lemnisk.json b/test/__tests__/data/lemnisk.json index d8135126b66e..0f38eaf639c2 100644 --- a/test/__tests__/data/lemnisk.json +++ b/test/__tests__/data/lemnisk.json @@ -1,1055 +1,983 @@ [ - { - "description": "Error: Event Type is required ", - "input": { - "message": { - "userId": "user123", - "event": "Product Reviewed", - "properties": { - "review_body": "Average product, expected much more." - }, - "context": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" - }, - "timestamp": "2020-02-02T00:23:09.544Z", - "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383" + { + "description": "Error: Event Type is required ", + "input": { + "message": { + "userId": "user123", + "event": "Product Reviewed", + "properties": { + "review_body": "Average product, expected much more." + }, + "context": { + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" + }, + "timestamp": "2020-02-02T00:23:09.544Z", + "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" }, - "output": { - "error": "Event type is required" - } + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": "Error: Pl Track: Invalid Configuration", - "input": { - "message": { - "type": "track", - "properties": { - "product_id": "ab1234", - "rating": 3, - "review_body": "Average product, expected much more.", - "review_id": "12345" - }, - "event": "Product Reviewed", - "context": { - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "2.9.1" - }, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" - }, - "timestamp": "2020-02-02T00:23:09.544Z", - "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383" + "output": { + "error": "Event type is required" + } + }, + { + "description": "Error: Pl Track: Invalid Configuration", + "input": { + "message": { + "type": "track", + "properties": { + "product_id": "ab1234", + "rating": 3, + "review_body": "Average product, expected much more.", + "review_id": "12345" + }, + "event": "Product Reviewed", + "context": { + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "2.9.1" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" + }, + "timestamp": "2020-02-02T00:23:09.544Z", + "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" }, - "output": { - "error": "Configuration for Web Mode requires write key and region url" - } + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": "Error: Invalid Configs for Diapi", - "input": { - "message": { - "anonymousId": "anon-id-new", - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - }, - "traits": { - "firstName": "Anant", - "lastName": "jain", - "role": "Manager", - "address": "Flat No 58 ABC building XYZ Area near PQRS , 354408", - "hasPurchased": "yes", - "email": "abc@xyz.com", - "title": "Mr", - "phone": "9876543212", - "state": "Uttar Pradesh", - "zipcode": "243001", - "prospectOrCustomer": "Prospect", - "country": "India", - "website": "abc.com", - "subscriptionStatus": "New" - } - }, - "messageId": "25ea6605-c788-4cab-8fed-2cf0b831c4a8", - "originalTimestamp": "2020-02-02T00:23:09.544Z", - "receivedAt": "2022-08-17T10:40:21.162+05:30", - "request_ip": "[::1]", - "rudderId": "daf823fb-e8d3-413a-8313-d34cd756f968", - "sentAt": "2022-08-17T10:40:21.728+05:30", - "timestamp": "2020-02-02T05:53:08.977+05:30", - "type": "track", - "userId": "identified user id" + "output": { + "error": "Configuration for Web Mode requires write key and region url" + } + }, + { + "description": "Error: Invalid Configs for Diapi", + "input": { + "message": { + "anonymousId": "anon-id-new", + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "traits": { + "firstName": "Anant", + "lastName": "jain", + "role": "Manager", + "address": "Flat No 58 ABC building XYZ Area near PQRS , 354408", + "hasPurchased": "yes", + "email": "abc@xyz.com", + "title": "Mr", + "phone": "9876543212", + "state": "Uttar Pradesh", + "zipcode": "243001", + "prospectOrCustomer": "Prospect", + "country": "India", + "website": "abc.com", + "subscriptionStatus": "New" + } + }, + "messageId": "25ea6605-c788-4cab-8fed-2cf0b831c4a8", + "originalTimestamp": "2020-02-02T00:23:09.544Z", + "receivedAt": "2022-08-17T10:40:21.162+05:30", + "request_ip": "[::1]", + "rudderId": "daf823fb-e8d3-413a-8313-d34cd756f968", + "sentAt": "2022-08-17T10:40:21.728+05:30", + "timestamp": "2020-02-02T05:53:08.977+05:30", + "type": "track", + "userId": "identified user id" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "", + "pl": "", + "passKey": "1234", + "apiKey": "", + "diapi": "https://crux.lemnisk.co/v3/data", + "cloudMode": "server", + "srcId": "1", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "", - "pl": "", - "passKey": "1234", - "apiKey": "", - "diapi": "https://crux.lemnisk.co/v3/data", - "cloudMode": "server", - "srcId": "1", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" }, - "output": { - "error": "Configuration for Server Mode requires Api key, Pass Key and region url" - } + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": "Diapi Platform: Track Call", - "input": { - "message": { - "type": "track", - "properties": { - "product_id": "ab1234", - "rating": 3, - "review_body": "Average product, expected much more.", - "review_id": "12345" - }, - "event": "Product Reviewed", - "context": { - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "2.9.1" - }, - "traits": { - "email": "a@example.com" - }, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" - }, - "timestamp": "2020-02-02T00:23:09.544Z", - "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383", - "userId": "user123" - }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "", - "pl": "", - "passKey": "1234", - "apiKey": "abcd", - "diapi": "https://crux.lemnisk.co/v3/data", - "cloudMode": "server", - "srcId": "1", - "diapiWriteKey": "diapi_write_key" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "output": { + "error": "Configuration for Server Mode requires Api key, Pass Key and region url" + } + }, + { + "description": "Diapi Platform: Track Call", + "input": { + "message": { + "type": "track", + "properties": { + "product_id": "ab1234", + "rating": 3, + "review_body": "Average product, expected much more.", + "review_id": "12345" }, - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://crux.lemnisk.co/v3/data", - "headers": { - "Content-Type": "application/json", - "x-api-passKey": "1234", - "x-api-key": "abcd" - }, - "params": {}, - "body": { - "JSON": { - "type": "track", - "properties": { - "product_id": "ab1234", - "rating": 3, - "review_body": "Average product, expected much more.", - "review_id": "12345" - }, - "WriteKey":"diapi_write_key", - "eventname": "Product Reviewed", - "userId": "user123", - "email": "a@example.com", - "srcid": "1" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + "event": "Product Reviewed", + "context": { + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "2.9.1" + }, + "traits": { + "email": "a@example.com" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" + }, + "timestamp": "2020-02-02T00:23:09.544Z", + "messageId": "1578564113557-af022c68-429e-4af4-b99b-2b9174056383", + "userId": "user123" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "", + "pl": "", + "passKey": "1234", + "apiKey": "abcd", + "diapi": "https://crux.lemnisk.co/v3/data", + "cloudMode": "server", + "srcId": "1", + "diapiWriteKey": "diapi_write_key" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "files": {}, - "userId": "user123" - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": "Error: Message type not supported", - "input": { - "message": { - "anonymousId": "anon-id-new", - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - }, - "traits": { - "state": "uttar pradesh" - } - }, - "messageId": "25ea6605-c788-4cab-8fed-2cf0b831c4a8", - "originalTimestamp": "2020-02-02T00:23:09.544Z", - "receivedAt": "2022-08-17T10:40:21.162+05:30", - "request_ip": "[::1]", - "rudderId": "daf823fb-e8d3-413a-8313-d34cd756f968", - "sentAt": "2022-08-17T10:40:21.728+05:30", - "timestamp": "2020-02-02T05:53:08.977+05:30", - "userId": "identified user id", - "type": "Alias" + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://crux.lemnisk.co/v3/data", + "headers": { + "Content-Type": "application/json", + "x-api-passKey": "1234", + "x-api-key": "abcd" + }, + "params": {}, + "body": { + "JSON": { + "type": "track", + "properties": { + "product_id": "ab1234", + "rating": 3, + "review_body": "Average product, expected much more.", + "review_id": "12345" + }, + "WriteKey": "diapi_write_key", + "eventname": "Product Reviewed", + "userId": "user123", + "email": "a@example.com", + "srcid": "1" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "user123" + } + }, + { + "description": "Error: Message type not supported", + "input": { + "message": { + "anonymousId": "anon-id-new", + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + }, + "traits": { + "state": "uttar pradesh" + } + }, + "messageId": "25ea6605-c788-4cab-8fed-2cf0b831c4a8", + "originalTimestamp": "2020-02-02T00:23:09.544Z", + "receivedAt": "2022-08-17T10:40:21.162+05:30", + "request_ip": "[::1]", + "rudderId": "daf823fb-e8d3-413a-8313-d34cd756f968", + "sentAt": "2022-08-17T10:40:21.728+05:30", + "timestamp": "2020-02-02T05:53:08.977+05:30", + "userId": "identified user id", + "type": "Alias" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" }, - "output": { - "error": "Event type alias is not supported in Web Cloud Mode" - } + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": " Page Call -> pl Platform ", - "input": { - "message": { - "anonymousId": "anon-id-new", - "channel": "mobile", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - }, - "name": "Home", - "category": "Profile", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "page" + "output": { + "error": "Event type alias is not supported in Web Cloud Mode" + } + }, + { + "description": " Page Call -> pl Platform ", + "input": { + "message": { + "anonymousId": "anon-id-new", + "channel": "mobile", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" + }, + "page": { + "referrer": "google.com" + }, + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" + }, + "os": { + "name": "Android", + "version": "9" + }, + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + }, + "name": "Home", + "category": "Profile", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-28T19:53:31.900Z", + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "receivedAt": "2020-09-29T14:50:43.005+05:30", + "sentAt": "2020-09-28T19:53:44.998Z", + "timestamp": "2020-09-29T14:50:29.907+05:30", + "type": "page" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" }, - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", - "headers": { - "Content-Type": "application/json" + "rootStore": null, + "isProcessorEnabled": true + } + }, + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "type": "page", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" }, - "params": {}, - "body": { - "JSON": { - "type": "page", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": { - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - } - }, - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "name": "Home", - "id": "anon-id-new", - "userId": "anon-id-new", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "writeKey": "pl_writeKey" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + "page": { + "referrer": "google.com" }, - "files": {}, - "userId": "anon-id-new" - } - }, - { - "description": " Identify Call -> pl Platform ", - "input": { - "message": { - "anonymousId": "anon-id-new", - "channel": "mobile", - "context": { - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - }, - "event": "Visited Home", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "traits": { - "name": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "identify" + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" + }, + "os": { + "name": "Android", + "version": "9" + }, + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true + "userAgent": { + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" } + }, + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "name": "Home", + "id": "anon-id-new", + "userId": "anon-id-new", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "writeKey": "pl_writeKey" }, - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", - "headers": { - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "type": "identify", - "context": { - "userAgent": { - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - } - }, - "customerProperties": { - "name": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "id": "anon-id-new", - "userId": "anon-id-new", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "writeKey": "pl_writeKey" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + } + }, + { + "description": " Identify Call -> pl Platform ", + "input": { + "message": { + "anonymousId": "anon-id-new", + "channel": "mobile", + "context": { + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + }, + "event": "Visited Home", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-28T19:53:31.900Z", + "traits": { + "name": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "receivedAt": "2020-09-29T14:50:43.005+05:30", + "sentAt": "2020-09-28T19:53:44.998Z", + "timestamp": "2020-09-29T14:50:29.907+05:30", + "type": "identify" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] }, - "files": {}, - "userId": "anon-id-new" - } + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + } }, - { - "description": " Track Call -> pl Platform ", - "input": { - "message": { - "anonymousId": "anon-id-new", - "channel": "mobile", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - }, - "event": "Visited Home", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "track" - }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "type": "identify", + "context": { + "userAgent": { + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" } + }, + "customerProperties": { + "name": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "id": "anon-id-new", + "userId": "anon-id-new", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "writeKey": "pl_writeKey" }, - "output": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", - "headers": { - "Content-Type": "application/json" + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + } + }, + { + "description": " Track Call -> pl Platform ", + "input": { + "message": { + "anonymousId": "anon-id-new", + "channel": "mobile", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" + }, + "page": { + "referrer": "google.com" + }, + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" + }, + "os": { + "name": "Android", + "version": "9" + }, + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + }, + "event": "Visited Home", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-28T19:53:31.900Z", + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "receivedAt": "2020-09-29T14:50:43.005+05:30", + "sentAt": "2020-09-28T19:53:44.998Z", + "timestamp": "2020-09-29T14:50:29.907+05:30", + "type": "track" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + } + }, + "output": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "type": "track", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" }, - "params": {}, - "body": { - "JSON": { - "type": "track", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": { - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - } - }, - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "event": "Visited Home", - "id": "anon-id-new", - "userId": "anon-id-new", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "writeKey": "pl_writeKey" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + "page": { + "referrer": "google.com" }, - "files": {}, - "userId": "anon-id-new" - } + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" + }, + "os": { + "name": "Android", + "version": "9" + }, + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" + }, + "userAgent": { + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + } + }, + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "event": "Visited Home", + "id": "anon-id-new", + "userId": "anon-id-new", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "writeKey": "pl_writeKey" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/lemnisk_router.json b/test/__tests__/data/lemnisk_router.json index 35bea2115a43..8599a3644513 100644 --- a/test/__tests__/data/lemnisk_router.json +++ b/test/__tests__/data/lemnisk_router.json @@ -1,693 +1,639 @@ [ - { - "description": "Lemnisk batch events", - "input": [ - { - "message": { - "anonymousId": "anon-id-new", - "context": { - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "type": "identify" - }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "", - "pl": "https://crux.lemnisk.co/v2/data", - "passKey": "", - "apiKey": "", - "diapi": " ", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - }, - "metadata": { - "jobId": 1 - } + { + "description": "Lemnisk batch events", + "input": [ + { + "message": { + "anonymousId": "anon-id-new", + "context": { + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "type": "identify" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "", + "pl": "https://crux.lemnisk.co/v2/data", + "passKey": "", + "apiKey": "", + "diapi": " ", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] }, - { - "message": { - "anonymousId": "anon-id-new", - "channel": "mobile", - "context": { - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - }, - "event": "Visited Home", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "traits": { - "name": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "identify" - }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - }, - "metadata": { - "anonymousId": "12345", - "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", - "destinationType": "DISCORD", - "jobId": 123, - "messageId": "4aaecff2-a513-4bbf-9824-c471f4ac9777", - "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" - } + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": { + "jobId": 1 + } + }, + { + "message": { + "anonymousId": "anon-id-new", + "channel": "mobile", + "context": { + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + }, + "event": "Visited Home", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "traits": { + "name": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "receivedAt": "2020-09-29T14:50:43.005+05:30", + "sentAt": "2020-09-28T19:53:44.998Z", + "timestamp": "2020-09-29T14:50:29.907+05:30", + "type": "identify" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] }, - { - "message": { - "anonymousId": "anon-id-new", - "channel": "mobile", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - }, - "event": "Visited Home", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "track" - }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true - }, - "metadata": { - "anonymousId": "00000000000000000000000000", - "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", - "destinationType": "DISCORD", - "jobId": 129, - "messageId": "8b8d5937-09bc-49dc-a35e-8cd6370575f8", - "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": { + "anonymousId": "12345", + "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", + "destinationType": "DISCORD", + "jobId": 123, + "messageId": "4aaecff2-a513-4bbf-9824-c471f4ac9777", + "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" + } + }, + { + "message": { + "anonymousId": "anon-id-new", + "channel": "mobile", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" + }, + "page": { + "referrer": "google.com" + }, + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" + }, + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" + }, + "os": { + "name": "Android", + "version": "9" + }, + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" + }, + "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + }, + "event": "Visited Home", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-28T19:53:31.900Z", + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "receivedAt": "2020-09-29T14:50:43.005+05:30", + "sentAt": "2020-09-28T19:53:44.998Z", + "timestamp": "2020-09-29T14:50:29.907+05:30", + "type": "track" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": { + "anonymousId": "00000000000000000000000000", + "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", + "destinationType": "DISCORD", + "jobId": 129, + "messageId": "8b8d5937-09bc-49dc-a35e-8cd6370575f8", + "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" + } + } + ], + "output": [ + { + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "", + "pl": "https://crux.lemnisk.co/v2/data", + "passKey": "", + "apiKey": "", + "diapi": " ", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": [ + { + "jobId": 1 + } + ], + "statTags": { + "errorCategory": "dataValidation", + "errorType": "configuration" + }, + "batched": false, + "statusCode": 400, + "error": "Configuration for Web Mode requires write key and region url" + }, + { + "batchedRequest": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "type": "identify", + "context": { + "userAgent": { + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" } - } + }, + "customerProperties": { + "name": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "id": "anon-id-new", + "userId": "anon-id-new", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "writeKey": "pl_writeKey" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": [ + { + "anonymousId": "12345", + "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", + "destinationType": "DISCORD", + "jobId": 123, + "messageId": "4aaecff2-a513-4bbf-9824-c471f4ac9777", + "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" + } ], - "output": [ - { - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "", - "pl": "https://crux.lemnisk.co/v2/data", - "passKey": "", - "apiKey": "", - "diapi": " ", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true + "batched": false, + "statusCode": 200 + }, + { + "batchedRequest": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", + "headers": { + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "type": "track", + "context": { + "app": { + "build": "4", + "name": "RuddCDN" }, - "metadata": [ - { - "jobId": 1 - } - ], - "statTags": { - "errorCategory": "dataValidation", - "errorType": "configuration" + "page": { + "referrer": "google.com" }, - "batched": false, - "statusCode": 400, - "error": "Configuration for Web Mode requires write key and region url" - }, - { - "batchedRequest": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", - "headers": { - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "type": "identify", - "context": { - "userAgent": { - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - } - }, - "customerProperties": { - "name": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "id": "anon-id-new", - "userId": "anon-id-new", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "writeKey": "pl_writeKey" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "anon-id-new" + "device": { + "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", + "name": "generic_x86_arm" }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true + "library": { + "name": "com.rudderstack.android.sdk.core", + "version": "1.0.6" }, - "metadata": [ - { - "anonymousId": "12345", - "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", - "destinationType": "DISCORD", - "jobId": 123, - "messageId": "4aaecff2-a513-4bbf-9824-c471f4ac9777", - "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" - } - ], - "batched": false, - "statusCode": 200 - }, - { - "batchedRequest": { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "http://10.11.36.17:8080/analyze/analyze.php", - "headers": { - "Content-Type": "application/json" - }, - "params": {}, - "body": { - "JSON": { - "type": "track", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "page": { - "referrer": "google.com" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "customProp": "customValue" - }, - "userAgent": { - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" - } - }, - "properties": { - "title": "Home | RudderStack", - "url": "http://www.rudderstack.com" - }, - "event": "Visited Home", - "id": "anon-id-new", - "userId": "anon-id-new", - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-29T14:50:29.907+05:30", - "writeKey": "pl_writeKey" - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {}, - "userId": "anon-id-new" + "os": { + "name": "Android", + "version": "9" }, - "destination": { - "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", - "name": "Lemnisk Marketing Automation", - "enabled": true, - "Config": { - "plWriteKey": "pl_writeKey", - "pl": "http://10.11.36.17:8080/analyze/analyze.php", - "passKey": "", - "apiKey": "", - "diapi": "", - "cloudMode": "web", - "srcId": "", - "diapiWriteKey": "" - }, - "destinationDefinition": { - "config": { - "transformAt": "processor", - "transformAtV1": "processor", - "saveDestinationResponse": true, - "includeKeys": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "srcId" - ], - "excludeKeys": [], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative", - "flutter", - "cordova", - "warehouse" - ], - "supportedMessageTypes": [ - "track", - "identify", - "page" - ], - "destConfig": { - "defaultConfig": [ - "apiKey", - "passKey", - "cloudMode", - "diapi", - "pl", - "diapiWriteKey", - "plWriteKey", - "deviceModeWriteKey", - "srcId" - ] - }, - "secretKeys": [ - "apiKey", - "passKey", - "plWriteKey", - "diapiWriteKey" - ] - }, - "responseRules": null, - "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", - "name": "LEMNISK_MARKETING_AUTOMATION", - "displayName": "Lemnisk Marketing Automation", - "createdAt": "2022-12-12T21:58:08.637Z" - }, - "rootStore": null, - "isProcessorEnabled": true + "timezone": "Asia/Kolkata", + "traits": { + "customProp": "customValue" }, - "metadata": [ - { - "anonymousId": "00000000000000000000000000", - "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", - "destinationType": "DISCORD", - "jobId": 129, - "messageId": "8b8d5937-09bc-49dc-a35e-8cd6370575f8", - "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" - } - ], - "batched": false, - "statusCode": 200 - } - ] - } -] \ No newline at end of file + "userAgent": { + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + } + }, + "properties": { + "title": "Home | RudderStack", + "url": "http://www.rudderstack.com" + }, + "event": "Visited Home", + "id": "anon-id-new", + "userId": "anon-id-new", + "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", + "originalTimestamp": "2020-09-29T14:50:29.907+05:30", + "writeKey": "pl_writeKey" + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "userId": "anon-id-new" + }, + "destination": { + "id": "2JAdls99p6UxoFNSKGwvh0aIt7E", + "name": "Lemnisk Marketing Automation", + "enabled": true, + "Config": { + "plWriteKey": "pl_writeKey", + "pl": "http://10.11.36.17:8080/analyze/analyze.php", + "passKey": "", + "apiKey": "", + "diapi": "", + "cloudMode": "web", + "srcId": "", + "diapiWriteKey": "" + }, + "destinationDefinition": { + "config": { + "transformAt": "processor", + "transformAtV1": "processor", + "saveDestinationResponse": true, + "includeKeys": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "srcId" + ], + "excludeKeys": [], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "reactnative", + "flutter", + "cordova", + "warehouse" + ], + "supportedMessageTypes": ["track", "identify", "page"], + "destConfig": { + "defaultConfig": [ + "apiKey", + "passKey", + "cloudMode", + "diapi", + "pl", + "diapiWriteKey", + "plWriteKey", + "deviceModeWriteKey", + "srcId" + ] + }, + "secretKeys": ["apiKey", "passKey", "plWriteKey", "diapiWriteKey"] + }, + "responseRules": null, + "id": "1j9dYVEplxUC5swbXkpK9fYT7uk", + "name": "LEMNISK_MARKETING_AUTOMATION", + "displayName": "Lemnisk Marketing Automation", + "createdAt": "2022-12-12T21:58:08.637Z" + }, + "rootStore": null, + "isProcessorEnabled": true + }, + "metadata": [ + { + "anonymousId": "00000000000000000000000000", + "destinationId": "1ZQVSU9SXNg6KYgZALaqjAO3PIL", + "destinationType": "DISCORD", + "jobId": 129, + "messageId": "8b8d5937-09bc-49dc-a35e-8cd6370575f8", + "sourceId": "1YhwKyDcKstudlGxkeN5p2wgsrp" + } + ], + "batched": false, + "statusCode": 200 + } + ] + } +] diff --git a/test/__tests__/data/mautic_router_input.json b/test/__tests__/data/mautic_router_input.json index eddc60336dbf..cb8a44c189c0 100644 --- a/test/__tests__/data/mautic_router_input.json +++ b/test/__tests__/data/mautic_router_input.json @@ -123,4 +123,4 @@ "jobId": 3 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/monday.json b/test/__tests__/data/monday.json index c7fd615429f2..0feb20d374bd 100644 --- a/test/__tests__/data/monday.json +++ b/test/__tests__/data/monday.json @@ -1020,4 +1020,4 @@ "error": "The board with boardId 339283934 does not exist" } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/personalize_input.json b/test/__tests__/data/personalize_input.json index 723b12a5c584..6fd6e052f305 100644 --- a/test/__tests__/data/personalize_input.json +++ b/test/__tests__/data/personalize_input.json @@ -2882,19 +2882,8 @@ "excludeKeys": [], "includeKeys": [], "saveDestinationResponse": true, - "secretKeys": [ - "accessKeyId", - "secretAccessKey" - ], - "supportedSourceTypes": [ - "android", - "ios", - "web", - "unity", - "amp", - "cloud", - "reactnative" - ], + "secretKeys": ["accessKeyId", "secretAccessKey"], + "supportedSourceTypes": ["android", "ios", "web", "unity", "amp", "cloud", "reactnative"], "transformAt": "processor" } }, diff --git a/test/__tests__/data/profitwell_output.json b/test/__tests__/data/profitwell_output.json index 04be6d990fec..96e66db738ab 100644 --- a/test/__tests__/data/profitwell_output.json +++ b/test/__tests__/data/profitwell_output.json @@ -27,7 +27,7 @@ "status": "active", "value": "23", "user_alias": "sp_245", - "effective_date": 1630917906 + "effective_date": 1609748704 }, "JSON_ARRAY": {}, "XML": {}, diff --git a/test/__tests__/data/redis/redisConnector.json b/test/__tests__/data/redis/redisConnector.json index f9960153347d..48cc0069cd02 100644 --- a/test/__tests__/data/redis/redisConnector.json +++ b/test/__tests__/data/redis/redisConnector.json @@ -1,20 +1,18 @@ [ - { - "description": "Get Value error", - "input": { - "value": "error" - }, - "output": { - "error": "Error getting value from Redis: Error: Connection is Closed" - } - + { + "description": "Get Value error", + "input": { + "value": "error" }, - { - "description": "Get Value Successfull", - "input": { - "value": "redis_test_get" - }, - "output": "\"redis_test_get_value\"" - + "output": { + "error": "Error getting value from Redis: Error: Connection is Closed" } -] \ No newline at end of file + }, + { + "description": "Get Value Successfull", + "input": { + "value": "redis_test_get" + }, + "output": "\"redis_test_get_value\"" + } +] diff --git a/test/__tests__/data/redis/shopify_source.json b/test/__tests__/data/redis/shopify_source.json index 7ced639ad2b6..4f64bb9bf9a0 100644 --- a/test/__tests__/data/redis/shopify_source.json +++ b/test/__tests__/data/redis/shopify_source.json @@ -1,1131 +1,1111 @@ [ - { - "description": "Track Call -> carts_create with invalid cartToken", - "input": { - "id": "shopify_test3", - "query_parameters": { - "topic": [ - "carts_create" - ] - }, - "token": "shopify_test3", - "line_items": [], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" + { + "description": "Track Call -> carts_create with invalid cartToken", + "input": { + "id": "shopify_test3", + "query_parameters": { + "topic": ["carts_create"] + }, + "token": "shopify_test3", + "line_items": [], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" + }, + "output": { + "anonymousId": "2cc03982fec47ef7ca76b4e028c375a51879", + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" + }, + "topic": "carts_create" + }, + "event": "Cart Create", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "id": "shopify_test3", + "note": null, + "products": [], + "token": "shopify_test3", + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "Track Call -> orders_delete with invalid cartToken", + "input": { + "id": "shopify_test3", + "query_parameters": { + "topic": ["orders_delete"] + }, + "line_items": [], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" + }, + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" + }, + "topic": "orders_delete" + }, + "event": "Order Deleted", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "userId": "shopify-admin", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "id": "shopify_test3", + "note": null, + "products": [], + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "Track Call -> checkouts_delete with invalid cartToken", + "input": { + "id": "shopify_test3", + "query_parameters": { + "topic": ["checkouts_delete"] + }, + "line_items": [], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" + }, + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" }, - "output": { - "anonymousId": "2cc03982fec47ef7ca76b4e028c375a51879", - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "carts_create" + "topic": "checkouts_delete" + }, + "event": "Checkout Deleted", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "userId": "shopify-admin", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "id": "shopify_test3", + "note": null, + "products": [], + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "Track Call -> carts_update", + "input": { + "user_id": "rudder01", + "id": "shopify_test_cart", + "query_parameters": { + "topic": ["carts_update"] + }, + "token": "shopify_test_cart", + "email": "test@rudderstack.com", + "line_items": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant_id": 44323300999443, + "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "sku": "", + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "vendor": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "event": "Cart Create", - "integrations": { - "SHOPIFY": true + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "type": "track", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "id": "shopify_test3", - "note": null, - "products": [], - "token": "shopify_test3", - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" } - } - }, - { - "description": "Track Call -> orders_delete with invalid cartToken", - "input": { - "id": "shopify_test3", - "query_parameters": { - "topic": [ - "orders_delete" - ] + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "line_items": [], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" - }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "orders_delete" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "event": "Order Deleted", - "integrations": { - "SHOPIFY": true + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" }, - "type": "track", - "userId":"shopify-admin", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "id": "shopify_test3", - "note": null, - "products": [], - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" } + } } + ], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" }, - { - "description": "Track Call -> checkouts_delete with invalid cartToken", - "input": { - "id": "shopify_test3", - "query_parameters": { - "topic": [ - "checkouts_delete" - ] - }, - "line_items": [], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" + "output": { + "userId": "rudder01", + "anonymousId": "anon_shopify_test1", + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "checkouts_delete" + "integration": { + "name": "SHOPIFY" + }, + "topic": "carts_update" + }, + "event": "Cart Update", + "integrations": { + "SHOPIFY": true + }, + "traits": { + "email": "test@rudderstack.com" + }, + "type": "track", + "properties": { + "note": null, + "created_at": "2023-02-10T12:05:04.402Z", + "email": "test@rudderstack.com", + "id": "shopify_test_cart", + "products": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant": "44323300999443 ", + "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "brand": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "event": "Checkout Deleted", - "integrations": { - "SHOPIFY": true + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "type": "track", - "userId":"shopify-admin", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "id": "shopify_test3", - "note": null, - "products": [], - "updated_at": "2023-02-10T12:16:07.251Z" + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } } - } + } + ], + "user_id": "rudder01", + "token": "shopify_test_cart", + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "Track Call -> orders_updated with empty line_items", + "input": { + "id": "shopify_test2", + "query_parameters": { + "topic": ["orders_updated"] + }, + "shipping_address": "abc", + "billing_address": "abc", + "customer": { + "first_name": "Test", + "last_name": "Person" + }, + "cart_token": null, + "checkout_id": 36601802719507, + "checkout_token": "checkout token", + "client_details": { + "accept_language": null, + "browser_height": null, + "browser_ip": "122.161.73.113", + "user_agent": "Mozilla/5.0 User Agent" + }, + "line_items": [], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" }, - { - "description": "Track Call -> carts_update", - "input": { - "user_id": "rudder01", - "id": "shopify_test_cart", - "query_parameters": { - "topic": [ - "carts_update" - ] - }, - "token": "shopify_test_cart", - "email": "test@rudderstack.com", - "line_items": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant_id": 44323300999443, - "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "sku": "", - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "vendor": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" + "output": { + "userId": "shopify-admin", + "context": { + "cart_token": null, + "checkout_token": "checkout token", + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "userId": "rudder01", - "anonymousId": "anon_shopify_test1", - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "carts_update" - }, - "event": "Cart Update", - "integrations": { - "SHOPIFY": true + "integration": { + "name": "SHOPIFY" + }, + "topic": "orders_updated" + }, + "event": "Order Updated", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "checkout_id": 36601802719507, + "checkout_token": "checkout token", + "client_details": { + "accept_language": null, + "browser_height": null, + "browser_ip": "122.161.73.113", + "user_agent": "Mozilla/5.0 User Agent" + }, + "order_id": "shopify_test2", + "created_at": "2023-02-10T12:05:04.402Z", + "products": [], + "updated_at": "2023-02-10T12:16:07.251Z" + }, + "traits": { + "shippingAddress": "abc", + "billingAddress": "abc", + "firstName": "Test", + "lastName": "Person" + }, + "timestamp": "2023-02-10T12:16:07.251Z" + } + }, + { + "description": "Track Call -> fullfillments_create", + "input": { + "query_parameters": { + "topic": ["fulfillments_create"] + }, + "order_id": "random", + "status": "success", + "created_at": "2023-02-10T07:44:06-05:00", + "service": "manual", + "updated_at": "2023-02-10T07:44:06-05:00", + "tracking_company": null, + "shipment_status": null, + "location_id": 77735330067, + "origin_address": null, + "destination": null, + "line_items": [ + { + "variant_id": "variantId", + "title": "bitter cloud", + "quantity": 1, + "sku": "", + "variant_title": null, + "vendor": "testAnant", + "fulfillment_service": "manual", + "product_id": 8100634689811, + "requires_shipping": true, + "taxable": true, + "gift_card": false, + "name": "bitter cloud", + "variant_inventory_management": null, + "properties": [], + "product_exists": true, + "fulfillable_quantity": 0, + "grams": 0, + "price": "9.54", + "total_discount": "0.00", + "fulfillment_status": "fulfilled", + "price_set": { + "shop_money": { + "amount": "9.54", + "currency_code": "GBP" }, - "traits": { - "email": "test@rudderstack.com" + "presentment_money": { + "amount": "9.54", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.00", + "currency_code": "GBP" }, - "type": "track", - "properties": { - "note": null, - "created_at": "2023-02-10T12:05:04.402Z", - "email":"test@rudderstack.com", - "id": "shopify_test_cart", - "products": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant": "44323300999443 ", - "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "brand": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "user_id":"rudder01", - "token": "shopify_test_cart", - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "0.00", + "currency_code": "GBP" } + }, + "discount_allocations": [], + "duties": [], + "shopify-admin_graphql_api_id": "gid://shopify/LineItem/13729348059411", + "tax_lines": [] } + ], + "tracking_number": null, + "tracking_numbers": [], + "tracking_url": null, + "tracking_urls": [], + "receipt": {}, + "name": "#1001.1", + "shopify-admin_graphql_api_id": "gid://shopify/Fulfillment/4655820210451" }, - { - "description": "Track Call -> orders_updated with empty line_items", - "input": { - "id": "shopify_test2", - "query_parameters": { - "topic": [ - "orders_updated" - ] - }, - "shipping_address": "abc", - "billing_address": "abc", - "customer": { - "first_name": "Test", - "last_name": "Person" + "output": { + "userId": "shopify-admin", + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" + }, + "topic": "fulfillments_create" + }, + "event": "Fulfillments Create", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "shopify-admin_graphql_api_id": "gid://shopify/Fulfillment/4655820210451", + "created_at": "2023-02-10T07:44:06-05:00", + "destination": null, + "location_id": 77735330067, + "name": "#1001.1", + "order_id": "random", + "origin_address": null, + "products": [ + { + "shopify-admin_graphql_api_id": "gid://shopify/LineItem/13729348059411", + "quantity": 1, + "product_exists": true, + "title": "bitter cloud", + "product_id": 8100634689811, + "properties": [], + "requires_shipping": true, + "tax_lines": [], + "variant": "variantId ", + "variant_inventory_management": null, + "price": "9.54", + "taxable": true, + "total_discount": "0.00", + "brand": "testAnant", + "fulfillable_quantity": 0, + "fulfillment_service": "manual", + "fulfillment_status": "fulfilled", + "gift_card": false, + "grams": 0, + "discount_allocations": [], + "duties": [], + "price_set": { + "shop_money": { + "amount": "9.54", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "9.54", + "currency_code": "GBP" + } }, - "cart_token": null, - "checkout_id": 36601802719507, - "checkout_token": "checkout token", - "client_details": { - "accept_language": null, - "browser_height": null, - "browser_ip": "122.161.73.113", - "user_agent": "Mozilla/5.0 User Agent" + "total_discount_set": { + "shop_money": { + "amount": "0.00", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.00", + "currency_code": "GBP" + } + } + } + ], + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": null, + "tracking_number": null, + "tracking_numbers": [], + "tracking_url": null, + "tracking_urls": [], + "updated_at": "2023-02-10T07:44:06-05:00" + } + } + }, + { + "description": "Track Call -> checkouts_update ", + "input": { + "id": "shopify_test2", + "query_parameters": { + "topic": ["checkouts_update"] + }, + "token": "shopify_test2", + "cart_token": "shopify_test2", + "line_items": [ + { + "id": 44323300999443, + "token": "shopify_test2", + "properties": null, + "quantity": 1, + "variant_id": 44323300999443, + "key": "44323300999443:ky", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "sku": "", + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "vendor": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "line_items": [], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" - }, - "output": { - "userId": "shopify-admin", - "context": { - "cart_token": null, - "checkout_token": "checkout token", - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "orders_updated" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "event": "Order Updated", - "integrations": { - "SHOPIFY": true + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "type": "track", - "properties": { - "checkout_id": 36601802719507, - "checkout_token": "checkout token", - "client_details": { - "accept_language": null, - "browser_height": null, - "browser_ip": "122.161.73.113", - "user_agent": "Mozilla/5.0 User Agent" - }, - "order_id": "shopify_test2", - "created_at": "2023-02-10T12:05:04.402Z", - "products": [], - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "traits": { - "shippingAddress": "abc", - "billingAddress": "abc", - "firstName": "Test", - "lastName": "Person" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" }, - "timestamp": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } + } } + ], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" }, - { - "description": "Track Call -> fullfillments_create", - "input": { - "query_parameters": { - "topic": [ - "fulfillments_create" - ] - }, - "order_id": "random", - "status": "success", - "created_at": "2023-02-10T07:44:06-05:00", - "service": "manual", - "updated_at": "2023-02-10T07:44:06-05:00", - "tracking_company": null, - "shipment_status": null, - "location_id": 77735330067, - "origin_address": null, - "destination": null, - "line_items": [ - { - "variant_id": "variantId", - "title": "bitter cloud", - "quantity": 1, - "sku": "", - "variant_title": null, - "vendor": "testAnant", - "fulfillment_service": "manual", - "product_id": 8100634689811, - "requires_shipping": true, - "taxable": true, - "gift_card": false, - "name": "bitter cloud", - "variant_inventory_management": null, - "properties": [], - "product_exists": true, - "fulfillable_quantity": 0, - "grams": 0, - "price": "9.54", - "total_discount": "0.00", - "fulfillment_status": "fulfilled", - "price_set": { - "shop_money": { - "amount": "9.54", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "9.54", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.00", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.00", - "currency_code": "GBP" - } - }, - "discount_allocations": [], - "duties": [], - "shopify-admin_graphql_api_id": "gid://shopify/LineItem/13729348059411", - "tax_lines": [] - } - ], - "tracking_number": null, - "tracking_numbers": [], - "tracking_url": null, - "tracking_urls": [], - "receipt": {}, - "name": "#1001.1", - "shopify-admin_graphql_api_id": "gid://shopify/Fulfillment/4655820210451" + "output": { + "anonymousId": "anon_shopify_test2", + "context": { + "cart_token": "shopify_test2", + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" }, - "output": { - "userId": "shopify-admin", - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "fulfillments_create" + "topic": "checkouts_update" + }, + "event": "Checkout Updated", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "cart_token": "shopify_test2", + "order_id": "shopify_test2", + "products": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant": "44323300999443 ", + "key": "44323300999443:ky", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "taxable": true, + "token": "shopify_test2", + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "brand": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "event": "Fulfillments Create", - "integrations": { - "SHOPIFY": true + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "type": "track", - "properties": { - "shopify-admin_graphql_api_id": "gid://shopify/Fulfillment/4655820210451", - "created_at": "2023-02-10T07:44:06-05:00", - "destination": null, - "location_id": 77735330067, - "name": "#1001.1", - "order_id": "random", - "origin_address": null, - "products": [ - { - "shopify-admin_graphql_api_id": "gid://shopify/LineItem/13729348059411", - "quantity": 1, - "product_exists": true, - "title": "bitter cloud", - "product_id": 8100634689811, - "properties": [], - "requires_shipping": true, - "tax_lines": [], - "variant": "variantId ", - "variant_inventory_management": null, - "price": "9.54", - "taxable": true, - "total_discount": "0.00", - "brand": "testAnant", - "fulfillable_quantity": 0, - "fulfillment_service": "manual", - "fulfillment_status": "fulfilled", - "gift_card": false, - "grams": 0, - "discount_allocations": [], - "duties": [], - "price_set": { - "shop_money": { - "amount": "9.54", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "9.54", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.00", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.00", - "currency_code": "GBP" - } - } - } - ], - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": null, - "tracking_number": null, - "tracking_numbers": [], - "tracking_url": null, - "tracking_urls": [], - "updated_at": "2023-02-10T07:44:06-05:00" + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } } - } - }, - { - "description": "Track Call -> checkouts_update ", - "input": { - "id": "shopify_test2", - "query_parameters": { - "topic": [ - "checkouts_update" - ] + } + ], + "token": "shopify_test2", + "updated_at": "2023-02-10T12:16:07.251Z" + }, + "timestamp": "2023-02-10T12:16:07.251Z" + } + }, + { + "description": "Track Call -> checkouts_update with null cartToken", + "input": { + "id": "shopify_test2", + "query_parameters": { + "topic": ["checkouts_update"] + }, + "cart_token": null, + "line_items": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant_id": 44323300999443, + "key": "44323300999443:ky", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "sku": "", + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "vendor": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "token": "shopify_test2", - "cart_token": "shopify_test2", - "line_items": [ - { - "id": 44323300999443, - "token": "shopify_test2", - "properties": null, - "quantity": 1, - "variant_id": 44323300999443, - "key": "44323300999443:ky", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "sku": "", - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "vendor": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" - }, - "output": { - "anonymousId": "anon_shopify_test2", - "context": { - "cart_token": "shopify_test2", - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "checkouts_update" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "event": "Checkout Updated", - "integrations": { - "SHOPIFY": true + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "type": "track", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "cart_token": "shopify_test2", - "order_id": "shopify_test2", - "products": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant": "44323300999443 ", - "key": "44323300999443:ky", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "taxable": true, - "token": "shopify_test2", - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "brand": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "token": "shopify_test2", - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" }, - "timestamp": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } + } } + ], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" }, - { - "description": "Track Call -> checkouts_update with null cartToken", - "input": { - "id": "shopify_test2", - "query_parameters": { - "topic": [ - "checkouts_update" - ] - }, - "cart_token": null, - "line_items": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant_id": 44323300999443, - "key": "44323300999443:ky", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "sku": "", - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "vendor": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" + "output": { + "userId": "shopify-admin", + "context": { + "cart_token": null, + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" }, - "output": { - "userId": "shopify-admin", - "context": { - "cart_token": null, - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "checkouts_update" + "topic": "checkouts_update" + }, + "event": "Checkout Updated", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "order_id": "shopify_test2", + "created_at": "2023-02-10T12:05:04.402Z", + "products": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant": "44323300999443 ", + "key": "44323300999443:ky", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "brand": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "event": "Checkout Updated", - "integrations": { - "SHOPIFY": true + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "type": "track", - "properties": { - "order_id": "shopify_test2", - "created_at": "2023-02-10T12:05:04.402Z", - "products": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant": "44323300999443 ", - "key": "44323300999443:ky", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "brand": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "updated_at": "2023-02-10T12:16:07.251Z" + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "timestamp": "2023-02-10T12:16:07.251Z" - } - }, - { - "description": "Track Call -> carts_update with invalid cartToken", - "input": { - "id": "shopify_test3", - "query_parameters": { - "topic": [ - "carts_update" - ] + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } }, - "token": "shopify_test3", - "line_items": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant_id": 44323300999443, - "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "sku": "", - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "vendor": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" - }, - "output": { - "anonymousId": "2cc03982fec47ef7ca76b4e028c375a51879", - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "carts_update" + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } + } + } + ], + "updated_at": "2023-02-10T12:16:07.251Z" + }, + "timestamp": "2023-02-10T12:16:07.251Z" + } + }, + { + "description": "Track Call -> carts_update with invalid cartToken", + "input": { + "id": "shopify_test3", + "query_parameters": { + "topic": ["carts_update"] + }, + "token": "shopify_test3", + "line_items": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant_id": 44323300999443, + "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "sku": "", + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "vendor": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "event": "Cart Update", - "integrations": { - "SHOPIFY": true + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "type": "track", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "id": "shopify_test3", - "note": null, - "products": [ - { - "id": 44323300999443, - "properties": null, - "quantity": 1, - "variant": "44323300999443 ", - "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", - "discounted_price": "30.00", - "discounts": [], - "gift_card": false, - "grams": 0, - "line_price": "30.00", - "original_line_price": "30.00", - "original_price": "30.00", - "price": "30.00", - "product_id": 8100575674643, - "taxable": true, - "title": "Shirt 2 - LARGE", - "total_discount": "0.00", - "brand": "testAnant", - "discounted_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "original_line_price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "price_set": { - "shop_money": { - "amount": "30.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "30.0", - "currency_code": "GBP" - } - }, - "total_discount_set": { - "shop_money": { - "amount": "0.0", - "currency_code": "GBP" - }, - "presentment_money": { - "amount": "0.0", - "currency_code": "GBP" - } - } - } - ], - "token": "shopify_test3", - "updated_at": "2023-02-10T12:16:07.251Z" + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" } - } - }, - { - "description": "Rudder Identifier Event", - "input": { - "event": "rudderIdentifier", - "anonymousId": "b9993cc5-9e60-4e69-be0e-4e38c228314b", - "cartToken": "shopify_test1", - "query_parameters": { - "writeKey": [ - "Shopify Write Key" - ] + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "cart": { - "token": "token", - "id": "id", - "updated_at": "2023-02-10T07:44:06-05:00", - "line_items": [] + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" } - }, - "output": { - "outputToSource": { - "body": "T0s=", - "contentType": "text/plain" + }, + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" }, - "statusCode": 200 + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } + } } + ], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" + }, + "output": { + "anonymousId": "2cc03982fec47ef7ca76b4e028c375a51879", + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" + }, + "integration": { + "name": "SHOPIFY" + }, + "topic": "carts_update" + }, + "event": "Cart Update", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "id": "shopify_test3", + "note": null, + "products": [ + { + "id": 44323300999443, + "properties": null, + "quantity": 1, + "variant": "44323300999443 ", + "key": "44323300999443:70b21df78d403673a8b5dbafd62f0559", + "discounted_price": "30.00", + "discounts": [], + "gift_card": false, + "grams": 0, + "line_price": "30.00", + "original_line_price": "30.00", + "original_price": "30.00", + "price": "30.00", + "product_id": 8100575674643, + "taxable": true, + "title": "Shirt 2 - LARGE", + "total_discount": "0.00", + "brand": "testAnant", + "discounted_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "original_line_price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "price_set": { + "shop_money": { + "amount": "30.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "30.0", + "currency_code": "GBP" + } + }, + "total_discount_set": { + "shop_money": { + "amount": "0.0", + "currency_code": "GBP" + }, + "presentment_money": { + "amount": "0.0", + "currency_code": "GBP" + } + } + } + ], + "token": "shopify_test3", + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "Rudder Identifier Event", + "input": { + "event": "rudderIdentifier", + "anonymousId": "b9993cc5-9e60-4e69-be0e-4e38c228314b", + "cartToken": "shopify_test1", + "query_parameters": { + "writeKey": ["Shopify Write Key"] + }, + "cart": { + "token": "token", + "id": "id", + "updated_at": "2023-02-10T07:44:06-05:00", + "line_items": [] + } + }, + "output": { + "outputToSource": { + "body": "T0s=", + "contentType": "text/plain" + }, + "statusCode": 200 } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/salesforce_proxy_output.json b/test/__tests__/data/salesforce_proxy_output.json index 690a3bdb229b..8674b03ba647 100644 --- a/test/__tests__/data/salesforce_proxy_output.json +++ b/test/__tests__/data/salesforce_proxy_output.json @@ -180,4 +180,4 @@ "status": 500 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/shopify.json b/test/__tests__/data/shopify.json index 61723567daa8..e37512236ce0 100644 --- a/test/__tests__/data/shopify.json +++ b/test/__tests__/data/shopify.json @@ -1,866 +1,809 @@ [ - { - "description": "Track Call -> carts_create with invalid cartToken", - "input": { - "id": "shopify_test3", - "query_parameters": { - "topic": [ - "carts_create" - ] - }, - "token": "shopify_test3", - "line_items": [], - "note": null, - "updated_at": "2023-02-10T12:16:07.251Z", - "created_at": "2023-02-10T12:05:04.402Z" + { + "description": "Track Call -> carts_create with invalid cartToken", + "input": { + "id": "shopify_test3", + "query_parameters": { + "topic": ["carts_create"] + }, + "token": "shopify_test3", + "line_items": [], + "note": null, + "updated_at": "2023-02-10T12:16:07.251Z", + "created_at": "2023-02-10T12:05:04.402Z" + }, + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "carts_create" - }, - "event": "Cart Create", - "integrations": { - "SHOPIFY": true - }, - "type": "track", - "properties": { - "created_at": "2023-02-10T12:05:04.402Z", - "id": "shopify_test3", - "note": null, - "products": [], - "token": "shopify_test3", - "updated_at": "2023-02-10T12:16:07.251Z" - } - } + "integration": { + "name": "SHOPIFY" + }, + "topic": "carts_create" + }, + "event": "Cart Create", + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "properties": { + "created_at": "2023-02-10T12:05:04.402Z", + "id": "shopify_test3", + "note": null, + "products": [], + "token": "shopify_test3", + "updated_at": "2023-02-10T12:16:07.251Z" + } + } + }, + { + "description": "No Query Parameters", + "input": {}, + "output": { + "error": "Query_parameters is missing" + } + }, + { + "description": "Invalid topic", + "input": { + "query_parameters": { + "signature": ["rudderstack"], + "writeKey": ["sample-write-key"] + } }, - { - "description": "No Query Parameters", - "input": {}, - "output": { - "error": "Query_parameters is missing" - } + "output": { + "error": "Invalid topic in query_parameters" + } + }, + { + "description": "Topic Not found", + "input": { + "query_parameters": { + "topic": [], + "signature": ["rudderstack"], + "writeKey": ["sample-write-key"] + } }, - { - "description": "Invalid topic", - "input": { - "query_parameters": { - "signature": [ - "rudderstack" - ], - "writeKey": [ - "sample-write-key" - ] - } - }, - "output": { - "error": "Invalid topic in query_parameters" - } + "output": { + "error": "Topic not found" + } + }, + { + "description": "Unsupported Event Type", + "input": { + "query_parameters": { + "topic": ["random_event"], + "signature": ["rudderstack"], + "writeKey": ["sample-write-key"] + } }, - { - "description": "Topic Not found", - "input": { - "query_parameters": { - "topic": [ - ], - "signature": [ - "rudderstack" - ], - "writeKey": [ - "sample-write-key" - ] - } - }, - "output": { - "error": "Topic not found" + "output": { + "error": "event type random_event not supported" + } + }, + { + "description": "Identify Call for customers create event", + "input": { + "query_parameters": { + "topic": ["customers_create"], + "signature": ["rudderstack"], + "writeKey": ["sample-write-key"] + }, + "id": 5747017285820, + "email": "anuraj@rudderstack.com", + "accepts_marketing": false, + "created_at": "2021-12-29T15:15:19+05:30", + "updated_at": "2021-12-29T15:15:20+05:30", + "first_name": "Anuraj", + "last_name": "Guha", + "orders_count": 0, + "state": "disabled", + "total_spent": "0.00", + "last_order_id": null, + "note": "", + "verified_email": true, + "multipass_identifier": null, + "tax_exempt": false, + "phone": "+919876543210", + "tags": "", + "last_order_name": null, + "currency": "INR", + "addresses": [ + { + "id": 6947581821116, + "customer_id": 5747017285820, + "first_name": "Anuraj", + "last_name": "Guha", + "company": "Rudderstack", + "address1": "Home", + "address2": "Apartment", + "city": "Kolkata", + "province": "West Bengal", + "country": "India", + "zip": "708091", + "phone": "+919876543210", + "name": "Anuraj Guha", + "province_code": "WB", + "country_code": "IN", + "country_name": "India", + "default": true } + ], + "accepts_marketing_updated_at": "2021-12-29T15:15:20+05:30", + "marketing_opt_in_level": null, + "tax_exemptions": [], + "sms_marketing_consent": { + "state": "not_subscribed", + "opt_in_level": "single_opt_in", + "consent_updated_at": null, + "consent_collected_from": "SHOPIFY" + }, + "admin_graphql_api_id": "gid://shopify/Customer/5747017285820", + "default_address": { + "id": 6947581821116, + "customer_id": 5747017285820, + "first_name": "Anuraj", + "last_name": "Guha", + "company": "Rudderstack", + "address1": "Home", + "address2": "Apartment", + "city": "Kolkata", + "province": "West Bengal", + "country": "India", + "zip": "708091", + "phone": "+919876543210", + "name": "Anuraj Guha", + "province_code": "WB", + "country_code": "IN", + "country_name": "India", + "default": true + } }, - { - "description": "Unsupported Event Type", - "input": { - "query_parameters": { - "topic": [ - "random_event" - ], - "signature": [ - "rudderstack" - ], - "writeKey": [ - "sample-write-key" - ] - } + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "error": "event type random_event not supported" - } - }, - { - "description": "Identify Call for customers create event", - "input": { - "query_parameters": { - "topic": [ - "customers_create" - ], - "signature": [ - "rudderstack" - ], - "writeKey": [ - "sample-write-key" - ] - }, - "id": 5747017285820, - "email": "anuraj@rudderstack.com", - "accepts_marketing": false, - "created_at": "2021-12-29T15:15:19+05:30", - "updated_at": "2021-12-29T15:15:20+05:30", + "integration": { + "name": "SHOPIFY" + }, + "topic": "customers_create" + }, + "integrations": { + "SHOPIFY": true + }, + "type": "identify", + "userId": "5747017285820", + "traits": { + "email": "anuraj@rudderstack.com", + "firstName": "Anuraj", + "lastName": "Guha", + "phone": "+919876543210", + "addressList": [ + { + "id": 6947581821116, + "customer_id": 5747017285820, "first_name": "Anuraj", "last_name": "Guha", - "orders_count": 0, - "state": "disabled", - "total_spent": "0.00", - "last_order_id": null, - "note": "", - "verified_email": true, - "multipass_identifier": null, - "tax_exempt": false, + "company": "Rudderstack", + "address1": "Home", + "address2": "Apartment", + "city": "Kolkata", + "province": "West Bengal", + "country": "India", + "zip": "708091", "phone": "+919876543210", - "tags": "", - "last_order_name": null, - "currency": "INR", - "addresses": [ - { - "id": 6947581821116, - "customer_id": 5747017285820, - "first_name": "Anuraj", - "last_name": "Guha", - "company": "Rudderstack", - "address1": "Home", - "address2": "Apartment", - "city": "Kolkata", - "province": "West Bengal", - "country": "India", - "zip": "708091", - "phone": "+919876543210", - "name": "Anuraj Guha", - "province_code": "WB", - "country_code": "IN", - "country_name": "India", - "default": true - } - ], - "accepts_marketing_updated_at": "2021-12-29T15:15:20+05:30", - "marketing_opt_in_level": null, - "tax_exemptions": [], - "sms_marketing_consent": { - "state": "not_subscribed", - "opt_in_level": "single_opt_in", - "consent_updated_at": null, - "consent_collected_from": "SHOPIFY" - }, - "admin_graphql_api_id": "gid://shopify/Customer/5747017285820", - "default_address": { - "id": 6947581821116, - "customer_id": 5747017285820, - "first_name": "Anuraj", - "last_name": "Guha", - "company": "Rudderstack", - "address1": "Home", - "address2": "Apartment", - "city": "Kolkata", - "province": "West Bengal", - "country": "India", - "zip": "708091", - "phone": "+919876543210", - "name": "Anuraj Guha", - "province_code": "WB", - "country_code": "IN", - "country_name": "India", - "default": true - } + "name": "Anuraj Guha", + "province_code": "WB", + "country_code": "IN", + "country_name": "India", + "default": true + } + ], + "address": { + "id": 6947581821116, + "customer_id": 5747017285820, + "first_name": "Anuraj", + "last_name": "Guha", + "company": "Rudderstack", + "address1": "Home", + "address2": "Apartment", + "city": "Kolkata", + "province": "West Bengal", + "country": "India", + "zip": "708091", + "phone": "+919876543210", + "name": "Anuraj Guha", + "province_code": "WB", + "country_code": "IN", + "country_name": "India", + "default": true }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "customers_create" - }, - "integrations": { - "SHOPIFY": true + "acceptsMarketing": false, + "orderCount": 0, + "state": "disabled", + "totalSpent": "0.00", + "note": "", + "verifiedEmail": true, + "taxExempt": false, + "tags": "", + "currency": "INR", + "taxExemptions": [], + "smsMarketingConsent": { + "state": "not_subscribed", + "opt_in_level": "single_opt_in", + "consent_updated_at": null, + "consent_collected_from": "SHOPIFY" + }, + "adminGraphqlApiId": "gid://shopify/Customer/5747017285820", + "acceptsMarketingUpdatedAt": "2021-12-29T15:15:20+05:30" + }, + "timestamp": "2021-12-29T09:45:20.000Z" + } + }, + { + "description": "Unsupported checkout event", + "input": { + "query_parameters": { + "topic": ["checkout_delete"], + "writeKey": ["sample-write-key"], + "signature": ["rudderstack"] + }, + "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", + "created_at": "2022-01-05T18:13:02+05:30", + "destination": null, + "id": 4124667937024, + "line_items": [], + "customer": { + "email": "test_person@email.com", + "first_name": "Test", + "last_name": "Person" + }, + "billing_address": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore" + }, + "shipping_address": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore" + }, + "location_id": 66855371008, + "name": "#1002.1", + "order_id": 4617255092480, + "origin_address": null, + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": "Amazon Logistics UK", + "tracking_number": "Sample001test", + "tracking_numbers": ["Sample001test"], + "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", + "tracking_urls": ["https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530"], + "updated_at": "2022-01-05T18:16:48+05:30" + }, + "output": { + "error": "event type checkout_delete not supported" + } + }, + { + "description": "Track Call -> Fullfillments updated event", + "input": { + "query_parameters": { + "topic": ["fulfillments_update"], + "writeKey": ["sample-write-key"], + "signature": ["rudderstack"] + }, + "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", + "created_at": "2022-01-05T18:13:02+05:30", + "destination": null, + "email": "test_person@email.com", + "id": 4124667937024, + "line_items": [ + { + "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", + "discount_allocations": [], + "duties": [], + "fulfillable_quantity": 0, + "fulfillment_service": "manual", + "fulfillment_status": "fulfilled", + "gift_card": false, + "grams": 0, + "id": 11896203149568, + "name": "p1", + "origin_location": { + "address1": "74 CC/7, Anupama Housing Estate - II", + "address2": "", + "city": "Kolkatta", + "country_code": "IN", + "id": 3373642219776, + "name": "74 CC/7, Anupama Housing Estate - II", + "province_code": "WB", + "zip": "700052" + }, + "price": "5000.00", + "price_set": { + "presentment_money": { + "amount": "5000.00", + "currency_code": "INR" }, - "type": "identify", - "userId": "5747017285820", - "traits": { - "email": "anuraj@rudderstack.com", - "firstName": "Anuraj", - "lastName": "Guha", - "phone": "+919876543210", - "addressList": [ - { - "id": 6947581821116, - "customer_id": 5747017285820, - "first_name": "Anuraj", - "last_name": "Guha", - "company": "Rudderstack", - "address1": "Home", - "address2": "Apartment", - "city": "Kolkata", - "province": "West Bengal", - "country": "India", - "zip": "708091", - "phone": "+919876543210", - "name": "Anuraj Guha", - "province_code": "WB", - "country_code": "IN", - "country_name": "India", - "default": true - } - ], - "address": { - "id": 6947581821116, - "customer_id": 5747017285820, - "first_name": "Anuraj", - "last_name": "Guha", - "company": "Rudderstack", - "address1": "Home", - "address2": "Apartment", - "city": "Kolkata", - "province": "West Bengal", - "country": "India", - "zip": "708091", - "phone": "+919876543210", - "name": "Anuraj Guha", - "province_code": "WB", - "country_code": "IN", - "country_name": "India", - "default": true - }, - "acceptsMarketing": false, - "orderCount": 0, - "state": "disabled", - "totalSpent": "0.00", - "note": "", - "verifiedEmail": true, - "taxExempt": false, - "tags": "", - "currency": "INR", - "taxExemptions": [], - "smsMarketingConsent": { - "state": "not_subscribed", - "opt_in_level": "single_opt_in", - "consent_updated_at": null, - "consent_collected_from": "SHOPIFY" + "shop_money": { + "amount": "5000.00", + "currency_code": "INR" + } + }, + "product_exists": true, + "product_id": 7510929801472, + "properties": [], + "quantity": 1, + "requires_shipping": true, + "sku": "15", + "tax_lines": [ + { + "channel_liable": false, + "price": "900.00", + "price_set": { + "presentment_money": { + "amount": "900.00", + "currency_code": "INR" }, - "adminGraphqlApiId": "gid://shopify/Customer/5747017285820", - "acceptsMarketingUpdatedAt": "2021-12-29T15:15:20+05:30" + "shop_money": { + "amount": "900.00", + "currency_code": "INR" + } + }, + "rate": 0.18, + "title": "IGST" + } + ], + "taxable": true, + "title": "p1", + "total_discount": "0.00", + "total_discount_set": { + "presentment_money": { + "amount": "0.00", + "currency_code": "INR" }, - "timestamp": "2021-12-29T09:45:20.000Z" + "shop_money": { + "amount": "0.00", + "currency_code": "INR" + } + }, + "variant_id": 42211160228096, + "variant_inventory_management": "shopify", + "variant_title": "", + "vendor": "rudderstack-store" } + ], + "location_id": 66855371008, + "name": "#1002.1", + "order_id": 4617255092480, + "origin_address": null, + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": "Amazon Logistics UK", + "tracking_number": "Sample001test", + "tracking_numbers": ["Sample001test"], + "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", + "tracking_urls": ["https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530"], + "updated_at": "2022-01-05T18:16:48+05:30" }, - { - "description": "Unsupported checkout event", - "input": { - "query_parameters": { - "topic": [ - "checkout_delete" - ], - "writeKey": [ - "sample-write-key" - ], - "signature": [ - "rudderstack" - ] - }, - "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", - "created_at": "2022-01-05T18:13:02+05:30", - "destination": null, - "id": 4124667937024, - "line_items": [], - "customer": { - "email": "test_person@email.com", - "first_name": "Test", - "last_name": "Person" - }, - "billing_address": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore" - }, - "shipping_address": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore" - }, - "location_id": 66855371008, - "name": "#1002.1", - "order_id": 4617255092480, - "origin_address": null, - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": "Amazon Logistics UK", - "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], - "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], - "updated_at": "2022-01-05T18:16:48+05:30" + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "error": "event type checkout_delete not supported" - } - }, - { - "description": "Track Call -> Fullfillments updated event", - "input": { - "query_parameters": { - "topic": [ - "fulfillments_update" - ], - "writeKey": [ - "sample-write-key" - ], - "signature": [ - "rudderstack" - ] - }, - "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", - "created_at": "2022-01-05T18:13:02+05:30", - "destination": null, - "email": "test_person@email.com", - "id": 4124667937024, - "line_items": [ - { - "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", - "discount_allocations": [], - "duties": [], - "fulfillable_quantity": 0, - "fulfillment_service": "manual", - "fulfillment_status": "fulfilled", - "gift_card": false, - "grams": 0, - "id": 11896203149568, - "name": "p1", - "origin_location": { - "address1": "74 CC/7, Anupama Housing Estate - II", - "address2": "", - "city": "Kolkatta", - "country_code": "IN", - "id": 3373642219776, - "name": "74 CC/7, Anupama Housing Estate - II", - "province_code": "WB", - "zip": "700052" - }, - "price": "5000.00", - "price_set": { - "presentment_money": { - "amount": "5000.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "5000.00", - "currency_code": "INR" - } - }, - "product_exists": true, - "product_id": 7510929801472, - "properties": [], - "quantity": 1, - "requires_shipping": true, - "sku": "15", - "tax_lines": [ - { - "channel_liable": false, - "price": "900.00", - "price_set": { - "presentment_money": { - "amount": "900.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "900.00", - "currency_code": "INR" - } - }, - "rate": 0.18, - "title": "IGST" - } - ], - "taxable": true, - "title": "p1", - "total_discount": "0.00", - "total_discount_set": { - "presentment_money": { - "amount": "0.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "0.00", - "currency_code": "INR" - } - }, - "variant_id": 42211160228096, - "variant_inventory_management": "shopify", - "variant_title": "", - "vendor": "rudderstack-store" - } - ], - "location_id": 66855371008, - "name": "#1002.1", - "order_id": 4617255092480, - "origin_address": null, - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": "Amazon Logistics UK", - "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], - "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], - "updated_at": "2022-01-05T18:16:48+05:30" + "integration": { + "name": "SHOPIFY" }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" + "topic": "fulfillments_update" + }, + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "userId": "shopify-admin", + "event": "Fulfillments Update", + "properties": { + "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", + "created_at": "2022-01-05T18:13:02+05:30", + "destination": null, + "email": "test_person@email.com", + "id": 4124667937024, + "location_id": 66855371008, + "name": "#1002.1", + "order_id": 4617255092480, + "origin_address": null, + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": "Amazon Logistics UK", + "tracking_number": "Sample001test", + "tracking_numbers": ["Sample001test"], + "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", + "tracking_urls": [ + "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" + ], + "updated_at": "2022-01-05T18:16:48+05:30", + "products": [ + { + "product_id": 7510929801472, + "sku": "15", + "title": "p1", + "price": "5000.00", + "brand": "rudderstack-store", + "quantity": 1, + "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", + "discount_allocations": [], + "duties": [], + "fulfillable_quantity": 0, + "fulfillment_service": "manual", + "fulfillment_status": "fulfilled", + "gift_card": false, + "grams": 0, + "id": 11896203149568, + "origin_location": { + "address1": "74 CC/7, Anupama Housing Estate - II", + "address2": "", + "city": "Kolkatta", + "country_code": "IN", + "id": 3373642219776, + "name": "74 CC/7, Anupama Housing Estate - II", + "province_code": "WB", + "zip": "700052" + }, + "price_set": { + "presentment_money": { + "amount": "5000.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "5000.00", + "currency_code": "INR" + } + }, + "product_exists": true, + "properties": [], + "requires_shipping": true, + "tax_lines": [ + { + "channel_liable": false, + "price": "900.00", + "price_set": { + "presentment_money": { + "amount": "900.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "900.00", + "currency_code": "INR" + } }, - "topic": "fulfillments_update" + "rate": 0.18, + "title": "IGST" + } + ], + "taxable": true, + "total_discount": "0.00", + "total_discount_set": { + "presentment_money": { + "amount": "0.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "0.00", + "currency_code": "INR" + } }, - "integrations": { - "SHOPIFY": true + "variant_inventory_management": "shopify", + "variant": "42211160228096 " + } + ] + }, + "traits": { + "email": "test_person@email.com" + } + } + }, + { + "description": "Track Call -> Fullfillments updated event with traits", + "input": { + "query_parameters": { + "topic": ["fulfillments_update"], + "writeKey": ["sample-write-key"], + "signature": ["rudderstack"] + }, + "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", + "created_at": "2022-01-05T18:13:02+05:30", + "destination": null, + "id": 4124667937024, + "line_items": [ + { + "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", + "discount_allocations": [], + "duties": [], + "fulfillable_quantity": 0, + "fulfillment_service": "manual", + "fulfillment_status": "fulfilled", + "gift_card": false, + "grams": 0, + "id": 11896203149568, + "name": "p1", + "origin_location": { + "address1": "74 CC/7, Anupama Housing Estate - II", + "address2": "", + "city": "Kolkatta", + "country_code": "IN", + "id": 3373642219776, + "name": "74 CC/7, Anupama Housing Estate - II", + "province_code": "WB", + "zip": "700052" + }, + "price": "5000.00", + "price_set": { + "presentment_money": { + "amount": "5000.00", + "currency_code": "INR" }, - "type": "track", - "userId": "shopify-admin", - "event": "Fulfillments Update", - "properties": { - "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", - "created_at": "2022-01-05T18:13:02+05:30", - "destination": null, - "email": "test_person@email.com", - "id": 4124667937024, - "location_id": 66855371008, - "name": "#1002.1", - "order_id": 4617255092480, - "origin_address": null, - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": "Amazon Logistics UK", - "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], - "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], - "updated_at": "2022-01-05T18:16:48+05:30", - "products": [ - { - "product_id": 7510929801472, - "sku": "15", - "title": "p1", - "price": "5000.00", - "brand": "rudderstack-store", - "quantity": 1, - "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", - "discount_allocations": [], - "duties": [], - "fulfillable_quantity": 0, - "fulfillment_service": "manual", - "fulfillment_status": "fulfilled", - "gift_card": false, - "grams": 0, - "id": 11896203149568, - "origin_location": { - "address1": "74 CC/7, Anupama Housing Estate - II", - "address2": "", - "city": "Kolkatta", - "country_code": "IN", - "id": 3373642219776, - "name": "74 CC/7, Anupama Housing Estate - II", - "province_code": "WB", - "zip": "700052" - }, - "price_set": { - "presentment_money": { - "amount": "5000.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "5000.00", - "currency_code": "INR" - } - }, - "product_exists": true, - "properties": [], - "requires_shipping": true, - "tax_lines": [ - { - "channel_liable": false, - "price": "900.00", - "price_set": { - "presentment_money": { - "amount": "900.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "900.00", - "currency_code": "INR" - } - }, - "rate": 0.18, - "title": "IGST" - } - ], - "taxable": true, - "total_discount": "0.00", - "total_discount_set": { - "presentment_money": { - "amount": "0.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "0.00", - "currency_code": "INR" - } - }, - "variant_inventory_management": "shopify", - "variant": "42211160228096 " - } - ] + "shop_money": { + "amount": "5000.00", + "currency_code": "INR" + } + }, + "product_exists": true, + "product_id": 7510929801472, + "properties": [], + "quantity": 1, + "requires_shipping": true, + "sku": "15", + "tax_lines": [ + { + "channel_liable": false, + "price": "900.00", + "price_set": { + "presentment_money": { + "amount": "900.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "900.00", + "currency_code": "INR" + } + }, + "rate": 0.18, + "title": "IGST" + } + ], + "taxable": true, + "title": "p1", + "total_discount": "0.00", + "total_discount_set": { + "presentment_money": { + "amount": "0.00", + "currency_code": "INR" }, - "traits": { - "email": "test_person@email.com" + "shop_money": { + "amount": "0.00", + "currency_code": "INR" } + }, + "variant_id": 42211160228096, + "variant_inventory_management": "shopify", + "variant_title": "", + "vendor": "rudderstack-store" } + ], + "customer": { + "email": "test_person@email.com", + "first_name": "Test", + "last_name": "Person" + }, + "billing_address": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", + "address2": "", + "city": "Kolkata", + "company": null, + "country": "India", + "country_code": "IN", + "first_name": "Utsab", + "last_name": "Chowdhury", + "latitude": null, + "longitude": null, + "name": "Utsab Chowdhury", + "phone": null, + "province": "West Bengal", + "province_code": "WB", + "zip": "700025" + }, + "shipping_address": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", + "address2": "", + "city": "Kolkata", + "company": null, + "country": "India", + "country_code": "IN", + "first_name": "Utsab", + "last_name": "Chowdhury", + "latitude": null, + "longitude": null, + "name": "Utsab Chowdhury", + "phone": null, + "province": "West Bengal", + "province_code": "WB", + "zip": "700025" + }, + "location_id": 66855371008, + "name": "#1002.1", + "order_id": 4617255092480, + "origin_address": null, + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": "Amazon Logistics UK", + "tracking_number": "Sample001test", + "tracking_numbers": ["Sample001test"], + "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", + "tracking_urls": ["https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530"], + "updated_at": "2022-01-05T18:16:48+05:30" }, - { - "description": "Track Call -> Fullfillments updated event with traits", - "input": { - "query_parameters": { - "topic": [ - "fulfillments_update" - ], - "writeKey": [ - "sample-write-key" - ], - "signature": [ - "rudderstack" - ] - }, - "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", - "created_at": "2022-01-05T18:13:02+05:30", - "destination": null, - "id": 4124667937024, - "line_items": [ - { - "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", - "discount_allocations": [], - "duties": [], - "fulfillable_quantity": 0, - "fulfillment_service": "manual", - "fulfillment_status": "fulfilled", - "gift_card": false, - "grams": 0, - "id": 11896203149568, - "name": "p1", - "origin_location": { - "address1": "74 CC/7, Anupama Housing Estate - II", - "address2": "", - "city": "Kolkatta", - "country_code": "IN", - "id": 3373642219776, - "name": "74 CC/7, Anupama Housing Estate - II", - "province_code": "WB", - "zip": "700052" - }, - "price": "5000.00", - "price_set": { - "presentment_money": { - "amount": "5000.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "5000.00", - "currency_code": "INR" - } - }, - "product_exists": true, - "product_id": 7510929801472, - "properties": [], - "quantity": 1, - "requires_shipping": true, - "sku": "15", - "tax_lines": [ - { - "channel_liable": false, - "price": "900.00", - "price_set": { - "presentment_money": { - "amount": "900.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "900.00", - "currency_code": "INR" - } - }, - "rate": 0.18, - "title": "IGST" - } - ], - "taxable": true, - "title": "p1", - "total_discount": "0.00", - "total_discount_set": { - "presentment_money": { - "amount": "0.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "0.00", - "currency_code": "INR" - } - }, - "variant_id": 42211160228096, - "variant_inventory_management": "shopify", - "variant_title": "", - "vendor": "rudderstack-store" - } - ], - "customer": { - "email": "test_person@email.com", - "first_name": "Test", - "last_name": "Person" - }, - "billing_address": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", - "address2": "", - "city": "Kolkata", - "company": null, - "country": "India", - "country_code": "IN", - "first_name": "Utsab", - "last_name": "Chowdhury", - "latitude": null, - "longitude": null, - "name": "Utsab Chowdhury", - "phone": null, - "province": "West Bengal", - "province_code": "WB", - "zip": "700025" - }, - "shipping_address": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", - "address2": "", - "city": "Kolkata", - "company": null, - "country": "India", - "country_code": "IN", - "first_name": "Utsab", - "last_name": "Chowdhury", - "latitude": null, - "longitude": null, - "name": "Utsab Chowdhury", - "phone": null, - "province": "West Bengal", - "province_code": "WB", - "zip": "700025" - }, - "location_id": 66855371008, - "name": "#1002.1", - "order_id": 4617255092480, - "origin_address": null, - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": "Amazon Logistics UK", - "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], - "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], - "updated_at": "2022-01-05T18:16:48+05:30" + "output": { + "context": { + "library": { + "name": "RudderStack Shopify Cloud", + "version": "1.0.0" }, - "output": { - "context": { - "library": { - "name": "RudderStack Shopify Cloud", - "version": "1.0.0" - }, - "integration": { - "name": "SHOPIFY" - }, - "topic": "fulfillments_update" - }, - "integrations": { - "SHOPIFY": true + "integration": { + "name": "SHOPIFY" + }, + "topic": "fulfillments_update" + }, + "integrations": { + "SHOPIFY": true + }, + "type": "track", + "event": "Fulfillments Update", + "userId": "shopify-admin", + "properties": { + "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", + "created_at": "2022-01-05T18:13:02+05:30", + "destination": null, + "id": 4124667937024, + "location_id": 66855371008, + "name": "#1002.1", + "order_id": 4617255092480, + "origin_address": null, + "receipt": {}, + "service": "manual", + "shipment_status": null, + "status": "success", + "tracking_company": "Amazon Logistics UK", + "tracking_number": "Sample001test", + "tracking_numbers": ["Sample001test"], + "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", + "tracking_urls": [ + "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" + ], + "updated_at": "2022-01-05T18:16:48+05:30", + "products": [ + { + "product_id": 7510929801472, + "sku": "15", + "title": "p1", + "price": "5000.00", + "brand": "rudderstack-store", + "quantity": 1, + "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", + "discount_allocations": [], + "duties": [], + "fulfillable_quantity": 0, + "fulfillment_service": "manual", + "fulfillment_status": "fulfilled", + "gift_card": false, + "grams": 0, + "id": 11896203149568, + "origin_location": { + "address1": "74 CC/7, Anupama Housing Estate - II", + "address2": "", + "city": "Kolkatta", + "country_code": "IN", + "id": 3373642219776, + "name": "74 CC/7, Anupama Housing Estate - II", + "province_code": "WB", + "zip": "700052" }, - "type": "track", - "event": "Fulfillments Update", - "userId": "shopify-admin", - "properties": { - "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", - "created_at": "2022-01-05T18:13:02+05:30", - "destination": null, - "id": 4124667937024, - "location_id": 66855371008, - "name": "#1002.1", - "order_id": 4617255092480, - "origin_address": null, - "receipt": {}, - "service": "manual", - "shipment_status": null, - "status": "success", - "tracking_company": "Amazon Logistics UK", - "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], - "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], - "updated_at": "2022-01-05T18:16:48+05:30", - "products": [ - { - "product_id": 7510929801472, - "sku": "15", - "title": "p1", - "price": "5000.00", - "brand": "rudderstack-store", - "quantity": 1, - "admin_graphql_api_id": "gid://shopify/LineItem/11896203149568", - "discount_allocations": [], - "duties": [], - "fulfillable_quantity": 0, - "fulfillment_service": "manual", - "fulfillment_status": "fulfilled", - "gift_card": false, - "grams": 0, - "id": 11896203149568, - "origin_location": { - "address1": "74 CC/7, Anupama Housing Estate - II", - "address2": "", - "city": "Kolkatta", - "country_code": "IN", - "id": 3373642219776, - "name": "74 CC/7, Anupama Housing Estate - II", - "province_code": "WB", - "zip": "700052" - }, - "price_set": { - "presentment_money": { - "amount": "5000.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "5000.00", - "currency_code": "INR" - } - }, - "product_exists": true, - "properties": [], - "requires_shipping": true, - "tax_lines": [ - { - "channel_liable": false, - "price": "900.00", - "price_set": { - "presentment_money": { - "amount": "900.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "900.00", - "currency_code": "INR" - } - }, - "rate": 0.18, - "title": "IGST" - } - ], - "taxable": true, - "total_discount": "0.00", - "total_discount_set": { - "presentment_money": { - "amount": "0.00", - "currency_code": "INR" - }, - "shop_money": { - "amount": "0.00", - "currency_code": "INR" - } - }, - "variant_inventory_management": "shopify", - "variant": "42211160228096 " - } - ] + "price_set": { + "presentment_money": { + "amount": "5000.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "5000.00", + "currency_code": "INR" + } }, - "traits": { - "email": "test_person@email.com", - "firstName": "Test", - "lastName": "Person", - "shippingAddress": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", - "address2": "", - "city": "Kolkata", - "company": null, - "country": "India", - "country_code": "IN", - "first_name": "Utsab", - "last_name": "Chowdhury", - "latitude": null, - "longitude": null, - "name": "Utsab Chowdhury", - "phone": null, - "province": "West Bengal", - "province_code": "WB", - "zip": "700025" + "product_exists": true, + "properties": [], + "requires_shipping": true, + "tax_lines": [ + { + "channel_liable": false, + "price": "900.00", + "price_set": { + "presentment_money": { + "amount": "900.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "900.00", + "currency_code": "INR" + } }, - "billingAddress": { - "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", - "address2": "", - "city": "Kolkata", - "company": null, - "country": "India", - "country_code": "IN", - "first_name": "Utsab", - "last_name": "Chowdhury", - "latitude": null, - "longitude": null, - "name": "Utsab Chowdhury", - "phone": null, - "province": "West Bengal", - "province_code": "WB", - "zip": "700025" - } - } + "rate": 0.18, + "title": "IGST" + } + ], + "taxable": true, + "total_discount": "0.00", + "total_discount_set": { + "presentment_money": { + "amount": "0.00", + "currency_code": "INR" + }, + "shop_money": { + "amount": "0.00", + "currency_code": "INR" + } + }, + "variant_inventory_management": "shopify", + "variant": "42211160228096 " + } + ] + }, + "traits": { + "email": "test_person@email.com", + "firstName": "Test", + "lastName": "Person", + "shippingAddress": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", + "address2": "", + "city": "Kolkata", + "company": null, + "country": "India", + "country_code": "IN", + "first_name": "Utsab", + "last_name": "Chowdhury", + "latitude": null, + "longitude": null, + "name": "Utsab Chowdhury", + "phone": null, + "province": "West Bengal", + "province_code": "WB", + "zip": "700025" + }, + "billingAddress": { + "address1": "11 Rani Sankari Lane Patuapara Bhowanipore", + "address2": "", + "city": "Kolkata", + "company": null, + "country": "India", + "country_code": "IN", + "first_name": "Utsab", + "last_name": "Chowdhury", + "latitude": null, + "longitude": null, + "name": "Utsab Chowdhury", + "phone": null, + "province": "West Bengal", + "province_code": "WB", + "zip": "700025" } + } } -] \ No newline at end of file + } +] diff --git a/test/__tests__/data/singular_router_input.json b/test/__tests__/data/singular_router_input.json index 7f502442764e..f3fb694832f1 100644 --- a/test/__tests__/data/singular_router_input.json +++ b/test/__tests__/data/singular_router_input.json @@ -438,18 +438,10 @@ "DestinationDefinition": { "config": { "destConfig": { - "ios": [ - "useNativeSDK" - ], - "android": [ - "useNativeSDK" - ], - "cordova": [ - "useNativeSDK" - ], - "reactnative": [ - "useNativeSDK" - ], + "ios": ["useNativeSDK"], + "android": ["useNativeSDK"], + "cordova": ["useNativeSDK"], + "reactnative": ["useNativeSDK"], "defaultConfig": [ "apiKey", "apiSecret", @@ -536,4 +528,4 @@ "destinationDefinitionId": "" } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/singular_router_output.json b/test/__tests__/data/singular_router_output.json index c59f3ebc1c68..b5221d1f7b04 100644 --- a/test/__tests__/data/singular_router_output.json +++ b/test/__tests__/data/singular_router_output.json @@ -301,18 +301,10 @@ "DestinationDefinition": { "config": { "destConfig": { - "ios": [ - "useNativeSDK" - ], - "android": [ - "useNativeSDK" - ], - "cordova": [ - "useNativeSDK" - ], - "reactnative": [ - "useNativeSDK" - ], + "ios": ["useNativeSDK"], + "android": ["useNativeSDK"], + "cordova": ["useNativeSDK"], + "reactnative": ["useNativeSDK"], "defaultConfig": [ "apiKey", "apiSecret", @@ -368,4 +360,4 @@ "secretVersion": 1 } } -] \ No newline at end of file +] diff --git a/test/__tests__/data/tiktok_ads_offline_events.json b/test/__tests__/data/tiktok_ads_offline_events.json index a2af156d5b34..aded6af93b72 100644 --- a/test/__tests__/data/tiktok_ads_offline_events.json +++ b/test/__tests__/data/tiktok_ads_offline_events.json @@ -328,9 +328,7 @@ "phone_numbers": [ "c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646" ], - "emails": [ - "d9fcca64ec1b250da4261a3f89a8e0f7749c4e0f5a1a918e5397194c8b5a9f16" - ] + "emails": ["d9fcca64ec1b250da4261a3f89a8e0f7749c4e0f5a1a918e5397194c8b5a9f16"] } }, "properties": { @@ -468,4 +466,4 @@ } ] } -] \ No newline at end of file +] diff --git a/test/__tests__/data/webhook_router_input.json b/test/__tests__/data/webhook_router_input.json index 197677d7a9c1..6305fbfe7710 100644 --- a/test/__tests__/data/webhook_router_input.json +++ b/test/__tests__/data/webhook_router_input.json @@ -212,4 +212,3 @@ } ] ] - diff --git a/test/__tests__/data/webhook_router_output.json b/test/__tests__/data/webhook_router_output.json index a5f0aaf7b3b2..716f8f3c76f1 100644 --- a/test/__tests__/data/webhook_router_output.json +++ b/test/__tests__/data/webhook_router_output.json @@ -254,4 +254,4 @@ } } ] -] \ No newline at end of file +] diff --git a/test/__tests__/integration/data_scenarios/cdk_v1/failure.json b/test/__tests__/integration/data_scenarios/cdk_v1/failure.json index 976bc69ad0ad..b8a89d60b1dc 100644 --- a/test/__tests__/integration/data_scenarios/cdk_v1/failure.json +++ b/test/__tests__/integration/data_scenarios/cdk_v1/failure.json @@ -79,18 +79,10 @@ "Config": { "cdkEnabled": true, "destConfig": { - "defaultConfig": [ - "zapUrl", - "trackEventsToZap", - "pageScreenEventsToZap" - ] + "defaultConfig": ["zapUrl", "trackEventsToZap", "pageScreenEventsToZap"] }, "excludeKeys": [], - "includeKeys": [ - "zapUrl", - "trackEventsToZap", - "pageScreenEventsToZap" - ], + "includeKeys": ["zapUrl", "trackEventsToZap", "pageScreenEventsToZap"], "saveDestinationResponse": true, "secretKeys": ["zapUrl"], "supportedMessageTypes": ["track", "page", "screen"], diff --git a/test/__tests__/integration/data_scenarios/cdk_v1/success.json b/test/__tests__/integration/data_scenarios/cdk_v1/success.json index f59510853913..c8505382b163 100644 --- a/test/__tests__/integration/data_scenarios/cdk_v1/success.json +++ b/test/__tests__/integration/data_scenarios/cdk_v1/success.json @@ -79,18 +79,10 @@ "Config": { "cdkEnabled": true, "destConfig": { - "defaultConfig": [ - "zapUrl", - "trackEventsToZap", - "pageScreenEventsToZap" - ] + "defaultConfig": ["zapUrl", "trackEventsToZap", "pageScreenEventsToZap"] }, "excludeKeys": [], - "includeKeys": [ - "zapUrl", - "trackEventsToZap", - "pageScreenEventsToZap" - ], + "includeKeys": ["zapUrl", "trackEventsToZap", "pageScreenEventsToZap"], "saveDestinationResponse": true, "secretKeys": ["zapUrl"], "supportedMessageTypes": ["track", "page", "screen"], diff --git a/test/__tests__/integration/data_scenarios/cdk_v2/failure.json b/test/__tests__/integration/data_scenarios/cdk_v2/failure.json index e426bb33a709..a38afbbf638b 100644 --- a/test/__tests__/integration/data_scenarios/cdk_v2/failure.json +++ b/test/__tests__/integration/data_scenarios/cdk_v2/failure.json @@ -646,8 +646,7 @@ "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": "dataValidation", - "errorType": "instrumentation", + "errorCategory": "platform", "implementation": "cdkV2", "destType": "PINTEREST_TAG", "module": "destination", diff --git a/test/__tests__/integration/data_scenarios/destination/batch/failure_batch.json b/test/__tests__/integration/data_scenarios/destination/batch/failure_batch.json index 836bb7b9f3ff..eb15d0be6d66 100644 --- a/test/__tests__/integration/data_scenarios/destination/batch/failure_batch.json +++ b/test/__tests__/integration/data_scenarios/destination/batch/failure_batch.json @@ -263,14 +263,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -625,14 +618,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -989,14 +975,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -1186,7 +1165,7 @@ }, "batched": false, "statusCode": 400, - "statTags": { + "statTags": { "errorCategory": "dataValidation", "errorType": "instrumentation" }, @@ -1596,14 +1575,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", diff --git a/test/__tests__/integration/data_scenarios/destination/batch/successful_batch.json b/test/__tests__/integration/data_scenarios/destination/batch/successful_batch.json index 9f6bff299375..bec5bdb26ef3 100644 --- a/test/__tests__/integration/data_scenarios/destination/batch/successful_batch.json +++ b/test/__tests__/integration/data_scenarios/destination/batch/successful_batch.json @@ -263,14 +263,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -627,14 +620,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -991,14 +977,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", @@ -1620,14 +1599,7 @@ ], "saveDestinationResponse": true, "secretKeys": ["apiKey", "apiSecret"], - "supportedMessageTypes": [ - "alias", - "group", - "identify", - "page", - "screen", - "track" - ], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], "supportedSourceTypes": [ "android", "ios", diff --git a/test/__tests__/integration/data_scenarios/source/successful.json b/test/__tests__/integration/data_scenarios/source/successful.json index 539140402004..74af44932b50 100644 --- a/test/__tests__/integration/data_scenarios/source/successful.json +++ b/test/__tests__/integration/data_scenarios/source/successful.json @@ -2,15 +2,9 @@ "input": [ { "query_parameters": { - "topic": [ - "fulfillments_update" - ], - "writeKey": [ - "sample-write-key" - ], - "signature": [ - "rudderstack" - ] + "topic": ["fulfillments_update"], + "writeKey": ["sample-write-key"], + "signature": ["rudderstack"] }, "admin_graphql_api_id": "gid://shopify/Fulfillment/4124667937024", "created_at": "2022-01-05T18:13:02+05:30", @@ -141,13 +135,9 @@ "status": "success", "tracking_company": "Amazon Logistics UK", "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], + "tracking_numbers": ["Sample001test"], "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", - "tracking_urls": [ - "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" - ], + "tracking_urls": ["https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530"], "updated_at": "2022-01-05T18:16:48+05:30" } ], @@ -187,9 +177,7 @@ "status": "success", "tracking_company": "Amazon Logistics UK", "tracking_number": "Sample001test", - "tracking_numbers": [ - "Sample001test" - ], + "tracking_numbers": ["Sample001test"], "tracking_url": "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530", "tracking_urls": [ "https://www.amazon.co.uk/gp/help/customer/display.html?nodeId=201910530" @@ -314,4 +302,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/__tests__/integration/service.integration.test.ts b/test/__tests__/integration/service.integration.test.ts index 09a14160fd27..e56c8d4e4f88 100644 --- a/test/__tests__/integration/service.integration.test.ts +++ b/test/__tests__/integration/service.integration.test.ts @@ -4,8 +4,8 @@ import request from 'supertest'; import { createHttpTerminator } from 'http-terminator'; import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; -import { applicationRoutes } from '../../../src/routes'; import setValue from 'set-value'; +import { applicationRoutes } from '../../../src/routes'; let server: any; const OLD_ENV = process.env; @@ -37,7 +37,9 @@ const getDataFromPath = (pathInput) => { describe('Basic route tests', () => { test('successful features response', async () => { - const expectedData = JSON.parse(fs.readFileSync('features.json', 'utf8')); + const expectedData = JSON.parse( + fs.readFileSync(path.resolve(__dirname, '../../../src/features.json'), 'utf8'), + ); const response = await request(server).get('/features'); expect(response.status).toEqual(200); expect(JSON.parse(response.text)).toEqual(expectedData); diff --git a/test/integrations/destinations/engage/processor/data.js b/test/integrations/destinations/engage/processor/data.js index 5d89bd17875c..cf0156162332 100644 --- a/test/integrations/destinations/engage/processor/data.js +++ b/test/integrations/destinations/engage/processor/data.js @@ -42,7 +42,7 @@ const data = [ privateKey: 'n89g389yr389fgbef0u2rff', }, }, - error: 'Neither externalId or userId is available.', + error: 'Neither externalId nor userId is available', statTags: { destType: 'ENGAGE', errorCategory: 'dataValidation', diff --git a/test/integrations/destinations/pipedream/processor/data.js b/test/integrations/destinations/pipedream/processor/data.js index cbb4a668a6ce..8e910288e314 100644 --- a/test/integrations/destinations/pipedream/processor/data.js +++ b/test/integrations/destinations/pipedream/processor/data.js @@ -1,51 +1,239 @@ -const data = [{ - "name": "pipedream", - "description": "Dynamic Header and Append Header", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","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"},"traits":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}},"event":"spin_result","integrations":{"All":true},"message_id":"a80f82be-9bdc-4a9f-b2a5-15621ee41df8","properties":{"additional_bet_index":0,"battle_id":"N/A","featureGameType":"N/A","win_amount":0},"timestamp":"2019-09-01T15:46:51.693229+05:30","type":"track","header":{"dynamic_header_key_string":"dynamic_header_value_string","dynamic_header_key_num":10,"dynamic_header_key_object":{"k1":"v1"}},"appendPath":"/product/search?string=value"},"destination":{"Config":{"pipedreamUrl":"http://6b0e6a60.ngrok.io","headers":[{"from":"","to":""},{"from":"test2","to":"value2"}]}}}, - ], - "method": "POST", +const data = [ + { + name: 'pipedream', + description: 'Dynamic Header and Append Header', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + context: { + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', }, - "pathSuffix": "", + network: { carrier: 'Banglalink' }, + os: { name: 'android', version: '8.1.0' }, + traits: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { All: true }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + additional_bet_index: 0, + battle_id: 'N/A', + featureGameType: 'N/A', + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + header: { + dynamic_header_key_string: 'dynamic_header_value_string', + dynamic_header_key_num: 10, + dynamic_header_key_object: { k1: 'v1' }, + }, + appendPath: '/product/search?string=value', + }, + destination: { + Config: { + pipedreamUrl: 'http://6b0e6a60.ngrok.io', + headers: [ + { from: '', to: '' }, + { from: 'test2', to: 'value2' }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + JSON_ARRAY: {}, + JSON: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + 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' }, + traits: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { All: true }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + additional_bet_index: 0, + battle_id: 'N/A', + featureGameType: 'N/A', + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + }, + FORM: {}, + }, + files: {}, + endpoint: 'http://6b0e6a60.ngrok.io/product/search?string=value', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + headers: { + 'content-type': 'application/json', + test2: 'value2', + dynamic_header_key_string: 'dynamic_header_value_string', + }, + version: '1', + params: {}, + type: 'REST', + method: 'POST', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'pipedream', + description: 'Dynamic Header', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + 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' }, + traits: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { All: true }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + additional_bet_index: 0, + battle_id: 'N/A', + featureGameType: 'N/A', + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', + header: { + dynamic_header_key_string: 'dynamic_header_value_string', + dynamic_header_key_num: 10, + dynamic_header_key_object: { k1: 'v1' }, + }, + }, + destination: { + Config: { + pipedreamUrl: 'http://6b0e6a60.ngrok.io', + pipedreamMethod: 'PUT', + headers: [ + { from: '', to: '' }, + { from: 'test2', to: 'value2' }, + ], + }, }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"JSON_ARRAY":{},"JSON":{"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","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"},"traits":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}},"event":"spin_result","integrations":{"All":true},"message_id":"a80f82be-9bdc-4a9f-b2a5-15621ee41df8","properties":{"additional_bet_index":0,"battle_id":"N/A","featureGameType":"N/A","win_amount":0},"timestamp":"2019-09-01T15:46:51.693229+05:30","type":"track"},"FORM":{}},"files":{},"endpoint":"http://6b0e6a60.ngrok.io/product/search?string=value","userId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","headers":{"content-type":"application/json","test2":"value2","dynamic_header_key_string":"dynamic_header_value_string"},"version":"1","params":{},"type":"REST","method":"POST"}, - "statusCode": 200}] - } - } - },{ - "name": "pipedream", - "description": "Dynamic Header", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","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"},"traits":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}},"event":"spin_result","integrations":{"All":true},"message_id":"a80f82be-9bdc-4a9f-b2a5-15621ee41df8","properties":{"additional_bet_index":0,"battle_id":"N/A","featureGameType":"N/A","win_amount":0},"timestamp":"2019-09-01T15:46:51.693229+05:30","type":"track","header":{"dynamic_header_key_string":"dynamic_header_value_string","dynamic_header_key_num":10,"dynamic_header_key_object":{"k1":"v1"}}},"destination":{"Config":{"pipedreamUrl":"http://6b0e6a60.ngrok.io","pipedreamMethod":"PUT","headers":[{"from":"","to":""},{"from":"test2","to":"value2"}]}}}, - ], - "method": "POST", + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + JSON_ARRAY: {}, + JSON: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + 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' }, + traits: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + event: 'spin_result', + integrations: { All: true }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + additional_bet_index: 0, + battle_id: 'N/A', + featureGameType: 'N/A', + win_amount: 0, + }, + timestamp: '2019-09-01T15:46:51.693229+05:30', + type: 'track', }, - "pathSuffix": "", + FORM: {}, + }, + files: {}, + endpoint: 'http://6b0e6a60.ngrok.io', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + headers: { + 'content-type': 'application/json', + test2: 'value2', + dynamic_header_key_string: 'dynamic_header_value_string', + }, + version: '1', + params: {}, + type: 'REST', + method: 'PUT', }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"JSON_ARRAY":{},"JSON":{"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","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"},"traits":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}},"event":"spin_result","integrations":{"All":true},"message_id":"a80f82be-9bdc-4a9f-b2a5-15621ee41df8","properties":{"additional_bet_index":0,"battle_id":"N/A","featureGameType":"N/A","win_amount":0},"timestamp":"2019-09-01T15:46:51.693229+05:30","type":"track"},"FORM":{}},"files":{},"endpoint":"http://6b0e6a60.ngrok.io","userId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","headers":{"content-type":"application/json","test2":"value2","dynamic_header_key_string":"dynamic_header_value_string"},"version":"1","params":{},"type":"REST","method":"PUT"}, - "statusCode": 200}] - } - } - }]; module.exports = { - data - } \ No newline at end of file + statusCode: 200, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/pipedream/router/data.js b/test/integrations/destinations/pipedream/router/data.js index 2ab4b770125a..33494b5b2524 100644 --- a/test/integrations/destinations/pipedream/router/data.js +++ b/test/integrations/destinations/pipedream/router/data.js @@ -1,523 +1,523 @@ const data = [ { - "name": "pipedream", - "description": "Track Sucessfull Call with Headers from Config", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "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" - }, - "traits": { - "address": { - "city": "Dhaka", - "country": "Bangladesh" - }, - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" - } + name: 'pipedream', + description: 'Track Sucessfull Call with Headers from Config', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + context: { + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', }, - "event": "spin_result", - "integrations": { - "All": true + os: { + name: 'android', + version: '8.1.0', }, - "message_id": "a80f82be-9bdc-4a9f-b2a5-15621ee41df8", - "properties": { - "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 + traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "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", - "gem_balance": 0, - "graphicsQuality": "HD", - "idfa": "2bf99787-33d2-4ae2-a76a-c49672f97252", - "internetReachability": "ReachableViaLocalAreaNetwork", - "isLowEndDevice": false, - "level": 6, - "lifetime_gem_balance": 0, - "player_total_battles": 0, - "player_total_shields": 0, - "start_date": "2019-08-01", - "total_payments": 0, - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "versionSessionCount": 2 - } }, - "metadata": { - "jobId": 2 + event: 'spin_result', + integrations: { + All: true, }, - "destination": { - "Config": { - "pipedreamUrl": "http://6b0e6a60.ngrok.io", - "headers": [ - { - "from": "", - "to": "" - }, - { - "from": "test2", - "to": "value2" - } - ] - } - } - }] - , "destType": "pipedream" + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + 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, + }, + 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', + gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + internetReachability: 'ReachableViaLocalAreaNetwork', + isLowEndDevice: false, + level: 6, + lifetime_gem_balance: 0, + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, + }, + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + pipedreamUrl: 'http://6b0e6a60.ngrok.io', + headers: [ + { + from: '', + to: '', + }, + { + from: 'test2', + to: 'value2', + }, + ], + }, + }, + }, + ], + destType: 'pipedream', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "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" + batchedRequest: { + 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 + 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", - "name": "xiaomi" + 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', + name: 'xiaomi', + }, + traits: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, }, - "traits": { - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "address": { - "city": "Dhaka", - "country": "Bangladesh" - } + os: { + version: '8.1.0', + name: 'android', }, - "os": { - "version": "8.1.0", - "name": "android" + network: { + carrier: 'Banglalink', }, - "network": { - "carrier": "Banglalink" - } }, - "type": "track", - "properties": { - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "jackpot_win_type": "Silver", - "coin_balance": 9466052, - "bet_level": 1, - "ishighroller": "False", - "tournament_id": "T1561970819", - "battle_id": "N/A", - "bet_amount": 9, - "fb_profile": "0", - "player_total_shields": 0, - "is_turbo": "False", - "player_total_battles": 0, - "bet_multiplier": 1, - "start_date": "2019-08-01", - "versionSessionCount": 2, - "graphicsQuality": "HD", - "is_auto_spin": "False", - "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", - "featureGameType": "N/A", - "gem_balance": 0, - "internetReachability": "ReachableViaLocalAreaNetwork", - "total_payments": 0, - "level": 6, - "win_amount": 0, - "no_of_spin": 1, - "game_name": "FireEagleSlots", - "jackpot_win_amount": 90, - "lifetime_gem_balance": 0, - "isf": "False" - } + type: 'track', + properties: { + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + jackpot_win_type: 'Silver', + coin_balance: 9466052, + bet_level: 1, + ishighroller: 'False', + tournament_id: 'T1561970819', + battle_id: 'N/A', + bet_amount: 9, + fb_profile: '0', + player_total_shields: 0, + is_turbo: 'False', + player_total_battles: 0, + bet_multiplier: 1, + start_date: '2019-08-01', + versionSessionCount: 2, + graphicsQuality: 'HD', + is_auto_spin: 'False', + 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', + featureGameType: 'N/A', + gem_balance: 0, + internetReachability: 'ReachableViaLocalAreaNetwork', + total_payments: 0, + level: 6, + win_amount: 0, + no_of_spin: 1, + game_name: 'FireEagleSlots', + jackpot_win_amount: 90, + lifetime_gem_balance: 0, + isf: 'False', + }, }, - "FORM": {} + FORM: {}, }, - "files": {}, - "endpoint": "http://6b0e6a60.ngrok.io", - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "headers": { - "content-type": "application/json", - "test2": "value2" + files: {}, + endpoint: 'http://6b0e6a60.ngrok.io', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + headers: { + 'content-type': 'application/json', + test2: 'value2', }, - "version": "1", - "params": {}, - "type": "REST", - "method": "POST" + version: '1', + params: {}, + type: 'REST', + method: 'POST', }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "pipedreamUrl": "http://6b0e6a60.ngrok.io", - "headers": [ + batched: false, + statusCode: 200, + destination: { + Config: { + pipedreamUrl: 'http://6b0e6a60.ngrok.io', + headers: [ { - "from": "", - "to": "" + from: '', + to: '', }, { - "from": "test2", - "to": "value2" - } - ] - } - } - } - ] - } - } - } + from: 'test2', + to: 'value2', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "pipedream", - "description": "Track Call without extra Headers", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "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" - }, - "traits": { - "address": { - "city": "Dhaka", - "country": "Bangladesh" - }, - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" - } + name: 'pipedream', + description: 'Track Call without extra Headers', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + context: { + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', }, - "event": "spin_result", - "integrations": { - "All": true + os: { + name: 'android', + version: '8.1.0', }, - "message_id": "a80f82be-9bdc-4a9f-b2a5-15621ee41df8", - "properties": { - "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 + traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "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", - "gem_balance": 0, - "graphicsQuality": "HD", - "idfa": "2bf99787-33d2-4ae2-a76a-c49672f97252", - "internetReachability": "ReachableViaLocalAreaNetwork", - "isLowEndDevice": false, - "level": 6, - "lifetime_gem_balance": 0, - "player_total_battles": 0, - "player_total_shields": 0, - "start_date": "2019-08-01", - "total_payments": 0, - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "versionSessionCount": 2 - } }, - "metadata": { - "jobId": 2 + event: 'spin_result', + integrations: { + All: true, + }, + message_id: 'a80f82be-9bdc-4a9f-b2a5-15621ee41df8', + properties: { + 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, + }, + 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', + gem_balance: 0, + graphicsQuality: 'HD', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + internetReachability: 'ReachableViaLocalAreaNetwork', + isLowEndDevice: false, + level: 6, + lifetime_gem_balance: 0, + player_total_battles: 0, + player_total_shields: 0, + start_date: '2019-08-01', + total_payments: 0, + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + versionSessionCount: 2, + }, + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + pipedreamUrl: 'https://6b0e6a60.ngrok.io/n', }, - "destination": { - "Config": { - "pipedreamUrl": "https://6b0e6a60.ngrok.io/n" - } - } - }] - , "destType": "pipedream" + }, + }, + ], + destType: 'pipedream', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "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" + batchedRequest: { + 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 + 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", - "name": "xiaomi" + 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', + name: 'xiaomi', }, - "traits": { - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "address": { - "city": "Dhaka", - "country": "Bangladesh" - } + traits: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, }, - "os": { - "version": "8.1.0", - "name": "android" + os: { + version: '8.1.0', + name: 'android', }, - "network": { - "carrier": "Banglalink" - } + network: { + carrier: 'Banglalink', + }, + }, + type: 'track', + properties: { + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + jackpot_win_type: 'Silver', + coin_balance: 9466052, + bet_level: 1, + ishighroller: 'False', + tournament_id: 'T1561970819', + battle_id: 'N/A', + bet_amount: 9, + fb_profile: '0', + player_total_shields: 0, + is_turbo: 'False', + player_total_battles: 0, + bet_multiplier: 1, + start_date: '2019-08-01', + versionSessionCount: 2, + graphicsQuality: 'HD', + is_auto_spin: 'False', + 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', + featureGameType: 'N/A', + gem_balance: 0, + internetReachability: 'ReachableViaLocalAreaNetwork', + total_payments: 0, + level: 6, + win_amount: 0, + no_of_spin: 1, + game_name: 'FireEagleSlots', + jackpot_win_amount: 90, + lifetime_gem_balance: 0, + isf: 'False', }, - "type": "track", - "properties": { - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "jackpot_win_type": "Silver", - "coin_balance": 9466052, - "bet_level": 1, - "ishighroller": "False", - "tournament_id": "T1561970819", - "battle_id": "N/A", - "bet_amount": 9, - "fb_profile": "0", - "player_total_shields": 0, - "is_turbo": "False", - "player_total_battles": 0, - "bet_multiplier": 1, - "start_date": "2019-08-01", - "versionSessionCount": 2, - "graphicsQuality": "HD", - "is_auto_spin": "False", - "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", - "featureGameType": "N/A", - "gem_balance": 0, - "internetReachability": "ReachableViaLocalAreaNetwork", - "total_payments": 0, - "level": 6, - "win_amount": 0, - "no_of_spin": 1, - "game_name": "FireEagleSlots", - "jackpot_win_amount": 90, - "lifetime_gem_balance": 0, - "isf": "False" - } }, - "FORM": {} + FORM: {}, }, - "files": {}, - "endpoint": "https://6b0e6a60.ngrok.io/n", - "userId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "headers": { - "content-type": "application/json" + files: {}, + endpoint: 'https://6b0e6a60.ngrok.io/n', + userId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + headers: { + 'content-type': 'application/json', }, - "version": "1", - "params": {}, - "type": "REST", - "method": "POST" + version: '1', + params: {}, + type: 'REST', + method: 'POST', }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "pipedreamUrl": "https://6b0e6a60.ngrok.io/n" - } - } - } - ] - } - } - } - } + batched: false, + statusCode: 200, + destination: { + Config: { + pipedreamUrl: 'https://6b0e6a60.ngrok.io/n', + }, + }, + }, + ], + }, + }, + }, + }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/posthog/processor/data.js b/test/integrations/destinations/posthog/processor/data.js index 274c0c413943..130b4af1aef7 100644 --- a/test/integrations/destinations/posthog/processor/data.js +++ b/test/integrations/destinations/posthog/processor/data.js @@ -1,291 +1,1942 @@ -const data = [{ - "name": "posthog", - "description": "PostHog alias call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/"}},"message":{"event":"event-alias","context":{"ip":"0.0.0.0","device":{"id":"df16bffa-5c3d-4fbb-9bce-3bab098129a7R","manufacturer":"Xiaomi","model":"Redmi 6","name":"xiaomi"},"network":{"carrier":"Banglalink"},"os":{"name":"android","version":"8.1.0"},"app":{"build":"1.0.0","name":"RudderLabs JavaScript SDK","namespace":"com.rudderlabs.javascript","version":"1.1.7"},"traits":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}},"type":"alias","timestamp":"2020-11-04T13:21:09.712Z","userId":"uid-1","previousId":"prevId_1","anonymousId":"f3cf54d8-f237-45d2-89f7-ccd70d42cf31"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"properties":{"$set":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"},"$os":"android","$time":"2020-11-04T13:21:09.712Z","$device_id":"df16bffa-5c3d-4fbb-9bce-3bab098129a7R","$ip":"0.0.0.0","$timestamp":"2020-11-04T13:21:09.712Z","$anon_distinct_id":"f3cf54d8-f237-45d2-89f7-ccd70d42cf31","distinct_id":"prevId_1","$device_manufacturer":"Xiaomi","$os_version":"8.1.0","$app_version":"1.1.7","$device_name":"xiaomi","$network_carrier":"Banglalink","$app_name":"RudderLabs JavaScript SDK","$device_model":"Redmi 6","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","alias":"uid-1"},"timestamp":"2020-11-04T13:21:09.712Z","event":"$create_alias","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"alias"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE"}},"message":{"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","event":"Product Brought","context":{"ip":"0.0.0.0","device":{"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"}},"type":"track","properties":{"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","versionSessionCount":2,"win_amount":0},"timestamp":"2020-11-04T13:21:09.712Z","userId":"uid-2","messageId":"e4408cb8-16dd-41e9-a313-a7a9cdc4bac5"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"distinct_id":"uid-2","event":"Product Brought","messageId":"e4408cb8-16dd-41e9-a313-a7a9cdc4bac5","properties":{"$set":{"address":{"city":"Dhaka","country":"Bangladesh"},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"},"$os":"android","$time":"2020-11-04T13:21:09.712Z","$device_id":"df16bffa-5c3d-4fbb-9bce-3bab098129a7R","$ip":"0.0.0.0","$timestamp":"2020-11-04T13:21:09.712Z","$anon_distinct_id":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","distinct_id":"uid-2","$device_manufacturer":"Xiaomi","$os_version":"8.1.0","$device_name":"xiaomi","$network_carrier":"Banglalink","$device_model":"Redmi 6","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","versionSessionCount":2,"win_amount":0},"timestamp":"2020-11-04T13:21:09.712Z","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"capture"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com"}},"message":{"channel":"web","context":{"app":{"build":"1.0.0","name":"RudderLabs JavaScript SDK","namespace":"com.rudderlabs.javascript","version":"1.1.7"},"traits":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"library":{"name":"RudderLabs JavaScript SDK","version":"1.1.7"},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","locale":"en-GB","os":{"name":"","version":""},"screen":{"density":2},"campaign":{},"page":{"path":"/Rectified.html","referrer":"http://localhost:1112/","search":"","title":"","url":"http://localhost:1112/Rectified.html"},"ip":"0.0.0.0","userID":"sampleUserOption"},"type":"track","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","originalTimestamp":"2020-11-04T13:21:09.712Z","anonymousId":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","userId":"uid-3","event":"order completed","properties":{"path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"integrations":{"All":true},"sentAt":"2020-11-04T13:21:09.712Z"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"distinct_id":"uid-3","event":"order completed","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","properties":{"$set":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"$current_url":"http://localhost:1112/Rectified.html","$pathname":"/Rectified.html","$lib":"RudderLabs JavaScript SDK","$lib_version":"1.1.7","$time":"2020-11-04T13:21:09.712Z","$ip":"0.0.0.0","$timestamp":"2020-11-04T13:21:09.712Z","$anon_distinct_id":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","distinct_id":"uid-3","$screen_density":2,"$locale":"en-GB","$useragent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","$app_version":"1.1.7","$app_name":"RudderLabs JavaScript SDK","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","$os":"Mac OS","$browser":"Chrome","$browser_version":"86.0.4240.111","$host":"localhost:1112","path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"timestamp":"2020-11-04T13:21:09.712Z","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"capture"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "4", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/"}},"message":{"type":"screen","event":"HomePage","sentAt":"2020-11-12T21:12:54.117Z","userId":"sajal","channel":"mobile","context":{"os":{"name":"Android","version":"10"},"app":{"name":"AMTestProject","build":"1","version":"1.0","namespace":"com.rudderstack.android.rudderstack.sampleAndroidApp"},"device":{"id":"9c6bd77ea9da3e68","name":"raphaelin","type":"Android","model":"Redmi K20 Pro","manufacturer":"Xiaomi"},"locale":"en-IN","screen":{"width":1080,"height":2210,"density":440},"traits":{"id":"sajal","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"sajal","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"Mohanta","quantity":"5","username":"Samle_putUserName","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"library":{"name":"com.rudderstack.android.sdk.core","version":"1.0.8"},"network":{"wifi":true,"carrier":"airtel","cellular":true,"bluetooth":false},"timezone":"Asia/Kolkata","userAgent":"Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)"},"messageId":"1605215561320-917a2554-87fd-4f9e-881d-9d29e8f30490","properties":{"name":"HomePage"},"anonymousId":"9c6bd77ea9da3e68","integrations":{"All":true},"originalTimestamp":"2020-11-12T21:12:41.320Z"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"properties":{"$set":{"id":"sajal","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"sajal","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"Mohanta","quantity":"5","username":"Samle_putUserName","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"$os":"Android","$screen_height":2210,"$screen_width":1080,"$lib":"com.rudderstack.android.sdk.core","$lib_version":"1.0.8","$time":"2020-11-12T21:12:41.320Z","$device_id":"9c6bd77ea9da3e68","$timestamp":"2020-11-12T21:12:41.320Z","$anon_distinct_id":"9c6bd77ea9da3e68","distinct_id":"sajal","$screen_density":440,"$device_manufacturer":"Xiaomi","$os_version":"10","$timezone":"Asia/Kolkata","$locale":"en-IN","$useragent":"Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)","$app_version":"1.0","$device_name":"raphaelin","$network_carrier":"airtel","$app_name":"AMTestProject","$device_model":"Redmi K20 Pro","$app_namespace":"com.rudderstack.android.rudderstack.sampleAndroidApp","$app_build":"1","$screen_name":"HomePage","name":"HomePage"},"timestamp":"2020-11-12T21:12:41.320Z","distinct_id":"sajal","messageId":"1605215561320-917a2554-87fd-4f9e-881d-9d29e8f30490","event":"$screen","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"screen"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog identify call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/"}},"message":{"type":"identify","event":"identify","sentAt":"2020-11-12T21:12:54.117Z","userId":"sajal","channel":"mobile","context":{"os":{"name":"Android","version":"10"},"app":{"name":"AMTestProject","build":"1","version":"1.0","namespace":"com.rudderstack.android.rudderstack.sampleAndroidApp"},"device":{"id":"9c6bd77ea9da3e68","name":"raphaelin","type":"Android","model":"Redmi K20 Pro","manufacturer":"Xiaomi"},"locale":"en-IN","screen":{"width":1080,"height":2210,"density":440},"traits":{"id":"sajal","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"sajal","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"Mohanta","quantity":"5","username":"Samle_putUserName","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"library":{"name":"com.rudderstack.android.sdk.core","version":"1.0.8"},"network":{"wifi":true,"carrier":"airtel","cellular":true,"bluetooth":false},"timezone":"Asia/Kolkata","userAgent":"Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)"},"messageId":"1605215561266-084c95fb-aaf6-4abf-9b3b-7ac449a2d4fb","anonymousId":"9c6bd77ea9da3e68","integrations":{"All":true},"originalTimestamp":"2020-11-12T21:12:41.266Z"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"distinct_id":"sajal","timestamp":"2020-11-12T21:12:41.266Z","messageId":"1605215561266-084c95fb-aaf6-4abf-9b3b-7ac449a2d4fb","$set":{"id":"sajal","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"sajal","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"Mohanta","quantity":"5","username":"Samle_putUserName","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"properties":{"$os":"Android","$screen_height":2210,"$screen_width":1080,"$lib":"com.rudderstack.android.sdk.core","$lib_version":"1.0.8","$time":"2020-11-12T21:12:41.266Z","$device_id":"9c6bd77ea9da3e68","$timestamp":"2020-11-12T21:12:41.266Z","$anon_distinct_id":"9c6bd77ea9da3e68","distinct_id":"sajal","$screen_density":440,"$device_manufacturer":"Xiaomi","$os_version":"10","$timezone":"Asia/Kolkata","$locale":"en-IN","$useragent":"Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)","$app_version":"1.0","$device_name":"raphaelin","$network_carrier":"airtel","$app_name":"AMTestProject","$device_model":"Redmi K20 Pro","$app_namespace":"com.rudderstack.android.rudderstack.sampleAndroidApp","$app_build":"1"},"event":"$identify","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"identify"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog track call with custom event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com"}},"message":{"channel":"web","context":{"app":{"build":"1.0.0","name":"RudderLabs JavaScript SDK","namespace":"com.rudderlabs.javascript","version":"1.1.7"},"traits":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"library":{"name":"RudderLabs JavaScript SDK","version":"1.1.7"},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","locale":"en-GB","os":{"name":"","version":""},"screen":{"density":2},"campaign":{},"page":{"path":"/Rectified.html","referrer":"http://localhost:1112/","search":"","title":"","url":"http://localhost:1112/Rectified.html"},"ip":"0.0.0.0","userID":"sampleUserOption"},"type":"track","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","originalTimestamp":"2020-11-04T13:21:09.712Z","anonymousId":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","userId":null,"event":"order completed","properties":{"path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"integrations":{"All":true},"sentAt":"2020-11-04T13:21:09.712Z"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"distinct_id":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","event":"order completed","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","properties":{"$set":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"$current_url":"http://localhost:1112/Rectified.html","$pathname":"/Rectified.html","$lib":"RudderLabs JavaScript SDK","$lib_version":"1.1.7","$time":"2020-11-04T13:21:09.712Z","$ip":"0.0.0.0","$timestamp":"2020-11-04T13:21:09.712Z","$anon_distinct_id":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","distinct_id":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","$screen_density":2,"$locale":"en-GB","$useragent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","$app_version":"1.1.7","$app_name":"RudderLabs JavaScript SDK","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","$os":"Mac OS","$browser":"Chrome","$browser_version":"86.0.4240.111","$host":"localhost:1112","path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"timestamp":"2020-11-04T13:21:09.712Z","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"capture"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog track call with custom event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com"}},"message":{"channel":"web","context":{"app":{"build":"1.0.0","name":"RudderLabs JavaScript SDK","namespace":"com.rudderlabs.javascript","version":"1.1.7"},"traits":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"library":{"name":"RudderLabs JavaScript SDK","version":"1.1.7"},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","locale":"en-GB","os":{"name":"","version":""},"screen":{"density":2},"campaign":{},"page":{"path":"/Rectified.html","referrer":"http://localhost:1112/","search":"","title":"","url":"http://localhost:1112/Rectified.html"},"ip":"0.0.0.0","userID":"sampleUserOption"},"type":"track","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","originalTimestamp":"2020-11-04T13:21:09.712Z","anonymousId":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","userId":123,"event":"order completed","properties":{"path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"integrations":{"All":true},"sentAt":"2020-11-04T13:21:09.712Z"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"distinct_id":"123","event":"order completed","messageId":"07cd68e5-9ad9-4a79-af51-f7118bc9ed71","properties":{"$set":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r1@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"$current_url":"http://localhost:1112/Rectified.html","$pathname":"/Rectified.html","$lib":"RudderLabs JavaScript SDK","$lib_version":"1.1.7","$time":"2020-11-04T13:21:09.712Z","$ip":"0.0.0.0","$timestamp":"2020-11-04T13:21:09.712Z","$anon_distinct_id":"a47b753d-c7d3-40ca-88dc-a1bb79e997e8","distinct_id":"123","$screen_density":2,"$locale":"en-GB","$useragent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","$app_version":"1.1.7","$app_name":"RudderLabs JavaScript SDK","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","$os":"Mac OS","$browser":"Chrome","$browser_version":"86.0.4240.111","$host":"localhost:1112","path":"path","referrer":"referrer","search":"search","KEY_3":{"CHILD_KEY_4":"value_3","CHILD_KEY_5":"value_4"},"title":"title","url":"url","total":1009,"products":[{"product_id":"507f1f77bcf86cd79943901ghh1","sku":"45790-38","name":"Monopoly: 7rd Edition","price":19,"position":"1","category":"Cars","quantity":4,"currency":"USD","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"},{"product_id":"507f1f77bcf86cd79943901gth1","sku":"45790-39","name":"Monopoly: 8th Edition","price":19,"quantity":2,"position":"1","currency":"USD","category":"Cars","url":"https://www.example.com/product/path","image_url":"https://www.example.com/product/path.jpg"}]},"timestamp":"2020-11-04T13:21:09.712Z","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"capture"},"XML":{},"JSON_ARRAY":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog group call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/","useV2Group":false}},"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":"chandra+r@rudderlabs.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},"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","anonymousId":"my-anonymous-id-new","userId":"sampleusrRudder7","integrations":{"All":true},"groupId":"Sample_groupId27","traits":{"groupType":"company","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"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"groupId":"Sample_groupId27","distinct_id":"sampleusrRudder7","traits":{"groupType":"company","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"},"messageId":"e5034df0-a404-47b4-a463-76df99934fea","properties":{"$set":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"$current_url":"https://docs.rudderstack.com/destinations/amplitude","$pathname":"/destinations/amplitude","$lib":"RudderLabs JavaScript SDK","$lib_version":"1.1.5","$anon_distinct_id":"my-anonymous-id-new","distinct_id":"sampleusrRudder7","$screen_density":0.8999999761581421,"$locale":"en-US","$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","$app_version":"1.1.5","$app_name":"RudderLabs JavaScript SDK","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","$os":"Mac OS","$browser":"Chrome","$browser_version":"85.0.4183.121","$host":"docs.rudderstack.com"},"event":"$groupidentify","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"group"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog group call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/","useV2Group":true}},"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":"chandra+r@rudderlabs.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},"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","anonymousId":"my-anonymous-id-new","userId":"sampleusrRudder7","integrations":{"All":true},"groupId":"Sample_groupId27","traits":{"groupType":"company","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"}}, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"properties":{"$set":{"name":"Shehan Study","category":"SampleIdentify","email":"chandra+r@rudderlabs.com","plan":"Open source","logins":5,"createdAt":1599264000},"$current_url":"https://docs.rudderstack.com/destinations/amplitude","$pathname":"/destinations/amplitude","$lib":"RudderLabs JavaScript SDK","$lib_version":"1.1.5","$anon_distinct_id":"my-anonymous-id-new","distinct_id":"sampleusrRudder7","$screen_density":0.8999999761581421,"$locale":"en-US","$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","$app_version":"1.1.5","$app_name":"RudderLabs JavaScript SDK","$app_namespace":"com.rudderlabs.javascript","$app_build":"1.0.0","$os":"Mac OS","$browser":"Chrome","$browser_version":"85.0.4183.121","$host":"docs.rudderstack.com","$group_key":"Sample_groupId27","$group_set":{"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","$groups":{"company":"Sample_groupId27"}},"distinct_id":"sampleusrRudder7","messageId":"e5034df0-a404-47b4-a463-76df99934fea","event":"$groupidentify","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"group"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog group call for all utm properties", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com/","useV2Group":true}},"message":{"channel":"web","context":{"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","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","loaded":"20"},"campaign":{"source":"google","medium":"medium","term":"keyword","content":"some content","name":"some campaign"}},"type":"group","messageId":"e50df0-a404-47b4-a463-76df99934fea","anonymousId":"newid@1234","userId":"user@1234","integrations":{"All":true},"groupId":"group@1234","traits":{"groupType":"company","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":"2022-08-12T07:54:58.983Z"}}, +const data = [ + { + name: 'posthog', + description: 'PostHog alias call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + }, + }, + message: { + event: 'event-alias', + context: { + ip: '0.0.0.0', + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { carrier: 'Banglalink' }, + os: { name: 'android', version: '8.1.0' }, + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.7', + }, + traits: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + type: 'alias', + timestamp: '2020-11-04T13:21:09.712Z', + userId: 'uid-1', + previousId: 'prevId_1', + anonymousId: 'f3cf54d8-f237-45d2-89f7-ccd70d42cf31', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + properties: { + $set: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + $os: 'android', + $time: '2020-11-04T13:21:09.712Z', + $device_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'f3cf54d8-f237-45d2-89f7-ccd70d42cf31', + distinct_id: 'prevId_1', + $device_manufacturer: 'Xiaomi', + $os_version: '8.1.0', + $app_version: '1.1.7', + $device_name: 'xiaomi', + $network_carrier: 'Banglalink', + $app_name: 'RudderLabs JavaScript SDK', + $device_model: 'Redmi 6', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + alias: 'uid-1', + }, + timestamp: '2020-11-04T13:21:09.712Z', + event: '$create_alias', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'alias', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { Config: { teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE' } }, + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + event: 'Product Brought', + context: { + ip: '0.0.0.0', + device: { + 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', + }, + }, + type: 'track', + properties: { + 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', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2020-11-04T13:21:09.712Z', + userId: 'uid-2', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + distinct_id: 'uid-2', + event: 'Product Brought', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + properties: { + $set: { + address: { city: 'Dhaka', country: 'Bangladesh' }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + $os: 'android', + $time: '2020-11-04T13:21:09.712Z', + $device_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + distinct_id: 'uid-2', + $device_manufacturer: 'Xiaomi', + $os_version: '8.1.0', + $device_name: 'xiaomi', + $network_carrier: 'Banglalink', + $device_model: 'Redmi 6', + 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', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2020-11-04T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.7', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.7' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + locale: 'en-GB', + os: { name: '', version: '' }, + screen: { density: 2 }, + campaign: {}, + page: { + path: '/Rectified.html', + referrer: 'http://localhost:1112/', + search: '', + title: '', + url: 'http://localhost:1112/Rectified.html', + }, + ip: '0.0.0.0', + userID: 'sampleUserOption', + }, + type: 'track', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + originalTimestamp: '2020-11-04T13:21:09.712Z', + anonymousId: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + userId: 'uid-3', + event: 'order completed', + properties: { + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + integrations: { All: true }, + sentAt: '2020-11-04T13:21:09.712Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + distinct_id: 'uid-3', + event: 'order completed', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + properties: { + $set: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + $current_url: 'http://localhost:1112/Rectified.html', + $pathname: '/Rectified.html', + $lib: 'RudderLabs JavaScript SDK', + $lib_version: '1.1.7', + $time: '2020-11-04T13:21:09.712Z', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + distinct_id: 'uid-3', + $screen_density: 2, + $locale: 'en-GB', + $useragent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + $app_version: '1.1.7', + $app_name: 'RudderLabs JavaScript SDK', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '86.0.4240.111', + $host: 'localhost:1112', + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"properties":{"$current_url":"https://docs.rudderstack.com/destinations/amplitude","$pathname":"/destinations/amplitude","$anon_distinct_id":"newid@1234","distinct_id":"user@1234","$locale":"en-US","$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","utm_source":"google","utm_medium":"medium","utm_campaign":"some campaign","utm_content":"some content","utm_term":"keyword","$performance_page_loaded":"20","$os":"Mac OS","$browser":"Chrome","$browser_version":"85.0.4183.121","$host":"docs.rudderstack.com","$group_key":"group@1234","$group_set":{"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","$groups":{"company":"group@1234"}},"distinct_id":"user@1234","messageId":"e50df0-a404-47b4-a463-76df99934fea","event":"$groupidentify","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"group"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "PostHog track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","yourInstance":"https://app.posthog.com"}},"message":{"channel":"web","context":{"traits":{"name":"Rudder Usr","category":"SampleIdentify","email":"mihirb@rudderlabs.com","plan":"Paid","logins":5},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","locale":"en-GB","page":{"path":"/Rectified.html","referrer":"http://localhost:1112/","url":"http://localhost:1112/Rectified.html","loaded":"40"},"userID":"user@2345"},"type":"track","messageId":"07cde5-9ad9-4a79-af51-f71bc9ed71","originalTimestamp":"2022-08-12T13:21:09.712Z","anonymousId":"a4753d-c7d3-40ca-88dc-a1bbe997e8","userId":"uid-1234","event":"card checkout","properties":{"path":"path","referrer":"referrer","search":"search","title":"title","url":"url","total":1009,"viewport_height":"173","viewport_width":"969"},"integrations":{"All":true},"sentAt":"2022-08-12T13:21:09.712Z"}}, + }, + timestamp: '2020-11-04T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: '4', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + }, + }, + message: { + type: 'screen', + event: 'HomePage', + sentAt: '2020-11-12T21:12:54.117Z', + userId: 'sajal', + channel: 'mobile', + context: { + os: { name: 'Android', version: '10' }, + app: { + name: 'AMTestProject', + build: '1', + version: '1.0', + namespace: 'com.rudderstack.android.rudderstack.sampleAndroidApp', + }, + device: { + id: '9c6bd77ea9da3e68', + name: 'raphaelin', + type: 'Android', + model: 'Redmi K20 Pro', + manufacturer: 'Xiaomi', + }, + locale: 'en-IN', + screen: { width: 1080, height: 2210, density: 440 }, + traits: { + id: 'sajal', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'sajal', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'Mohanta', + quantity: '5', + username: 'Samle_putUserName', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '1.0.8' }, + network: { wifi: true, carrier: 'airtel', cellular: true, bluetooth: false }, + timezone: 'Asia/Kolkata', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)', + }, + messageId: '1605215561320-917a2554-87fd-4f9e-881d-9d29e8f30490', + properties: { name: 'HomePage' }, + anonymousId: '9c6bd77ea9da3e68', + integrations: { All: true }, + originalTimestamp: '2020-11-12T21:12:41.320Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + properties: { + $set: { + id: 'sajal', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'sajal', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'Mohanta', + quantity: '5', + username: 'Samle_putUserName', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + $os: 'Android', + $screen_height: 2210, + $screen_width: 1080, + $lib: 'com.rudderstack.android.sdk.core', + $lib_version: '1.0.8', + $time: '2020-11-12T21:12:41.320Z', + $device_id: '9c6bd77ea9da3e68', + $timestamp: '2020-11-12T21:12:41.320Z', + $anon_distinct_id: '9c6bd77ea9da3e68', + distinct_id: 'sajal', + $screen_density: 440, + $device_manufacturer: 'Xiaomi', + $os_version: '10', + $timezone: 'Asia/Kolkata', + $locale: 'en-IN', + $useragent: + 'Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)', + $app_version: '1.0', + $device_name: 'raphaelin', + $network_carrier: 'airtel', + $app_name: 'AMTestProject', + $device_model: 'Redmi K20 Pro', + $app_namespace: 'com.rudderstack.android.rudderstack.sampleAndroidApp', + $app_build: '1', + $screen_name: 'HomePage', + name: 'HomePage', + }, + timestamp: '2020-11-12T21:12:41.320Z', + distinct_id: 'sajal', + messageId: '1605215561320-917a2554-87fd-4f9e-881d-9d29e8f30490', + event: '$screen', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'screen', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog identify call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + }, + }, + message: { + type: 'identify', + event: 'identify', + sentAt: '2020-11-12T21:12:54.117Z', + userId: 'sajal', + channel: 'mobile', + context: { + os: { name: 'Android', version: '10' }, + app: { + name: 'AMTestProject', + build: '1', + version: '1.0', + namespace: 'com.rudderstack.android.rudderstack.sampleAndroidApp', + }, + device: { + id: '9c6bd77ea9da3e68', + name: 'raphaelin', + type: 'Android', + model: 'Redmi K20 Pro', + manufacturer: 'Xiaomi', + }, + locale: 'en-IN', + screen: { width: 1080, height: 2210, density: 440 }, + traits: { + id: 'sajal', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'sajal', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'Mohanta', + quantity: '5', + username: 'Samle_putUserName', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '1.0.8' }, + network: { wifi: true, carrier: 'airtel', cellular: true, bluetooth: false }, + timezone: 'Asia/Kolkata', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)', + }, + messageId: '1605215561266-084c95fb-aaf6-4abf-9b3b-7ac449a2d4fb', + anonymousId: '9c6bd77ea9da3e68', + integrations: { All: true }, + originalTimestamp: '2020-11-12T21:12:41.266Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + distinct_id: 'sajal', + timestamp: '2020-11-12T21:12:41.266Z', + messageId: '1605215561266-084c95fb-aaf6-4abf-9b3b-7ac449a2d4fb', + $set: { + id: 'sajal', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'sajal', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'Mohanta', + quantity: '5', + username: 'Samle_putUserName', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + properties: { + $os: 'Android', + $screen_height: 2210, + $screen_width: 1080, + $lib: 'com.rudderstack.android.sdk.core', + $lib_version: '1.0.8', + $time: '2020-11-12T21:12:41.266Z', + $device_id: '9c6bd77ea9da3e68', + $timestamp: '2020-11-12T21:12:41.266Z', + $anon_distinct_id: '9c6bd77ea9da3e68', + distinct_id: 'sajal', + $screen_density: 440, + $device_manufacturer: 'Xiaomi', + $os_version: '10', + $timezone: 'Asia/Kolkata', + $locale: 'en-IN', + $useragent: + 'Dalvik/2.1.0 (Linux; U; Android 10; Redmi K20 Pro MIUI/V12.0.3.0.QFKINXM)', + $app_version: '1.0', + $device_name: 'raphaelin', + $network_carrier: 'airtel', + $app_name: 'AMTestProject', + $device_model: 'Redmi K20 Pro', + $app_namespace: 'com.rudderstack.android.rudderstack.sampleAndroidApp', + $app_build: '1', + }, + event: '$identify', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'identify', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog track call with custom event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.7', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.7' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + locale: 'en-GB', + os: { name: '', version: '' }, + screen: { density: 2 }, + campaign: {}, + page: { + path: '/Rectified.html', + referrer: 'http://localhost:1112/', + search: '', + title: '', + url: 'http://localhost:1112/Rectified.html', + }, + ip: '0.0.0.0', + userID: 'sampleUserOption', + }, + type: 'track', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + originalTimestamp: '2020-11-04T13:21:09.712Z', + anonymousId: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + userId: null, + event: 'order completed', + properties: { + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + integrations: { All: true }, + sentAt: '2020-11-04T13:21:09.712Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + distinct_id: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + event: 'order completed', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + properties: { + $set: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + $current_url: 'http://localhost:1112/Rectified.html', + $pathname: '/Rectified.html', + $lib: 'RudderLabs JavaScript SDK', + $lib_version: '1.1.7', + $time: '2020-11-04T13:21:09.712Z', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + distinct_id: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + $screen_density: 2, + $locale: 'en-GB', + $useragent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + $app_version: '1.1.7', + $app_name: 'RudderLabs JavaScript SDK', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '86.0.4240.111', + $host: 'localhost:1112', + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","params":{},"method":"POST","endpoint":"https://app.posthog.com/batch","headers":{"Content-Type":"application/json"},"body":{"XML":{},"FORM":{},"JSON":{"messageId":"07cde5-9ad9-4a79-af51-f71bc9ed71","distinct_id":"uid-1234","properties":{"$set":{"name":"Rudder Usr","category":"SampleIdentify","email":"mihirb@rudderlabs.com","plan":"Paid","logins":5},"$os":"Mac OS","url":"url","path":"path","$host":"localhost:1112","$time":"2022-08-12T13:21:09.712Z","$timestamp":"2022-08-12T13:21:09.712Z","title":"title","total":1009,"search":"search","$locale":"en-GB","$browser":"Chrome","referrer":"referrer","$pathname":"/Rectified.html","$useragent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","distinct_id":"uid-1234","$current_url":"http://localhost:1112/Rectified.html","$viewport_width":"969","$browser_version":"86.0.4240.111","$viewport_height":"173","$anon_distinct_id":"a4753d-c7d3-40ca-88dc-a1bbe997e8","$performance_page_loaded":"40","viewport_height":"173","viewport_width":"969"},"event":"card checkout","timestamp":"2022-08-12T13:21:09.712Z","api_key":"K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE","type":"capture"},"JSON_ARRAY":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "posthog", - "description": "Pass userTraits for track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"destination":{"Config":{"teamApiKey":"phc_HiQkvGt9vktokentokentokenTN","yourInstance":"https://app.posthog.com"}},"message":{"type":"track","event":"Product Brought","userId":"uid-2","context":{"ip":"0.0.0.0","os":{"name":"android","version":"8.1.0"},"device":{"id":"df16bffa-5c3d-4fbb-9bce-3bab098129a7R","name":"xiaomi","model":"Redmi 6","manufacturer":"Xiaomi"},"traits":{"id":"Virat KohliProX","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"Virat","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"KohliDa","quantity":"5","username":"Kohli_putUserName1","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"network":{"carrier":"Banglalink"}},"rudderId":"ee5c68e2-ecea-4aaf-a885-d0611eb8827b","messageId":"e4408cb8-16dd-41e9-a313-a7a9cdc4bac5","properties":{"isf":"False","idfa":"2bf99787-33d2-4ae2-a76a-c49672f97252","level":6,"game_id":"fireEagleBase","game_fps":30,"is_turbo":"False","battle_id":"N/A","bet_level":1,"game_name":"FireEagleSlots","bet_amount":9,"fb_profile":"0","no_of_spin":1,"start_date":"2019-08-01","win_amount":0,"extra_param":"N/A","gem_balance":0,"coin_balance":9466052,"days_in_game":0,"is_auto_spin":"False","ishighroller":"False","tournament_id":"T1561970819","bet_multiplier":1,"isLowEndDevice":"False","total_payments":0,"featureGameType":"N/A","graphicsQuality":"HD","jackpot_win_type":"Silver","jackpot_win_amount":90,"current_module_name":"CasinoGameModule","versionSessionCount":2,"additional_bet_index":0,"internetReachability":"ReachableViaLocalAreaNetwork","lifetime_gem_balance":0,"player_total_battles":0,"player_total_shields":0},"anonymousId":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1"}}, + }, + timestamp: '2020-11-04T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog track call with custom event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.7', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.7' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + locale: 'en-GB', + os: { name: '', version: '' }, + screen: { density: 2 }, + campaign: {}, + page: { + path: '/Rectified.html', + referrer: 'http://localhost:1112/', + search: '', + title: '', + url: 'http://localhost:1112/Rectified.html', + }, + ip: '0.0.0.0', + userID: 'sampleUserOption', + }, + type: 'track', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + originalTimestamp: '2020-11-04T13:21:09.712Z', + anonymousId: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + userId: 123, + event: 'order completed', + properties: { + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + integrations: { All: true }, + sentAt: '2020-11-04T13:21:09.712Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + distinct_id: '123', + event: 'order completed', + messageId: '07cd68e5-9ad9-4a79-af51-f7118bc9ed71', + properties: { + $set: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r1@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + $current_url: 'http://localhost:1112/Rectified.html', + $pathname: '/Rectified.html', + $lib: 'RudderLabs JavaScript SDK', + $lib_version: '1.1.7', + $time: '2020-11-04T13:21:09.712Z', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'a47b753d-c7d3-40ca-88dc-a1bb79e997e8', + distinct_id: '123', + $screen_density: 2, + $locale: 'en-GB', + $useragent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + $app_version: '1.1.7', + $app_name: 'RudderLabs JavaScript SDK', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '86.0.4240.111', + $host: 'localhost:1112', + path: 'path', + referrer: 'referrer', + search: 'search', + KEY_3: { CHILD_KEY_4: 'value_3', CHILD_KEY_5: 'value_4' }, + title: 'title', + url: 'url', + total: 1009, + products: [ + { + product_id: '507f1f77bcf86cd79943901ghh1', + sku: '45790-38', + name: 'Monopoly: 7rd Edition', + price: 19, + position: '1', + category: 'Cars', + quantity: 4, + currency: 'USD', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd79943901gth1', + sku: '45790-39', + name: 'Monopoly: 8th Edition', + price: 19, + quantity: 2, + position: '1', + currency: 'USD', + category: 'Cars', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{"type":"capture","event":"Product Brought","api_key":"phc_HiQkvGt9vktokentokentokenTN","messageId":"e4408cb8-16dd-41e9-a313-a7a9cdc4bac5","properties":{"$ip":"0.0.0.0","$os":"android","isf":"False","$set":{"id":"Virat KohliProX","age":"30","name":"User_id_identify","email":"identify@test.com","phone":"9112340345","price":"56.0","userId":"Virat","address":{"city":"KOlkata","state":"West bengal","street":"Park Street","country":"India","postalcode":"700096"},"birthday":"2020-11-13","lastname":"KohliDa","quantity":"5","username":"Kohli_putUserName1","createdat":"18th March 2020","firstname":"Sajal","anonymousId":"9c6bd77ea9da3e68","description":"Sample description"},"idfa":"2bf99787-33d2-4ae2-a76a-c49672f97252","level":6,"game_id":"fireEagleBase","game_fps":30,"is_turbo":"False","battle_id":"N/A","bet_level":1,"game_name":"FireEagleSlots","$device_id":"df16bffa-5c3d-4fbb-9bce-3bab098129a7R","bet_amount":9,"fb_profile":"0","no_of_spin":1,"start_date":"2019-08-01","win_amount":0,"$os_version":"8.1.0","distinct_id":"uid-2","extra_param":"N/A","gem_balance":0,"$device_name":"xiaomi","coin_balance":9466052,"days_in_game":0,"is_auto_spin":"False","ishighroller":"False","$device_model":"Redmi 6","tournament_id":"T1561970819","bet_multiplier":1,"isLowEndDevice":"False","total_payments":0,"featureGameType":"N/A","graphicsQuality":"HD","$network_carrier":"Banglalink","jackpot_win_type":"Silver","$anon_distinct_id":"c82cbdff-e5be-4009-ac78-cdeea09ab4b1","jackpot_win_amount":90,"current_module_name":"CasinoGameModule","versionSessionCount":2,"$device_manufacturer":"Xiaomi","additional_bet_index":0,"internetReachability":"ReachableViaLocalAreaNetwork","lifetime_gem_balance":0,"player_total_battles":0,"player_total_shields":0},"distinct_id":"uid-2"},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"POST","params":{},"headers":{"Content-Type":"application/json"},"version":"1","endpoint":"https://app.posthog.com/batch","userId":""}, - "statusCode": 200}] - } - } - }]; module.exports = { - data - } \ No newline at end of file + }, + timestamp: '2020-11-04T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', + }, + XML: {}, + JSON_ARRAY: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog group call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + useV2Group: false, + }, + }, + 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: 'chandra+r@rudderlabs.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 }, + 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', + anonymousId: 'my-anonymous-id-new', + userId: 'sampleusrRudder7', + integrations: { All: true }, + groupId: 'Sample_groupId27', + traits: { + groupType: 'company', + 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', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + groupId: 'Sample_groupId27', + distinct_id: 'sampleusrRudder7', + traits: { + groupType: 'company', + 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', + }, + messageId: 'e5034df0-a404-47b4-a463-76df99934fea', + properties: { + $set: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + $current_url: 'https://docs.rudderstack.com/destinations/amplitude', + $pathname: '/destinations/amplitude', + $lib: 'RudderLabs JavaScript SDK', + $lib_version: '1.1.5', + $anon_distinct_id: 'my-anonymous-id-new', + distinct_id: 'sampleusrRudder7', + $screen_density: 0.8999999761581421, + $locale: 'en-US', + $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', + $app_version: '1.1.5', + $app_name: 'RudderLabs JavaScript SDK', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '85.0.4183.121', + $host: 'docs.rudderstack.com', + }, + event: '$groupidentify', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'group', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog group call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + useV2Group: true, + }, + }, + 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: 'chandra+r@rudderlabs.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 }, + 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', + anonymousId: 'my-anonymous-id-new', + userId: 'sampleusrRudder7', + integrations: { All: true }, + groupId: 'Sample_groupId27', + traits: { + groupType: 'company', + 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', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + properties: { + $set: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r@rudderlabs.com', + plan: 'Open source', + logins: 5, + createdAt: 1599264000, + }, + $current_url: 'https://docs.rudderstack.com/destinations/amplitude', + $pathname: '/destinations/amplitude', + $lib: 'RudderLabs JavaScript SDK', + $lib_version: '1.1.5', + $anon_distinct_id: 'my-anonymous-id-new', + distinct_id: 'sampleusrRudder7', + $screen_density: 0.8999999761581421, + $locale: 'en-US', + $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', + $app_version: '1.1.5', + $app_name: 'RudderLabs JavaScript SDK', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '85.0.4183.121', + $host: 'docs.rudderstack.com', + $group_key: 'Sample_groupId27', + $group_set: { + 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', + $groups: { company: 'Sample_groupId27' }, + }, + distinct_id: 'sampleusrRudder7', + messageId: 'e5034df0-a404-47b4-a463-76df99934fea', + event: '$groupidentify', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'group', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog group call for all utm properties', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + useV2Group: true, + }, + }, + message: { + channel: 'web', + context: { + 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', + 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', + loaded: '20', + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + }, + type: 'group', + messageId: 'e50df0-a404-47b4-a463-76df99934fea', + anonymousId: 'newid@1234', + userId: 'user@1234', + integrations: { All: true }, + groupId: 'group@1234', + traits: { + groupType: 'company', + 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: '2022-08-12T07:54:58.983Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + properties: { + $current_url: 'https://docs.rudderstack.com/destinations/amplitude', + $pathname: '/destinations/amplitude', + $anon_distinct_id: 'newid@1234', + distinct_id: 'user@1234', + $locale: 'en-US', + $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', + utm_source: 'google', + utm_medium: 'medium', + utm_campaign: 'some campaign', + utm_content: 'some content', + utm_term: 'keyword', + $performance_page_loaded: '20', + $os: 'Mac OS', + $browser: 'Chrome', + $browser_version: '85.0.4183.121', + $host: 'docs.rudderstack.com', + $group_key: 'group@1234', + $group_set: { + 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', + $groups: { company: 'group@1234' }, + }, + distinct_id: 'user@1234', + messageId: 'e50df0-a404-47b4-a463-76df99934fea', + event: '$groupidentify', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'group', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'PostHog track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com', + }, + }, + message: { + channel: 'web', + context: { + traits: { + name: 'Rudder Usr', + category: 'SampleIdentify', + email: 'mihirb@rudderlabs.com', + plan: 'Paid', + logins: 5, + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + locale: 'en-GB', + page: { + path: '/Rectified.html', + referrer: 'http://localhost:1112/', + url: 'http://localhost:1112/Rectified.html', + loaded: '40', + }, + userID: 'user@2345', + }, + type: 'track', + messageId: '07cde5-9ad9-4a79-af51-f71bc9ed71', + originalTimestamp: '2022-08-12T13:21:09.712Z', + anonymousId: 'a4753d-c7d3-40ca-88dc-a1bbe997e8', + userId: 'uid-1234', + event: 'card checkout', + properties: { + path: 'path', + referrer: 'referrer', + search: 'search', + title: 'title', + url: 'url', + total: 1009, + viewport_height: '173', + viewport_width: '969', + }, + integrations: { All: true }, + sentAt: '2022-08-12T13:21:09.712Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + params: {}, + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { 'Content-Type': 'application/json' }, + body: { + XML: {}, + FORM: {}, + JSON: { + messageId: '07cde5-9ad9-4a79-af51-f71bc9ed71', + distinct_id: 'uid-1234', + properties: { + $set: { + name: 'Rudder Usr', + category: 'SampleIdentify', + email: 'mihirb@rudderlabs.com', + plan: 'Paid', + logins: 5, + }, + $os: 'Mac OS', + url: 'url', + path: 'path', + $host: 'localhost:1112', + $time: '2022-08-12T13:21:09.712Z', + $timestamp: '2022-08-12T13:21:09.712Z', + title: 'title', + total: 1009, + search: 'search', + $locale: 'en-GB', + $browser: 'Chrome', + referrer: 'referrer', + $pathname: '/Rectified.html', + $useragent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + distinct_id: 'uid-1234', + $current_url: 'http://localhost:1112/Rectified.html', + $viewport_width: '969', + $browser_version: '86.0.4240.111', + $viewport_height: '173', + $anon_distinct_id: 'a4753d-c7d3-40ca-88dc-a1bbe997e8', + $performance_page_loaded: '40', + viewport_height: '173', + viewport_width: '969', + }, + event: 'card checkout', + timestamp: '2022-08-12T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', + }, + JSON_ARRAY: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'posthog', + description: 'Pass userTraits for track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + teamApiKey: 'phc_HiQkvGt9vktokentokentokenTN', + yourInstance: 'https://app.posthog.com', + }, + }, + message: { + type: 'track', + event: 'Product Brought', + userId: 'uid-2', + context: { + ip: '0.0.0.0', + os: { name: 'android', version: '8.1.0' }, + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + name: 'xiaomi', + model: 'Redmi 6', + manufacturer: 'Xiaomi', + }, + traits: { + id: 'Virat KohliProX', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'Virat', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'KohliDa', + quantity: '5', + username: 'Kohli_putUserName1', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + network: { carrier: 'Banglalink' }, + }, + rudderId: 'ee5c68e2-ecea-4aaf-a885-d0611eb8827b', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + properties: { + isf: 'False', + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + level: 6, + game_id: 'fireEagleBase', + game_fps: 30, + is_turbo: 'False', + battle_id: 'N/A', + bet_level: 1, + game_name: 'FireEagleSlots', + bet_amount: 9, + fb_profile: '0', + no_of_spin: 1, + start_date: '2019-08-01', + win_amount: 0, + extra_param: 'N/A', + gem_balance: 0, + coin_balance: 9466052, + days_in_game: 0, + is_auto_spin: 'False', + ishighroller: 'False', + tournament_id: 'T1561970819', + bet_multiplier: 1, + isLowEndDevice: 'False', + total_payments: 0, + featureGameType: 'N/A', + graphicsQuality: 'HD', + jackpot_win_type: 'Silver', + jackpot_win_amount: 90, + current_module_name: 'CasinoGameModule', + versionSessionCount: 2, + additional_bet_index: 0, + internetReachability: 'ReachableViaLocalAreaNetwork', + lifetime_gem_balance: 0, + player_total_battles: 0, + player_total_shields: 0, + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + type: 'capture', + event: 'Product Brought', + api_key: 'phc_HiQkvGt9vktokentokentokenTN', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + properties: { + $ip: '0.0.0.0', + $os: 'android', + isf: 'False', + $set: { + id: 'Virat KohliProX', + age: '30', + name: 'User_id_identify', + email: 'identify@test.com', + phone: '9112340345', + price: '56.0', + userId: 'Virat', + address: { + city: 'KOlkata', + state: 'West bengal', + street: 'Park Street', + country: 'India', + postalcode: '700096', + }, + birthday: '2020-11-13', + lastname: 'KohliDa', + quantity: '5', + username: 'Kohli_putUserName1', + createdat: '18th March 2020', + firstname: 'Sajal', + anonymousId: '9c6bd77ea9da3e68', + description: 'Sample description', + }, + idfa: '2bf99787-33d2-4ae2-a76a-c49672f97252', + level: 6, + game_id: 'fireEagleBase', + game_fps: 30, + is_turbo: 'False', + battle_id: 'N/A', + bet_level: 1, + game_name: 'FireEagleSlots', + $device_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + bet_amount: 9, + fb_profile: '0', + no_of_spin: 1, + start_date: '2019-08-01', + win_amount: 0, + $os_version: '8.1.0', + distinct_id: 'uid-2', + extra_param: 'N/A', + gem_balance: 0, + $device_name: 'xiaomi', + coin_balance: 9466052, + days_in_game: 0, + is_auto_spin: 'False', + ishighroller: 'False', + $device_model: 'Redmi 6', + tournament_id: 'T1561970819', + bet_multiplier: 1, + isLowEndDevice: 'False', + total_payments: 0, + featureGameType: 'N/A', + graphicsQuality: 'HD', + $network_carrier: 'Banglalink', + jackpot_win_type: 'Silver', + $anon_distinct_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + jackpot_win_amount: 90, + current_module_name: 'CasinoGameModule', + versionSessionCount: 2, + $device_manufacturer: 'Xiaomi', + additional_bet_index: 0, + internetReachability: 'ReachableViaLocalAreaNetwork', + lifetime_gem_balance: 0, + player_total_battles: 0, + player_total_shields: 0, + }, + distinct_id: 'uid-2', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { 'Content-Type': 'application/json' }, + version: '1', + endpoint: 'https://app.posthog.com/batch', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/posthog/router/data.js b/test/integrations/destinations/posthog/router/data.js index d7be79dbc153..095747084149 100644 --- a/test/integrations/destinations/posthog/router/data.js +++ b/test/integrations/destinations/posthog/router/data.js @@ -1,345 +1,345 @@ const data = [ { - "name": "posthog", - "description": "Successfull Alias Call batching", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "teamApiKey": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE", - "yourInstance": "https://app.posthog.com/" - } - }, - "metadata": { - "jobId": 2 + name: 'posthog', + description: 'Successfull Alias Call batching', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', }, - "message": { - "event": "event-alias", - "context": { - "ip": "0.0.0.0", - "device": { - "id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "manufacturer": "Xiaomi", - "model": "Redmi 6", - "name": "xiaomi" - }, - "network": { - "carrier": "Banglalink" - }, - "os": { - "name": "android", - "version": "8.1.0" - }, - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.1.7" + }, + metadata: { + jobId: 2, + }, + message: { + event: 'event-alias', + context: { + ip: '0.0.0.0', + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', + }, + os: { + name: 'android', + version: '8.1.0', + }, + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.7', + }, + traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', }, - "traits": { - "address": { - "city": "Dhaka", - "country": "Bangladesh" - }, - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" - } + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "type": "alias", - "timestamp": "2020-11-04T13:21:09.712Z", - "userId": "uid-1", - "previousId": "prevId_1", - "anonymousId": "f3cf54d8-f237-45d2-89f7-ccd70d42cf31" - } - }] - , "destType": "posthog" + }, + type: 'alias', + timestamp: '2020-11-04T13:21:09.712Z', + userId: 'uid-1', + previousId: 'prevId_1', + anonymousId: 'f3cf54d8-f237-45d2-89f7-ccd70d42cf31', + }, + }, + ], + destType: 'posthog', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", - "userId": "", - "method": "POST", - "endpoint": "https://app.posthog.com/batch", - "headers": { - "Content-Type": "application/json" + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { + 'Content-Type': 'application/json', }, - "params": {}, - "body": { - "JSON": { - "properties": { - "$set": { - "address": { - "city": "Dhaka", - "country": "Bangladesh" + params: {}, + body: { + JSON: { + properties: { + $set: { + address: { + city: 'Dhaka', + country: 'Bangladesh', }, - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "$os": "android", - "$time": "2020-11-04T13:21:09.712Z", - "$device_id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "$ip": "0.0.0.0", - "$timestamp": "2020-11-04T13:21:09.712Z", - "$anon_distinct_id": "f3cf54d8-f237-45d2-89f7-ccd70d42cf31", - "distinct_id": "prevId_1", - "$device_manufacturer": "Xiaomi", - "$os_version": "8.1.0", - "$app_version": "1.1.7", - "$device_name": "xiaomi", - "$network_carrier": "Banglalink", - "$app_name": "RudderLabs JavaScript SDK", - "$device_model": "Redmi 6", - "$app_namespace": "com.rudderlabs.javascript", - "$app_build": "1.0.0", - "alias": "uid-1" + $os: 'android', + $time: '2020-11-04T13:21:09.712Z', + $device_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'f3cf54d8-f237-45d2-89f7-ccd70d42cf31', + distinct_id: 'prevId_1', + $device_manufacturer: 'Xiaomi', + $os_version: '8.1.0', + $app_version: '1.1.7', + $device_name: 'xiaomi', + $network_carrier: 'Banglalink', + $app_name: 'RudderLabs JavaScript SDK', + $device_model: 'Redmi 6', + $app_namespace: 'com.rudderlabs.javascript', + $app_build: '1.0.0', + alias: 'uid-1', }, - "timestamp": "2020-11-04T13:21:09.712Z", - "event": "$create_alias", - "api_key": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE", - "type": "alias" + timestamp: '2020-11-04T13:21:09.712Z', + event: '$create_alias', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'alias', }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} + XML: {}, + JSON_ARRAY: {}, + FORM: {}, }, - "files": {} + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "teamApiKey": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE", - "yourInstance": "https://app.posthog.com/" - } - } - } - ] - } - } - } + batched: false, + statusCode: 200, + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + yourInstance: 'https://app.posthog.com/', + }, + }, + }, + ], + }, + }, + }, }, { - "name": "posthog", - "description": "Succesfull Track Call of event Product Brought", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "teamApiKey": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE" - } - }, - "metadata": { - "jobId": 2 + name: 'posthog', + description: 'Succesfull Track Call of event Product Brought', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', }, - "message": { - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "event": "Product Brought", - "context": { - "ip": "0.0.0.0", - "device": { - "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" - } + }, + metadata: { + jobId: 2, + }, + message: { + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + event: 'Product Brought', + context: { + ip: '0.0.0.0', + device: { + id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + manufacturer: 'Xiaomi', + model: 'Redmi 6', + name: 'xiaomi', + }, + network: { + carrier: 'Banglalink', }, - "type": "track", - "properties": { - "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", - "versionSessionCount": 2, - "win_amount": 0 + os: { + name: 'android', + version: '8.1.0', + }, + traits: { + address: { + city: 'Dhaka', + country: 'Bangladesh', + }, + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "timestamp": "2020-11-04T13:21:09.712Z", - "userId": "uid-2", - "messageId": "e4408cb8-16dd-41e9-a313-a7a9cdc4bac5" - } - }] - , "destType": "posthog" + }, + type: 'track', + properties: { + 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', + versionSessionCount: 2, + win_amount: 0, + }, + timestamp: '2020-11-04T13:21:09.712Z', + userId: 'uid-2', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + }, + }, + ], + destType: 'posthog', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", - "userId": "", - "method": "POST", - "endpoint": "https://app.posthog.com/batch", - "headers": { - "Content-Type": "application/json" + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: 'https://app.posthog.com/batch', + headers: { + 'Content-Type': 'application/json', }, - "params": {}, - "body": { - "JSON": { - "distinct_id": "uid-2", - "event": "Product Brought", - "messageId": "e4408cb8-16dd-41e9-a313-a7a9cdc4bac5", - "properties": { - "$set": { - "address": { - "city": "Dhaka", - "country": "Bangladesh" + params: {}, + body: { + JSON: { + distinct_id: 'uid-2', + event: 'Product Brought', + messageId: 'e4408cb8-16dd-41e9-a313-a7a9cdc4bac5', + properties: { + $set: { + address: { + city: 'Dhaka', + country: 'Bangladesh', }, - "anonymousId": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1" + anonymousId: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', }, - "$os": "android", - "$time": "2020-11-04T13:21:09.712Z", - "$device_id": "df16bffa-5c3d-4fbb-9bce-3bab098129a7R", - "$ip": "0.0.0.0", - "$timestamp": "2020-11-04T13:21:09.712Z", - "$anon_distinct_id": "c82cbdff-e5be-4009-ac78-cdeea09ab4b1", - "distinct_id": "uid-2", - "$device_manufacturer": "Xiaomi", - "$os_version": "8.1.0", - "$device_name": "xiaomi", - "$network_carrier": "Banglalink", - "$device_model": "Redmi 6", - "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", - "versionSessionCount": 2, - "win_amount": 0 + $os: 'android', + $time: '2020-11-04T13:21:09.712Z', + $device_id: 'df16bffa-5c3d-4fbb-9bce-3bab098129a7R', + $ip: '0.0.0.0', + $timestamp: '2020-11-04T13:21:09.712Z', + $anon_distinct_id: 'c82cbdff-e5be-4009-ac78-cdeea09ab4b1', + distinct_id: 'uid-2', + $device_manufacturer: 'Xiaomi', + $os_version: '8.1.0', + $device_name: 'xiaomi', + $network_carrier: 'Banglalink', + $device_model: 'Redmi 6', + 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', + versionSessionCount: 2, + win_amount: 0, }, - "timestamp": "2020-11-04T13:21:09.712Z", - "api_key": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE", - "type": "capture" + timestamp: '2020-11-04T13:21:09.712Z', + api_key: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + type: 'capture', }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} + XML: {}, + JSON_ARRAY: {}, + FORM: {}, }, - "files": {} + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "teamApiKey": "K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE" - } - } - } - ] - } - } - } - } + batched: false, + statusCode: 200, + destination: { + Config: { + teamApiKey: 'K_HlByO3IE73-Tz4ch1LNDs0JGdwbknNGolFc4HdoAE', + }, + }, + }, + ], + }, + }, + }, + }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/refiner/processor/data.js b/test/integrations/destinations/refiner/processor/data.js index 7ed0f302e5d2..bc97629b0aff 100644 --- a/test/integrations/destinations/refiner/processor/data.js +++ b/test/integrations/destinations/refiner/processor/data.js @@ -1,235 +1,719 @@ -const data = [{ - "name": "refiner", - "description": "No Message type", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "sentAt": "2022-10-11T13:10:54.877+05:30", "userId": "user@45", "context": { "traits": { "age": "30", "city": "Banglore", "email": "test@user.com", "phone": "7267286346802347827", "address": { "city": "ahmedabad", "state": "india" }, "lastName": "user", "username": "testUser", "firstName": "test", "userCountry": "india" } }, "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", "messageId": "b6ce7f31-5d76-4240-94d2-3eea020ef791", "timestamp": "2022-10-11T13:10:52.137+05:30", "receivedAt": "2022-10-11T13:10:52.138+05:30", "request_ip": "[::1]", "originalTimestamp": "2022-10-11T13:10:54.877+05:30" }, "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } }, - "error": "Event type is required", "statTags": { - "destType": "REFINER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", +const data = [ + { + name: 'refiner', + description: 'No Message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + sentAt: '2022-10-11T13:10:54.877+05:30', + userId: 'user@45', + context: { + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + address: { city: 'ahmedabad', state: 'india' }, + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', }, - "statusCode": 400 - }] - } - } -}, { - "name": "refiner", - "description": "Unsupported Event type ", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "alias", "sentAt": "2022-10-11T13:10:54.877+05:30", "userId": "user@45", "context": { "traits": { "age": "30", "city": "Banglore", "email": "test@user.com", "phone": "7267286346802347827", "address": { "city": "ahmedabad", "state": "india" }, "lastName": "user", "username": "testUser", "firstName": "test", "userCountry": "india" } }, "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", "messageId": "b6ce7f31-5d76-4240-94d2-3eea020ef791", "timestamp": "2022-10-11T13:10:52.137+05:30", "receivedAt": "2022-10-11T13:10:52.138+05:30", "request_ip": "[::1]", "originalTimestamp": "2022-10-11T13:10:54.877+05:30" }, "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } }, - "error": "Event type \"alias\" is not supported", "statTags": { - "destType": "REFINER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: 'b6ce7f31-5d76-4240-94d2-3eea020ef791', + timestamp: '2022-10-11T13:10:52.137+05:30', + receivedAt: '2022-10-11T13:10:52.138+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:10:54.877+05:30', + }, + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + error: 'Event type is required', + statTags: { + destType: 'REFINER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'Unsupported Event type ', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'alias', + sentAt: '2022-10-11T13:10:54.877+05:30', + userId: 'user@45', + context: { + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + address: { city: 'ahmedabad', state: 'india' }, + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', }, - "statusCode": 400 - }] - } - } -}, { - "name": "refiner", - "description": "userId and email is not present", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "identify", "sentAt": "2022-10-11T13:10:54.877+05:30", "context": { "traits": { "age": "30", "city": "Banglore", "phone": "7267286346802347827", "address": { "city": "ahmedabad", "state": "india" }, "lastName": "user", "username": "testUser", "firstName": "test", "userCountry": "india" } }, "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", "messageId": "b6ce7f31-5d76-4240-94d2-3eea020ef791", "timestamp": "2022-10-11T13:10:52.137+05:30", "receivedAt": "2022-10-11T13:10:52.138+05:30", "request_ip": "[::1]", "originalTimestamp": "2022-10-11T13:10:54.877+05:30" }, "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } }, - "error": "At least one of `userId` or `email` is required", "statTags": { - "destType": "REFINER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: 'b6ce7f31-5d76-4240-94d2-3eea020ef791', + timestamp: '2022-10-11T13:10:52.137+05:30', + receivedAt: '2022-10-11T13:10:52.138+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:10:54.877+05:30', + }, + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + error: 'Event type "alias" is not supported', + statTags: { + destType: 'REFINER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'userId and email is not present', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + sentAt: '2022-10-11T13:10:54.877+05:30', + context: { + traits: { + age: '30', + city: 'Banglore', + phone: '7267286346802347827', + address: { city: 'ahmedabad', state: 'india' }, + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', + }, + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: 'b6ce7f31-5d76-4240-94d2-3eea020ef791', + timestamp: '2022-10-11T13:10:52.137+05:30', + receivedAt: '2022-10-11T13:10:52.138+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:10:54.877+05:30', + }, + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + error: 'At least one of `userId` or `email` is required', + statTags: { + destType: 'REFINER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'event name is not present', + 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.1.2', }, - "statusCode": 400 - }] - } - } -}, { - "name": "refiner", - "description": "event name is not present", - "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.1.2" }, "traits": { "age": "30", "email": "test@user.com", "phone": "7267286346802347827", "city": "Banglore", "userCountry": "india", "lastName": "user", "username": "testUser", "firstName": "test" }, "library": { "name": "RudderLabs JavaScript SDK", "version": "1.1.2" }, "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", "locale": "en-GB", "os": { "name": "", "version": "" }, "screen": { "density": 2 }, "page": { "path": "/tests/html/ecomm_test.html", "referrer": "http://0.0.0.0:1112/tests/html/", "search": "", "title": "Fb Offline Conversion Ecommerce Test", "url": "http://0.0.0.0:1112/tests/html/ecomm_test.html" } }, "type": "track", "messageId": "9116b734-7e6b-4497-ab51-c16744d4487e", "userId": "user@45", "properties": { "order_id": "5241735", "coupon": "APPARELSALE", "currency": "IND", "products": [{ "id": "product-bacon-jam", "category": "Merch", "brand": "" }, { "id": "product-t-shirt", "category": "Merch", "brand": "Levis" }, { "id": "offer-t-shirt", "category": "Merch", "brand": "Levis" }] } }, "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "da70166e-05a3-4fa2-bb1d-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665474171943, "eventFilteringOption": "disable", "whitelistedEvents": [{ "eventName": "" }] } }, - "error": "Event name is required", "statTags": { - "destType": "REFINER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", + traits: { + age: '30', + email: 'test@user.com', + phone: '7267286346802347827', + city: 'Banglore', + userCountry: 'india', + lastName: 'user', + username: 'testUser', + firstName: 'test', + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.2' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36', + locale: 'en-GB', + os: { name: '', version: '' }, + screen: { density: 2 }, + page: { + path: '/tests/html/ecomm_test.html', + referrer: 'http://0.0.0.0:1112/tests/html/', + search: '', + title: 'Fb Offline Conversion Ecommerce Test', + url: 'http://0.0.0.0:1112/tests/html/ecomm_test.html', + }, + }, + type: 'track', + messageId: '9116b734-7e6b-4497-ab51-c16744d4487e', + userId: 'user@45', + properties: { + order_id: '5241735', + coupon: 'APPARELSALE', + currency: 'IND', + products: [ + { id: 'product-bacon-jam', category: 'Merch', brand: '' }, + { id: 'product-t-shirt', category: 'Merch', brand: 'Levis' }, + { id: 'offer-t-shirt', category: 'Merch', brand: 'Levis' }, + ], + }, + }, + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'da70166e-05a3-4fa2-bb1d-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665474171943, + eventFilteringOption: 'disable', + whitelistedEvents: [{ eventName: '' }], + }, + }, + error: 'Event name is required', + statTags: { + destType: 'REFINER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'successful identify call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'identify', + sentAt: '2022-10-11T13:10:54.877+05:30', + userId: 'user@45', + context: { + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + address: { city: 'ahmedabad', state: 'india' }, + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', + }, + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: 'b6ce7f31-5d76-4240-94d2-3eea020ef791', + timestamp: '2022-10-11T13:10:52.137+05:30', + receivedAt: '2022-10-11T13:10:52.138+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:10:54.877+05:30', + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.refiner.io/v1/identify-user', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + userId: 'user@45', + lastName: 'user', + username: 'testUser', + firstName: 'test', + userAddress: { city: 'ahmedabad', state: 'india' }, + userCountry: 'india', }, - "statusCode": 400 - }] - } - } -}, { - "name": "refiner", - "description": "successful identify call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "identify", "sentAt": "2022-10-11T13:10:54.877+05:30", "userId": "user@45", "context": { "traits": { "age": "30", "city": "Banglore", "email": "test@user.com", "phone": "7267286346802347827", "address": { "city": "ahmedabad", "state": "india" }, "lastName": "user", "username": "testUser", "firstName": "test", "userCountry": "india" } }, "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", "messageId": "b6ce7f31-5d76-4240-94d2-3eea020ef791", "timestamp": "2022-10-11T13:10:52.137+05:30", "receivedAt": "2022-10-11T13:10:52.138+05:30", "request_ip": "[::1]", "originalTimestamp": "2022-10-11T13:10:54.877+05:30" }, "destination": { "Config": { "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665475307930, "eventFilteringOption": "disable", "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.refiner.io/v1/identify-user", "headers": { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4" }, "params": {}, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": { "age": "30", "city": "Banglore", "email": "test@user.com", "phone": "7267286346802347827", "userId": "user@45", "lastName": "user", "username": "testUser", "firstName": "test", "userAddress": { "city": "ahmedabad", "state": "india" }, "userCountry": "india" } }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "refiner", - "description": "successful track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "track", "event": "Product Searched", "sentAt": "2022-10-11T13:38:31.827+05:30", "userId": "user@45", "channel": "web", "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.2", "namespace": "com.rudderlabs.javascript" }, "page": { "url": "http://0.0.0.0:1112/tests/html/ecomm_test.html", "path": "/tests/html/ecomm_test.html", "title": "Fb Offline Conversion Ecommerce Test", "search": "", "referrer": "http://0.0.0.0:1112/tests/html/" }, "locale": "en-GB", "screen": { "density": 2 }, "traits": { "age": "30", "city": "Banglore", "email": "test@user.com", "phone": "7267286346802347827", "lastName": "user", "username": "testUser", "firstName": "test", "userCountry": "india" }, "library": { "name": "RudderLabs JavaScript SDK", "version": "1.1.2" }, "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36" }, "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", "messageId": "9116b734-7e6b-4497-ab51-c16744d4487e", "timestamp": "2022-10-11T13:38:29.177+05:30", "properties": { "coupon": "APPARELSALE", "currency": "IND", "order_id": "5241735", "products": [{ "id": "product-bacon-jam", "category": "Merch", "brand": "" }, { "id": "product-t-shirt", "category": "Merch", "brand": "Levis" }, { "id": "offer-t-shirt", "category": "Merch", "brand": "Levis" }] }, "receivedAt": "2022-10-11T13:38:29.178+05:30", "request_ip": "[::1]", "originalTimestamp": "2022-10-11T13:38:31.827+05:30" }, "destination": { "Config": { "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665475307930, "eventFilteringOption": "disable", "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": { "id": "user@45", "email": "test@user.com", "event": "Product Searched" }, "JSON": {}, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4" }, "version": "1", "endpoint": "https://api.refiner.io/v1/track", "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "refiner", - "description": "successful group call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "group", "sentAt": "2015-02-23T22:28:55.111Z", "traits": { "name": "rudder ventures", "email": "business@rudderstack.com" }, "userId": "test@12", "channel": "browser", "context": { "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" }, "groupId": "group@123", "rudderId": "d944be7a-c870-41ba-9fa5-f3c9dbf5f7e0", "messageId": "022bb90c-bbac-11e4-8dfc-aa07a5b093db", "request_ip": "[::1]", "integrations": { "All": true }, "originalTimestamp": "2022-10-11T13:51:00.906+05:30" }, "destination": { "Config": { "accountAttributesMapping": [{ "from": "email", "to": "businessEmail" }], "apiKey": "dc70156e-05a3-4fa1-bb1c-da767fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665476456112, "eventFilteringOption": "disable", "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.refiner.io/v1/identify-user", "headers": { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4" }, "params": {}, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": { "id": "test@12", "account[businessEmail]": "business@rudderstack.com", "account[id]": "group@123", "account[name]": "rudder ventures" } }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "refiner", - "description": "Refiner page call", - "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" }, "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": "page", "messageId": "5e10d13a-bf9a-44bf-b884-43a9e591ea71", "timestamp": "2019-09-01T15:46:51.693229+05:30", "anonymousId": "00000000000000000000000000", "userId": "12345", "properties": { "path": "/abc", "referrer": "xyz", "search": "def", "title": "ghi", "url": "jkl" }, "integrations": { "All": true }, "name": "pageviewed", "sentAt": "2019-10-14T11:15:53.296Z" }, "destination": { "Config": { "accountAttributesMapping": [{ "from": "email", "to": "businessEmail" }], "apiKey": "dc70156e-05a3-4fa1-bb1c-da767fd036b4", "blacklistedEvents": [{ "eventName": "" }], "eventDelivery": true, "eventDeliveryTS": 1665476456112, "eventFilteringOption": "disable", "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], "whitelistedEvents": [{ "eventName": "" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": { "id": "12345", "event": "Viewed pageviewed Page" }, "JSON": {}, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4" }, "version": "1", "endpoint": "https://api.refiner.io/v1/track", "userId": "" }, - "statusCode": 200 - }] - } - } -}]; module.exports = { - data -} \ No newline at end of file + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'successful track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'track', + event: 'Product Searched', + sentAt: '2022-10-11T13:38:31.827+05:30', + userId: 'user@45', + channel: 'web', + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.2', + namespace: 'com.rudderlabs.javascript', + }, + page: { + url: 'http://0.0.0.0:1112/tests/html/ecomm_test.html', + path: '/tests/html/ecomm_test.html', + title: 'Fb Offline Conversion Ecommerce Test', + search: '', + referrer: 'http://0.0.0.0:1112/tests/html/', + }, + locale: 'en-GB', + screen: { density: 2 }, + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', + }, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.2' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36', + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: '9116b734-7e6b-4497-ab51-c16744d4487e', + timestamp: '2022-10-11T13:38:29.177+05:30', + properties: { + coupon: 'APPARELSALE', + currency: 'IND', + order_id: '5241735', + products: [ + { id: 'product-bacon-jam', category: 'Merch', brand: '' }, + { id: 'product-t-shirt', category: 'Merch', brand: 'Levis' }, + { id: 'offer-t-shirt', category: 'Merch', brand: 'Levis' }, + ], + }, + receivedAt: '2022-10-11T13:38:29.178+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:38:31.827+05:30', + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: { id: 'user@45', email: 'test@user.com', event: 'Product Searched' }, + JSON: {}, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4', + }, + version: '1', + endpoint: 'https://api.refiner.io/v1/track', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'successful group call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'group', + sentAt: '2015-02-23T22:28:55.111Z', + traits: { name: 'rudder ventures', email: 'business@rudderstack.com' }, + userId: 'test@12', + channel: 'browser', + context: { + 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', + }, + groupId: 'group@123', + rudderId: 'd944be7a-c870-41ba-9fa5-f3c9dbf5f7e0', + messageId: '022bb90c-bbac-11e4-8dfc-aa07a5b093db', + request_ip: '[::1]', + integrations: { All: true }, + originalTimestamp: '2022-10-11T13:51:00.906+05:30', + }, + destination: { + Config: { + accountAttributesMapping: [{ from: 'email', to: 'businessEmail' }], + apiKey: 'dc70156e-05a3-4fa1-bb1c-da767fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665476456112, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.refiner.io/v1/identify-user', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: { + id: 'test@12', + 'account[businessEmail]': 'business@rudderstack.com', + 'account[id]': 'group@123', + 'account[name]': 'rudder ventures', + }, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'refiner', + description: 'Refiner page call', + 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', + }, + 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: 'page', + messageId: '5e10d13a-bf9a-44bf-b884-43a9e591ea71', + timestamp: '2019-09-01T15:46:51.693229+05:30', + anonymousId: '00000000000000000000000000', + userId: '12345', + properties: { + path: '/abc', + referrer: 'xyz', + search: 'def', + title: 'ghi', + url: 'jkl', + }, + integrations: { All: true }, + name: 'pageviewed', + sentAt: '2019-10-14T11:15:53.296Z', + }, + destination: { + Config: { + accountAttributesMapping: [{ from: 'email', to: 'businessEmail' }], + apiKey: 'dc70156e-05a3-4fa1-bb1c-da767fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665476456112, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: { id: '12345', event: 'Viewed pageviewed Page' }, + JSON: {}, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4', + }, + version: '1', + endpoint: 'https://api.refiner.io/v1/track', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/refiner/router/data.js b/test/integrations/destinations/refiner/router/data.js index 90984a018081..fcb1b3b2d3d3 100644 --- a/test/integrations/destinations/refiner/router/data.js +++ b/test/integrations/destinations/refiner/router/data.js @@ -1,379 +1,382 @@ const data = [ - { - "name": "refiner", - "description": "Successfull Identify Call eventDelivery set to True and with userAttributesMapping from config ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "type": "identify", - "sentAt": "2022-10-11T13:10:54.877+05:30", - "userId": "user@45", - "context": { - "traits": { - "age": "30", - "city": "Banglore", - "email": "test@user.com", - "phone": "7267286346802347827", - "address": { - "city": "ahmedabad", - "state": "india" - }, - "lastName": "user", - "username": "testUser", - "firstName": "test", - "userCountry": "india" - } - }, - "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", - "messageId": "b6ce7f31-5d76-4240-94d2-3eea020ef791", - "timestamp": "2022-10-11T13:10:52.137+05:30", - "receivedAt": "2022-10-11T13:10:52.138+05:30", - "request_ip": "[::1]", - "originalTimestamp": "2022-10-11T13:10:54.877+05:30" - }, - "metadata": { - "jobId": 1 - }, - "destination": { - "Config": { - "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665475307930, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - } - }] - , "destType": "refiner" + { + name: 'refiner', + description: + 'Successfull Identify Call eventDelivery set to True and with userAttributesMapping from config ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + type: 'identify', + sentAt: '2022-10-11T13:10:54.877+05:30', + userId: 'user@45', + context: { + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + address: { + city: 'ahmedabad', + state: 'india', + }, + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', + }, }, - "method": "POST" + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: 'b6ce7f31-5d76-4240-94d2-3eea020ef791', + timestamp: '2022-10-11T13:10:52.137+05:30', + receivedAt: '2022-10-11T13:10:52.138+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:10:54.877+05:30', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + destType: 'refiner', + }, + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: false, + batchedRequest: { + body: { + FORM: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + firstName: 'test', + lastName: 'user', + phone: '7267286346802347827', + userAddress: { + city: 'ahmedabad', + state: 'india', + }, + userCountry: 'india', + userId: 'user@45', + username: 'testUser', + }, + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.refiner.io/v1/identify-user', + files: {}, + headers: { + Authorization: 'Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + userId: '', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + metadata: [{ jobId: 1 }], + statusCode: 200, }, - "pathSuffix": "" + ], }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ - { - "batched": false, - "batchedRequest": { - "body": { - "FORM": { - "age": "30", - "city": "Banglore", - "email": "test@user.com", - "firstName": "test", - "lastName": "user", - "phone": "7267286346802347827", - "userAddress": { - "city": "ahmedabad", - "state": "india" - }, - "userCountry": "india", - "userId": "user@45", - "username": "testUser" - }, - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {} - }, - "endpoint": "https://api.refiner.io/v1/identify-user", - "files": {}, - "headers": { - "Authorization": "Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4", - "Content-Type": "application/x-www-form-urlencoded" - }, - "method": "POST", - "userId": "", - "params": {}, - "type": "REST", - "version": "1" - }, - "destination": { - "Config": { - "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665475307930, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - }, - "metadata": [{ "jobId": 1 }], - "statusCode": 200 - } - ] - } - } - } + }, }, - { - "name": "refiner", - "description": "Successfull Track Call of event Product Searched", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "type": "track", - "event": "Product Searched", - "sentAt": "2022-10-11T13:38:31.827+05:30", - "userId": "user@45", - "channel": "web", - "context": { - "os": { "name": "", "version": "" }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.2", - "namespace": "com.rudderlabs.javascript" - }, - "page": { - "url": "http://0.0.0.0:1112/tests/html/ecomm_test.html", - "path": "/tests/html/ecomm_test.html", - "title": "Fb Offline Conversion Ecommerce Test", - "search": "", - "referrer": "http://0.0.0.0:1112/tests/html/" - }, - "locale": "en-GB", - "screen": { "density": 2 }, - "traits": { - "age": "30", - "city": "Banglore", - "email": "test@user.com", - "phone": "7267286346802347827", - "lastName": "user", - "username": "testUser", - "firstName": "test", - "userCountry": "india" - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.1.2" - }, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36" - }, - "rudderId": "caae04c5-959f-467b-a293-86f6c62d59e6", - "messageId": "9116b734-7e6b-4497-ab51-c16744d4487e", - "timestamp": "2022-10-11T13:38:29.177+05:30", - "properties": { - "coupon": "APPARELSALE", - "currency": "IND", - "order_id": "5241735", - "products": [ - { - "id": "product-bacon-jam", - "category": "Merch", - "brand": "" - }, - { - "id": "product-t-shirt", - "category": "Merch", - "brand": "Levis" - }, - { - "id": "offer-t-shirt", - "category": "Merch", - "brand": "Levis" - } - ] - }, - "receivedAt": "2022-10-11T13:38:29.178+05:30", - "request_ip": "[::1]", - "originalTimestamp": "2022-10-11T13:38:31.827+05:30" - }, - "metadata": { - "jobId": 2 - }, - "destination": { - "Config": { - "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665475307930, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - } - }] - , "destType": "refiner" + }, + { + name: 'refiner', + description: 'Successfull Track Call of event Product Searched', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + type: 'track', + event: 'Product Searched', + sentAt: '2022-10-11T13:38:31.827+05:30', + userId: 'user@45', + channel: 'web', + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.2', + namespace: 'com.rudderlabs.javascript', + }, + page: { + url: 'http://0.0.0.0:1112/tests/html/ecomm_test.html', + path: '/tests/html/ecomm_test.html', + title: 'Fb Offline Conversion Ecommerce Test', + search: '', + referrer: 'http://0.0.0.0:1112/tests/html/', + }, + locale: 'en-GB', + screen: { density: 2 }, + traits: { + age: '30', + city: 'Banglore', + email: 'test@user.com', + phone: '7267286346802347827', + lastName: 'user', + username: 'testUser', + firstName: 'test', + userCountry: 'india', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.2', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36', + }, + rudderId: 'caae04c5-959f-467b-a293-86f6c62d59e6', + messageId: '9116b734-7e6b-4497-ab51-c16744d4487e', + timestamp: '2022-10-11T13:38:29.177+05:30', + properties: { + coupon: 'APPARELSALE', + currency: 'IND', + order_id: '5241735', + products: [ + { + id: 'product-bacon-jam', + category: 'Merch', + brand: '', + }, + { + id: 'product-t-shirt', + category: 'Merch', + brand: 'Levis', + }, + { + id: 'offer-t-shirt', + category: 'Merch', + brand: 'Levis', + }, + ], + }, + receivedAt: '2022-10-11T13:38:29.178+05:30', + request_ip: '[::1]', + originalTimestamp: '2022-10-11T13:38:31.827+05:30', + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], }, - "method": "POST" + }, }, - "pathSuffix": "" + ], + destType: 'refiner', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ - { - "batched": false, - "batchedRequest": { - "body": { - "FORM": { - "email": "test@user.com", - "event": "Product Searched", - "id": "user@45" - }, - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {} - }, - "endpoint": "https://api.refiner.io/v1/track", - "files": {}, - "userId": "", - "headers": { - "Authorization": "Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4", - "Content-Type": "application/x-www-form-urlencoded" - }, - "method": "POST", - "params": {}, - "type": "REST", - "version": "1" - }, - "destination": { - "Config": { - "apiKey": "da70166e-05a4-4fa1-bb1c-da757fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665475307930, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - }, - "metadata": [{ "jobId": 2 }], - "statusCode": 200 - } - ] - } - } - } + method: 'POST', + }, + pathSuffix: '', }, - { - "name": "refiner", - "description": "Successfull Group Call based in email from traits", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "type": "group", - "sentAt": "2015-02-23T22:28:55.111Z", - "traits": { - "name": "rudder ventures", - "email": "business@rudderstack.com" - }, - "userId": "test@12", - "channel": "browser", - "context": { - "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" - }, - "groupId": "group@123", - "rudderId": "d944be7a-c870-41ba-9fa5-f3c9dbf5f7e0", - "messageId": "022bb90c-bbac-11e4-8dfc-aa07a5b093db", - "request_ip": "[::1]", - "integrations": { "All": true }, - "originalTimestamp": "2022-10-11T13:51:00.906+05:30" - }, - "metadata": { - "jobId": 3 - }, - "destination": { - "Config": { - "accountAttributesMapping": [{ "from": "email", "to": "businessEmail" }], - "apiKey": "dc70156e-05a3-4fa1-bb1c-da767fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665476456112, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - } - }] - , "destType": "refiner" + output: { + response: { + status: 200, + body: { + output: [ + { + batched: false, + batchedRequest: { + body: { + FORM: { + email: 'test@user.com', + event: 'Product Searched', + id: 'user@45', + }, + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.refiner.io/v1/track', + files: {}, + userId: '', + headers: { + Authorization: 'Bearer da70166e-05a4-4fa1-bb1c-da757fd036b4', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + apiKey: 'da70166e-05a4-4fa1-bb1c-da757fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665475307930, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + metadata: [{ jobId: 2 }], + statusCode: 200, + }, + ], + }, + }, + }, + }, + { + name: 'refiner', + description: 'Successfull Group Call based in email from traits', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + type: 'group', + sentAt: '2015-02-23T22:28:55.111Z', + traits: { + name: 'rudder ventures', + email: 'business@rudderstack.com', + }, + userId: 'test@12', + channel: 'browser', + context: { + 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', + }, + groupId: 'group@123', + rudderId: 'd944be7a-c870-41ba-9fa5-f3c9dbf5f7e0', + messageId: '022bb90c-bbac-11e4-8dfc-aa07a5b093db', + request_ip: '[::1]', + integrations: { All: true }, + originalTimestamp: '2022-10-11T13:51:00.906+05:30', + }, + metadata: { + jobId: 3, + }, + destination: { + Config: { + accountAttributesMapping: [{ from: 'email', to: 'businessEmail' }], + apiKey: 'dc70156e-05a3-4fa1-bb1c-da767fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665476456112, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], + }, + }, + }, + ], + destType: 'refiner', + }, + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: false, + batchedRequest: { + body: { + FORM: { + 'account[businessEmail]': 'business@rudderstack.com', + 'account[id]': 'group@123', + 'account[name]': 'rudder ventures', + id: 'test@12', + }, + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.refiner.io/v1/identify-user', + files: {}, + headers: { + Authorization: 'Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + params: {}, + type: 'REST', + userId: '', + version: '1', + }, + destination: { + Config: { + accountAttributesMapping: [{ from: 'email', to: 'businessEmail' }], + apiKey: 'dc70156e-05a3-4fa1-bb1c-da767fd036b4', + blacklistedEvents: [{ eventName: '' }], + eventDelivery: true, + eventDeliveryTS: 1665476456112, + eventFilteringOption: 'disable', + userAttributesMapping: [{ from: 'address', to: 'userAddress' }], + whitelistedEvents: [{ eventName: '' }], }, - "method": "POST" + }, + metadata: [{ jobId: 3 }], + statusCode: 200, }, - "pathSuffix": "" + ], }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ - { - "batched": false, - "batchedRequest": { - "body": { - "FORM": { - "account[businessEmail]": "business@rudderstack.com", - "account[id]": "group@123", - "account[name]": "rudder ventures", - "id": "test@12" - }, - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {} - }, - "endpoint": "https://api.refiner.io/v1/identify-user", - "files": {}, - "headers": { - "Authorization": "Bearer dc70156e-05a3-4fa1-bb1c-da767fd036b4", - "Content-Type": "application/x-www-form-urlencoded" - }, - "method": "POST", - "params": {}, - "type": "REST", - "userId": "", - "version": "1" - }, - "destination": { - "Config": { - "accountAttributesMapping": [{ "from": "email", "to": "businessEmail" }], - "apiKey": "dc70156e-05a3-4fa1-bb1c-da767fd036b4", - "blacklistedEvents": [{ "eventName": "" }], - "eventDelivery": true, - "eventDeliveryTS": 1665476456112, - "eventFilteringOption": "disable", - "userAttributesMapping": [{ "from": "address", "to": "userAddress" }], - "whitelistedEvents": [{ "eventName": "" }] - } - }, - "metadata": [{ "jobId": 3 }], - "statusCode": 200 - } - ] - } - } - } + }, }, + }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/serenytics/processor/data.js b/test/integrations/destinations/serenytics/processor/data.js index ea3e5de7427b..7aa94d89e864 100644 --- a/test/integrations/destinations/serenytics/processor/data.js +++ b/test/integrations/destinations/serenytics/processor/data.js @@ -1,504 +1,1853 @@ -const data = [{ - "name": "serenytics", - "description": "Track call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, "message": { "event": "New Alert", "type": "track", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "New Alert", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Track call with multiple same event name", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "event": "Order Completed", "type": "track", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "Order Completed", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }, { - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "Order Completed", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }, { - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "Order Completed", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Identify call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "messageId": "ec5481b6-a926-4d2e-b293-0b3a77c4d3be", "originalTimestamp": "2022-06-22T10:57:58Z", "anonymousId": "ea5cfab2-3961-4d8a-8187-3d1858c99099", "context": { "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", "model": "AOSP on IA Emulator", "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 } }, "traits": { "email": "testuser@google.com", "first_name": "Rk", "last_name": "Mishra", "mobileNumber": "1-926-555-9504", "lifecycleStageId": 71010794467, "phone": "9988776655", "owner_id": "70000090119" }, "type": "identify", "sentAt": "2022-04-22T10:57:58Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": {}, "JSON": { "email": "testuser@google.com", "sent_at": "2022-04-22T10:57:58Z", "user_id": "ea5cfab2-3961-4d8a-8187-3d1858c99099", "last_name": "Mishra", "timestamp": "2022-06-22T10:57:58Z", "first_name": "Rk", "trait_phone": "9988776655", "trait_owner_id": "70000090119", "original_timestamp": "2022-06-22T10:57:58Z", "trait_mobileNumber": "1-926-555-9504", "trait_lifecycleStageId": 71010794467 }, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": {}, "version": "1", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Identify call with missing identify storage url", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "messageId": "ec5481b6-a926-4d2e-b293-0b3a77c4d3be", "originalTimestamp": "2022-06-22T10:57:58Z", "anonymousId": "ea5cfab2-3961-4d8a-8187-3d1858c99099", "context": { "locale": "en-US", "os": { "name": "iOS", "version": "14.4.1" }, "screen": { "density": 2 } }, "traits": { "email": "testuser@google.com", "first_name": "Rk" }, "type": "identify", "sentAt": "2022-04-22T10:57:58Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } }, - "error": "Storage url for \"IDENTIFY\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Screen call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "screen", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "page": "home Page" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": {}, "JSON": { "sent_at": "2021-01-03T17:02:53.195Z", "timestamp": "2021-01-03T17:02:53.193Z", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "property_page": "home Page", "property_message": "Please check the alert", "original_timestamp": "2021-01-03T17:02:53.193Z" }, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": {}, "version": "1", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Page Call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "page", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "page": "home Page" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": {}, "JSON": { "sent_at": "2021-01-03T17:02:53.195Z", "timestamp": "2021-01-03T17:02:53.193Z", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "property_page": "home Page", "property_message": "Please check the alert", "original_timestamp": "2021-01-03T17:02:53.193Z" }, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": {}, "version": "1", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Page call, storage url for page call is missing.", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "page", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "page": "home Page" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } }, - "error": "Storage url for \"PAGE\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Track call: event name is missing.", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, "message": { "type": "track", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, - "error": "Missing required value from \"event\"", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Track call: storage url is required for track call.", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, "message": { "event": "New Alert", "type": "track", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, - "error": "Storage url for \"TRACK\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Track call: if storage url is not present for track call, only present for event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } }, "message": { "event": "Order Completed", "type": "track", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "Order Completed", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }, { - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981", "headers": {}, "params": {}, "body": { "JSON": { "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", "event": "Order Completed", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "price": "12000", "property_message": "Please check the alert", "property_brand": "Zara" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Message type is not present", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } }, "message": { "event": "Order Completed", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "brand": "Zara", "price": "12000" }, "context": { "os": { "name": "", "version": "" }, "app": { "name": "RudderLabs JavaScript SDK", "build": "1.0.0", "version": "1.1.11", "namespace": "com.rudderlabs.javascript" }, "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "eventToStorageUrlMap": [{ "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" }, { "from": "Order Completed", "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" }, { "from": "Add to Cart", "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" }] } }, - "error": "Event type is required", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Screen call: storage url is missing for storage call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "screen", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "properties": { "message": "Please check the alert", "page": "home Page" }, "context": { "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", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, - "error": "Storage url for \"SCREEN\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Group call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "group", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "groupId": "rudder-123", "traits": { "name": "Mark Twain", "phone": "919191919191", "numberOfEmployees": 51, "annualRevenue": 1000, "address": "Red Colony", "city": "Colony", "state": "Haryana" }, "context": { "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", "model": "AOSP on IA Emulator", "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 }, "traits": { "email": "testuser@google.com" } }, "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "body": { "XML": {}, "FORM": {}, "JSON": { "id": "rudder-123", "sent_at": "2021-01-03T17:02:53.195Z", "timestamp": "2021-01-03T17:02:53.193Z", "trait_city": "Colony", "trait_name": "Mark Twain", "trait_email": "testuser@google.com", "trait_phone": "919191919191", "trait_state": "Haryana", "trait_address": "Red Colony", "original_timestamp": "2021-01-03T17:02:53.193Z", "trait_annualRevenue": 1000, "trait_numberOfEmployees": 51 }, "JSON_ARRAY": {} }, "type": "REST", "files": {}, "method": "POST", "params": {}, "headers": {}, "version": "1", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Group call: its check custom payload", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "group", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "groupId": "rudder-123", "traits": {}, "context": { "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", "model": "AOSP on IA Emulator", "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 }, "traits": { "email": "testuser@google.com" } }, "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "headers": {}, "params": {}, "body": { "JSON": { "id": "rudder-123", "sent_at": "2021-01-03T17:02:53.195Z", "original_timestamp": "2021-01-03T17:02:53.193Z", "timestamp": "2021-01-03T17:02:53.193Z", "trait_email": "testuser@google.com" }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "serenytics", - "description": "Group call misiing storage url", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "message": { "type": "group", "sentAt": "2021-01-03T17:02:53.195Z", "channel": "web", "groupId": "rudder-123", "traits": {}, "context": { "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", "model": "AOSP on IA Emulator", "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 }, "traits": { "email": "testuser@google.com" } }, "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", "originalTimestamp": "2021-01-03T17:02:53.193Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, - "error": "Storage url for \"GROUP\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Alias call: storage data url is missing", - "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.1.5" }, "traits": { "name": "Shehan Study", "category": "SampleIdentify", "email": "chandra+r@rudderlabs.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": "alias", "messageId": "dd46338d-5f83-493b-bd28-3b48f55d0be8", "originalTimestamp": "2020-10-20T08:14:28.778Z", "anonymousId": "my-anonymous-id-new", "userId": "newUserIdAlias", "integrations": { "All": true }, "previousId": "sampleusrRudder3", "sentAt": "2020-10-20T08:14:28.778Z" }, "destination": { "Config": { "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } }, - "error": "Storage url for \"ALIAS\" is missing. Aborting!", "statTags": { - "destType": "SERENYTICS", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "serenytics", - "description": "Alias call", - "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.1.5" }, "traits": { "name": "Shehan Study", "category": "SampleIdentify", "email": "chandra+r@rudderlabs.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": "alias", "messageId": "dd46338d-5f83-493b-bd28-3b48f55d0be8", "originalTimestamp": "2020-10-20T08:14:28.778Z", "anonymousId": "my-anonymous-id-new", "userId": "newUserIdAlias", "integrations": { "All": true }, "traits": { "city": "Disney", "country": "USA", "email": "mickey@disney.com", "firstname": "Mickey" }, "previousId": "sampleusrRudder3", "sentAt": "2020-10-20T08:14:28.778Z" }, "destination": { "Config": { "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" } } }, - ], - "method": "POST", - }, - "pathSuffix": "", - }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "POST", "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", "headers": {}, "params": {}, "body": { "JSON": { "user_id": "newUserIdAlias", "previous_id": "sampleusrRudder3", "sent_at": "2020-10-20T08:14:28.778Z", "original_timestamp": "2020-10-20T08:14:28.778Z", "timestamp": "2020-10-20T08:14:28.778Z", "trait_city": "Disney", "trait_country": "USA", "trait_email": "chandra+r@rudderlabs.com", "trait_firstname": "Mickey", "trait_name": "Shehan Study", "trait_category": "SampleIdentify", "trait_plan": "Open source", "trait_logins": 5, "trait_createdAt": 1599264000 }, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}]; module.exports = { - data -} \ No newline at end of file +const data = [ + { + name: 'serenytics', + description: 'Track call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'New Alert', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Track call with multiple same event name', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'Order Completed', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Identify call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2022-06-22T10:57:58Z', + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99099', + context: { + 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', + model: 'AOSP on IA Emulator', + 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 }, + }, + traits: { + email: 'testuser@google.com', + first_name: 'Rk', + last_name: 'Mishra', + mobileNumber: '1-926-555-9504', + lifecycleStageId: 71010794467, + phone: '9988776655', + owner_id: '70000090119', + }, + type: 'identify', + sentAt: '2022-04-22T10:57:58Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + email: 'testuser@google.com', + sent_at: '2022-04-22T10:57:58Z', + user_id: 'ea5cfab2-3961-4d8a-8187-3d1858c99099', + last_name: 'Mishra', + timestamp: '2022-06-22T10:57:58Z', + first_name: 'Rk', + trait_phone: '9988776655', + trait_owner_id: '70000090119', + original_timestamp: '2022-06-22T10:57:58Z', + trait_mobileNumber: '1-926-555-9504', + trait_lifecycleStageId: 71010794467, + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: {}, + version: '1', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Identify call with missing identify storage url', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2022-06-22T10:57:58Z', + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99099', + context: { + locale: 'en-US', + os: { name: 'iOS', version: '14.4.1' }, + screen: { density: 2 }, + }, + traits: { email: 'testuser@google.com', first_name: 'Rk' }, + type: 'identify', + sentAt: '2022-04-22T10:57:58Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + error: 'Storage url for "IDENTIFY" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Screen call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'screen', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', page: 'home Page' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + sent_at: '2021-01-03T17:02:53.195Z', + timestamp: '2021-01-03T17:02:53.193Z', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + property_page: 'home Page', + property_message: 'Please check the alert', + original_timestamp: '2021-01-03T17:02:53.193Z', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: {}, + version: '1', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Page Call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'page', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', page: 'home Page' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + sent_at: '2021-01-03T17:02:53.195Z', + timestamp: '2021-01-03T17:02:53.193Z', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + property_page: 'home Page', + property_message: 'Please check the alert', + original_timestamp: '2021-01-03T17:02:53.193Z', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: {}, + version: '1', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Page call, storage url for page call is missing.', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'page', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', page: 'home Page' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + error: 'Storage url for "PAGE" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Track call: event name is missing.', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + message: { + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + error: 'Missing required value from "event"', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Track call: storage url is required for track call.', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + error: 'Storage url for "TRACK" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Track call: if storage url is not present for track call, only present for event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + message: { + event: 'Order Completed', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Message type is not present', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + message: { + event: 'Order Completed', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + }, + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + }, + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + error: 'Event type is required', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Screen call: storage url is missing for storage call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'screen', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', page: 'home Page' }, + context: { + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + error: 'Storage url for "SCREEN" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Group call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'group', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + groupId: 'rudder-123', + traits: { + name: 'Mark Twain', + phone: '919191919191', + numberOfEmployees: 51, + annualRevenue: 1000, + address: 'Red Colony', + city: 'Colony', + state: 'Haryana', + }, + context: { + 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', + model: 'AOSP on IA Emulator', + 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 }, + traits: { email: 'testuser@google.com' }, + }, + rudderId: '8f8fa6b5-8e24-489c-8e22-61f23f2e364f', + messageId: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymousId: '97c46c81-3140-456d-b2a9-690d70aaca35', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + id: 'rudder-123', + sent_at: '2021-01-03T17:02:53.195Z', + timestamp: '2021-01-03T17:02:53.193Z', + trait_city: 'Colony', + trait_name: 'Mark Twain', + trait_email: 'testuser@google.com', + trait_phone: '919191919191', + trait_state: 'Haryana', + trait_address: 'Red Colony', + original_timestamp: '2021-01-03T17:02:53.193Z', + trait_annualRevenue: 1000, + trait_numberOfEmployees: 51, + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: {}, + version: '1', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Group call: its check custom payload', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'group', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + groupId: 'rudder-123', + traits: {}, + context: { + 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', + model: 'AOSP on IA Emulator', + 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 }, + traits: { email: 'testuser@google.com' }, + }, + rudderId: '8f8fa6b5-8e24-489c-8e22-61f23f2e364f', + messageId: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymousId: '97c46c81-3140-456d-b2a9-690d70aaca35', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + id: 'rudder-123', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + trait_email: 'testuser@google.com', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Group call misiing storage url', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + type: 'group', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + groupId: 'rudder-123', + traits: {}, + context: { + 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', + model: 'AOSP on IA Emulator', + 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 }, + traits: { email: 'testuser@google.com' }, + }, + rudderId: '8f8fa6b5-8e24-489c-8e22-61f23f2e364f', + messageId: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymousId: '97c46c81-3140-456d-b2a9-690d70aaca35', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + error: 'Storage url for "GROUP" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Alias call: storage data url is missing', + 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.1.5', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r@rudderlabs.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: 'alias', + messageId: 'dd46338d-5f83-493b-bd28-3b48f55d0be8', + originalTimestamp: '2020-10-20T08:14:28.778Z', + anonymousId: 'my-anonymous-id-new', + userId: 'newUserIdAlias', + integrations: { All: true }, + previousId: 'sampleusrRudder3', + sentAt: '2020-10-20T08:14:28.778Z', + }, + destination: { + Config: { + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + error: 'Storage url for "ALIAS" is missing. Aborting!', + statTags: { + destType: 'SERENYTICS', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'serenytics', + description: 'Alias call', + 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.1.5', + }, + traits: { + name: 'Shehan Study', + category: 'SampleIdentify', + email: 'chandra+r@rudderlabs.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: 'alias', + messageId: 'dd46338d-5f83-493b-bd28-3b48f55d0be8', + originalTimestamp: '2020-10-20T08:14:28.778Z', + anonymousId: 'my-anonymous-id-new', + userId: 'newUserIdAlias', + integrations: { All: true }, + traits: { + city: 'Disney', + country: 'USA', + email: 'mickey@disney.com', + firstname: 'Mickey', + }, + previousId: 'sampleusrRudder3', + sentAt: '2020-10-20T08:14:28.778Z', + }, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + user_id: 'newUserIdAlias', + previous_id: 'sampleusrRudder3', + sent_at: '2020-10-20T08:14:28.778Z', + original_timestamp: '2020-10-20T08:14:28.778Z', + timestamp: '2020-10-20T08:14:28.778Z', + trait_city: 'Disney', + trait_country: 'USA', + trait_email: 'chandra+r@rudderlabs.com', + trait_firstname: 'Mickey', + trait_name: 'Shehan Study', + trait_category: 'SampleIdentify', + trait_plan: 'Open source', + trait_logins: 5, + trait_createdAt: 1599264000, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/serenytics/router/data.js b/test/integrations/destinations/serenytics/router/data.js index 431fd4b02223..1310e66f2eeb 100644 --- a/test/integrations/destinations/serenytics/router/data.js +++ b/test/integrations/destinations/serenytics/router/data.js @@ -1,497 +1,543 @@ const data = [ { - "name": "serenytics", - "description": "Successfull Track Call ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" - } + name: 'serenytics', + description: 'Successfull Track Call ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', }, - "metadata": { - "jobId": 1 + }, + metadata: { + jobId: 1, + }, + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', }, - "message": { - "event": "New Alert", - "type": "track", - "sentAt": "2021-01-03T17:02:53.195Z", - "channel": "web", - "properties": { - "message": "Please check the alert", - "brand": "Zara", - "price": "12000" + context: { + os: { + name: '', + version: '', }, - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" - }, - "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" + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + locale: 'en-US', + screen: { + density: 2, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.11', }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }] - , "destType": "serenytics" + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + destType: 'serenytics', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": [ + batchedRequest: [ { - "version": "1", - "type": "REST", - "userId": "", - "method": "POST", - "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "headers": {}, - "params": {}, - "body": { - "JSON": { - "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", - "event": "New Alert", - "sent_at": "2021-01-03T17:02:53.195Z", - "original_timestamp": "2021-01-03T17:02:53.193Z", - "timestamp": "2021-01-03T17:02:53.193Z", - "price": "12000", - "property_message": "Please check the alert", - "property_brand": "Zara" + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'New Alert', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - "files": {} - } + files: {}, + }, ], - "metadata": [ + metadata: [ { - "jobId": 1 - } + jobId: 1, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" - } - } - } - ] - } - } - } + batched: false, + statusCode: 200, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + }, + }, + }, + ], + }, + }, + }, }, { - "name": "serenytics", - "description": "Succesfull Track Call with eventToStorageUrlMap from Config", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "eventToStorageUrlMap": [ - { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" - }, - { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" - }, - { - "from": "Add to Cart", - "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" - } - ] - } - }, - "metadata": { - "jobId": 2 - }, - "message": { - "event": "Order Completed", - "type": "track", - "sentAt": "2021-01-03T17:02:53.195Z", - "channel": "web", - "properties": { - "message": "Please check the alert", - "brand": "Zara", - "price": "12000" - }, - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" + name: 'serenytics', + description: 'Succesfull Track Call with eventToStorageUrlMap from Config', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', }, - "locale": "en-US", - "screen": { - "density": 2 + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.1.11" + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', }, - "campaign": {}, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" + ], + }, + }, + metadata: { + jobId: 2, + }, + message: { + event: 'Order Completed', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', + }, + context: { + os: { + name: '', + version: '', + }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + locale: 'en-US', + screen: { + density: 2, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.11', }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }] - , "destType": "serenytics" + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + destType: 'serenytics', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": [ + batchedRequest: [ { - "version": "1", - "type": "REST", - "userId": "", - "method": "POST", - "endpoint": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12", - "headers": {}, - "params": {}, - "body": { - "JSON": { - "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", - "event": "Order Completed", - "sent_at": "2021-01-03T17:02:53.195Z", - "original_timestamp": "2021-01-03T17:02:53.193Z", - "timestamp": "2021-01-03T17:02:53.193Z", - "price": "12000", - "property_message": "Please check the alert", - "property_brand": "Zara" + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - "files": {} + files: {}, }, { - "version": "1", - "type": "REST", "userId": "", - "method": "POST", - "endpoint": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981", - "headers": {}, - "params": {}, - "body": { - "JSON": { - "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", - "event": "Order Completed", - "sent_at": "2021-01-03T17:02:53.195Z", - "original_timestamp": "2021-01-03T17:02:53.193Z", - "timestamp": "2021-01-03T17:02:53.193Z", - "price": "12000", - "property_message": "Please check the alert", - "property_brand": "Zara" + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - "files": {} + files: {}, }, { - "version": "1", - "type": "REST", "userId": "", - "method": "POST", - "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "headers": {}, - "params": {}, - "body": { - "JSON": { - "id": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymous_id": "97c46c81-3140-456d-b2a9-690d70aaca35", - "event": "Order Completed", - "sent_at": "2021-01-03T17:02:53.195Z", - "original_timestamp": "2021-01-03T17:02:53.193Z", - "timestamp": "2021-01-03T17:02:53.193Z", - "price": "12000", - "property_message": "Please check the alert", - "property_brand": "Zara" + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + headers: {}, + params: {}, + body: { + JSON: { + id: '2116ef8c-efc3-4ca4-851b-02ee60dad6ff', + anonymous_id: '97c46c81-3140-456d-b2a9-690d70aaca35', + event: 'Order Completed', + sent_at: '2021-01-03T17:02:53.195Z', + original_timestamp: '2021-01-03T17:02:53.193Z', + timestamp: '2021-01-03T17:02:53.193Z', + price: '12000', + property_message: 'Please check the alert', + property_brand: 'Zara', }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - "files": {} - } + files: {}, + }, ], - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "eventToStorageUrlMap": [ + batched: false, + statusCode: 200, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', }, { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', }, { - "from": "Add to Cart", - "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" - } - ] - } - } - } - ] - } - } - } + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "serenytics", - "description": "Succesfull Identify Call with eventToStorageUrlMap from Config", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "eventToStorageUrlMap": [ - { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" - }, - { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" - }, - { - "from": "Add to Cart", - "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" - } - ] - } - }, - "metadata": { - "jobId": 3 - }, - "message": { - "messageId": "ec5481b6-a926-4d2e-b293-0b3a77c4d3be", - "originalTimestamp": "2022-06-22T10:57:58Z", - "anonymousId": "ea5cfab2-3961-4d8a-8187-3d1858c99099", - "context": { - "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", - "model": "AOSP on IA Emulator", - "name": "generic_x86_arm", - "type": "ios", - "attTrackingStatus": 3 + name: 'serenytics', + description: 'Succesfull Identify Call with eventToStorageUrlMap from Config', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.0" + { + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', }, - "locale": "en-US", - "os": { - "name": "iOS", - "version": "14.4.1" + { + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', }, - "screen": { - "density": 2 - } + ], + }, + }, + metadata: { + jobId: 3, + }, + message: { + messageId: 'ec5481b6-a926-4d2e-b293-0b3a77c4d3be', + originalTimestamp: '2022-06-22T10:57:58Z', + anonymousId: 'ea5cfab2-3961-4d8a-8187-3d1858c99099', + context: { + 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', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'ios', + attTrackingStatus: 3, }, - "traits": { - "email": "testuser@google.com", - "first_name": "Rk", - "last_name": "Mishra", - "mobileNumber": "1-926-555-9504", - "lifecycleStageId": 71010794467, - "phone": "9988776655", - "owner_id": "70000090119" + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', }, - "type": "identify", - "sentAt": "2022-04-22T10:57:58Z" - } - }] - , "destType": "serenytics" + locale: 'en-US', + os: { + name: 'iOS', + version: '14.4.1', + }, + screen: { + density: 2, + }, + }, + traits: { + email: 'testuser@google.com', + first_name: 'Rk', + last_name: 'Mishra', + mobileNumber: '1-926-555-9504', + lifecycleStageId: 71010794467, + phone: '9988776655', + owner_id: '70000090119', + }, + type: 'identify', + sentAt: '2022-04-22T10:57:58Z', + }, + }, + ], + destType: 'serenytics', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": { - "email": "testuser@google.com", - "sent_at": "2022-04-22T10:57:58Z", - "user_id": "ea5cfab2-3961-4d8a-8187-3d1858c99099", - "last_name": "Mishra", - "timestamp": "2022-06-22T10:57:58Z", - "first_name": "Rk", - "trait_phone": "9988776655", - "trait_owner_id": "70000090119", - "original_timestamp": "2022-06-22T10:57:58Z", - "trait_mobileNumber": "1-926-555-9504", - "trait_lifecycleStageId": 71010794467 + batchedRequest: { + body: { + XML: {}, + FORM: {}, + JSON: { + email: 'testuser@google.com', + sent_at: '2022-04-22T10:57:58Z', + user_id: 'ea5cfab2-3961-4d8a-8187-3d1858c99099', + last_name: 'Mishra', + timestamp: '2022-06-22T10:57:58Z', + first_name: 'Rk', + trait_phone: '9988776655', + trait_owner_id: '70000090119', + original_timestamp: '2022-06-22T10:57:58Z', + trait_mobileNumber: '1-926-555-9504', + trait_lifecycleStageId: 71010794467, }, - "JSON_ARRAY": {} + JSON_ARRAY: {}, }, - "type": "REST", "userId": "", - "files": {}, - "method": "POST", - "params": {}, - "headers": {}, - "version": "1", - "endpoint": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760" + type: 'REST', + userId: '', + files: {}, + method: 'POST', + params: {}, + headers: {}, + version: '1', + endpoint: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', }, - "metadata": [ + metadata: [ { - "jobId": 3 - } + jobId: 3, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "storageUrlAlias": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlGroup": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlIdentify": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlPage": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlScreen": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "storageUrlTrack": "https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760", - "eventToStorageUrlMap": [ + batched: false, + statusCode: 200, + destination: { + Config: { + storageUrlAlias: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlGroup: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlIdentify: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlPage: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlScreen: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + storageUrlTrack: + 'https://api.serenytics.com/api/data_source/5dc8508e-0946-47fc-8ed8-f67307c407f1/push/997877c6358621beb1f86dc320ac822b9f069760', + eventToStorageUrlMap: [ { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12" + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/b646…/push/ad051d45f10a0c11a50f5c20af838e39ea9dcf12', }, { - "from": "Order Completed", - "to": "https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981" + from: 'Order Completed', + to: 'https://api.serenytics.com/api/data_source/0714…/push/f48540d9b51fd5c88dffaad4e34cd0b56a525981', }, { - "from": "Add to Cart", - "to": "https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313" - } - ] - } - } - } - ] - } - } - } + from: 'Add to Cart', + to: 'https://api.serenytics.com/api/data_source/f62c…/push/75c48822ca582a1322aa1d7586ce374a4736c313', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/signl4/processor/data.js b/test/integrations/destinations/signl4/processor/data.js index e63a335815b4..22f193449d08 100644 --- a/test/integrations/destinations/signl4/processor/data.js +++ b/test/integrations/destinations/signl4/processor/data.js @@ -1,231 +1,791 @@ -const data = [{ - "name": "signl4", - "description": "Track call for creating an alert with all default values from web-app", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[]}}}, - ], - "method": "POST", +const data = [ + { + name: 'signl4', + description: 'Track call for creating an alert with all default values from web-app', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://connect.signl4.com/webhook/t1yurrb968zk","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"message":"Please check the alert","Title":"New Alert","brand":"Zara","price":"12000","X-S4-Service":"service","X-S4-Location":"67.3, 32.3","X-S4-AlertingScenario":"single_ack","X-S4-ExternalID":"INC493933","X-S4-Status":"new"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "signl4", - "description": "Check for eventToTitleMapping", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://connect.signl4.com/webhook/t1yurrb968zk', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + message: 'Please check the alert', + Title: 'New Alert', + brand: 'Zara', + price: '12000', + 'X-S4-Service': 'service', + 'X-S4-Location': '67.3, 32.3', + 'X-S4-AlertingScenario': 'single_ack', + 'X-S4-ExternalID': 'INC493933', + 'X-S4-Status': 'new', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Check for eventToTitleMapping', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://connect.signl4.com/webhook/t1yurrb968zk', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + message: 'Please check the alert', + Title: 'Alert Created', + brand: 'Zara', + price: '12000', + 'X-S4-Service': 'service', + 'X-S4-Location': '67.3, 32.3', + 'X-S4-AlertingScenario': 'single_ack', + 'X-S4-ExternalID': 'INC493933', + 'X-S4-Status': 'new', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Check for property mapping from UI', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', + s4Service: 'service', + s4Location: '67.3, 32.3', + s4Alerting: 'single_ack', + s4ExternalID: 'INC493933', + s4Status: 'new', + }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: '', + s4ServiceProperty: 's4Service', + s4LocationValue: '', + s4LocationProperty: 's4Location', + s4AlertingScenarioValue: '', + s4AlertingScenarioProperty: 's4Alerting', + s4ExternalIDValue: '', + s4ExternalIDProperty: 's4ExternalID', + s4StatusValue: '', + s4StatusProperty: 's4Status', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://connect.signl4.com/webhook/t1yurrb968zk', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + message: 'Please check the alert', + Title: 'Alert Created', + brand: 'Zara', + price: '12000', + 'X-S4-Service': 'service', + 'X-S4-Location': '67.3, 32.3', + 'X-S4-AlertingScenario': 'single_ack', + 'X-S4-ExternalID': 'INC493933', + 'X-S4-Status': 'new', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://connect.signl4.com/webhook/t1yurrb968zk","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"message":"Please check the alert","Title":"Alert Created","brand":"Zara","price":"12000","X-S4-Service":"service","X-S4-Location":"67.3, 32.3","X-S4-AlertingScenario":"single_ack","X-S4-ExternalID":"INC493933","X-S4-Status":"new"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "signl4", - "description": "Check for property mapping from UI", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000","s4Service":"service","s4Location":"67.3, 32.3","s4Alerting":"single_ack","s4ExternalID":"INC493933","s4Status":"new"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"","s4ServiceProperty":"s4Service","s4LocationValue":"","s4LocationProperty":"s4Location","s4AlertingScenarioValue":"","s4AlertingScenarioProperty":"s4Alerting","s4ExternalIDValue":"","s4ExternalIDProperty":"s4ExternalID","s4StatusValue":"","s4StatusProperty":"s4Status","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Check for property mapping overrding default value', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', + s4Service: 'service', + s4Location: '67.3, 32.3', + s4Alerting: 'single_ack', + s4ExternalID: 'INC493933', + s4Status: 'new', + }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://connect.signl4.com/webhook/t1yurrb968zk","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"message":"Please check the alert","Title":"Alert Created","brand":"Zara","price":"12000","X-S4-Service":"service","X-S4-Location":"67.3, 32.3","X-S4-AlertingScenario":"single_ack","X-S4-ExternalID":"INC493933","X-S4-Status":"new"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "signl4", - "description": "Check for property mapping overrding default value", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000","s4Service":"service","s4Location":"67.3, 32.3","s4Alerting":"single_ack","s4ExternalID":"INC493933","s4Status":"new"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"defaultServiceValue","s4ServiceProperty":"s4Service","s4LocationValue":"defaultLocationValue","s4LocationProperty":"s4Location","s4AlertingScenarioValue":"defaultScenarioValue","s4AlertingScenarioProperty":"s4Alerting","s4ExternalIDValue":"defaultIDValue","s4ExternalIDProperty":"s4ExternalID","s4StatusValue":"defaultStatusValue","s4StatusProperty":"s4Status","s4Filter":true,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'defaultServiceValue', + s4ServiceProperty: 's4Service', + s4LocationValue: 'defaultLocationValue', + s4LocationProperty: 's4Location', + s4AlertingScenarioValue: 'defaultScenarioValue', + s4AlertingScenarioProperty: 's4Alerting', + s4ExternalIDValue: 'defaultIDValue', + s4ExternalIDProperty: 's4ExternalID', + s4StatusValue: 'defaultStatusValue', + s4StatusProperty: 's4Status', + s4Filter: true, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://connect.signl4.com/webhook/t1yurrb968zk', + headers: { 'Content-Type': 'application/json' }, + params: {}, + body: { + JSON: { + message: 'Please check the alert', + Title: 'Alert Created', + brand: 'Zara', + price: '12000', + 'X-S4-Service': 'service', + 'X-S4-Location': '67.3, 32.3', + 'X-S4-AlertingScenario': 'single_ack', + 'X-S4-ExternalID': 'INC493933', + 'X-S4-Status': 'new', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"version":"1","type":"REST","method":"POST","endpoint":"https://connect.signl4.com/webhook/t1yurrb968zk","headers":{"Content-Type":"application/json"},"params":{},"body":{"JSON":{"message":"Please check the alert","Title":"Alert Created","brand":"Zara","price":"12000","X-S4-Service":"service","X-S4-Location":"67.3, 32.3","X-S4-AlertingScenario":"single_ack","X-S4-ExternalID":"INC493933","X-S4-Status":"new"},"JSON_ARRAY":{},"XML":{},"FORM":{}},"files":{},"userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "signl4", - "description": "Check for event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Check for event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: '', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"t1yurrb968zk","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}, - "error": "Event is not present in the input payload", "statTags": { - "destType": "SIGNL4", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "signl4", - "description": "Check for apiKey", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"track","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + error: 'Event is not present in the input payload', + statTags: { + destType: 'SIGNL4', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Check for apiKey', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}, - "error": "ApiKey is a required field", "statTags": { - "destType": "SIGNL4", - "errorCategory": "dataValidation", - "errorType": "configuration", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "signl4", - "description": "Unsupported message type", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"identify","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"urissi44sfgs","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: '', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: '', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + error: 'ApiKey is a required field', + statTags: { + destType: 'SIGNL4', + errorCategory: 'dataValidation', + errorType: 'configuration', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Unsupported message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: 'identify', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"urissi44sfgs","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}, - "error": "Event type identify is not supported", "statTags": { - "destType": "SIGNL4", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "signl4", - "description": "Message type not present", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"event":"New Alert","type":"","sentAt":"2021-01-03T17:02:53.195Z","channel":"web","properties":{"message":"Please check the alert","brand":"Zara","price":"12000"},"context":{"os":{"name":"","version":""},"app":{"name":"RudderLabs JavaScript SDK","build":"1.0.0","version":"1.1.11","namespace":"com.rudderlabs.javascript"},"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","originalTimestamp":"2021-01-03T17:02:53.193Z"},"destination":{"Config":{"apiKey":"urissi44sfgs","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}}, - ], - "method": "POST", + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + error: 'Event type identify is not supported', + statTags: { + destType: 'SIGNL4', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'signl4', + description: 'Message type not present', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + event: 'New Alert', + type: '', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { message: 'Please check the alert', brand: 'Zara', price: '12000' }, + context: { + os: { name: '', version: '' }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"urissi44sfgs","s4ServiceValue":"service","s4ServiceProperty":"","s4LocationValue":"67.3, 32.3","s4LocationProperty":"","s4AlertingScenarioValue":"single_ack","s4AlertingScenarioProperty":"","s4ExternalIDValue":"INC493933","s4ExternalIDProperty":"","s4StatusValue":"new","s4StatusProperty":"","s4Filter":false,"eventToTitleMapping":[{"from":"New Alert","to":"Alert Created"}]}}, - "error": "Event type is required", "statTags": { - "destType": "SIGNL4", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - }]; module.exports = { - data - } \ No newline at end of file + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [{ from: 'New Alert', to: 'Alert Created' }], + }, + }, + error: 'Event type is required', + statTags: { + destType: 'SIGNL4', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/signl4/router/data.js b/test/integrations/destinations/signl4/router/data.js index 454241d0a3b6..354d709b78ba 100644 --- a/test/integrations/destinations/signl4/router/data.js +++ b/test/integrations/destinations/signl4/router/data.js @@ -1,277 +1,279 @@ const data = [ { - "name": "signl4", - "description": "Successfull Track Call ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "apiKey": "t1yurrb968zk", - "s4ServiceValue": "service", - "s4ServiceProperty": "", - "s4LocationValue": "67.3, 32.3", - "s4LocationProperty": "", - "s4AlertingScenarioValue": "single_ack", - "s4AlertingScenarioProperty": "", - "s4ExternalIDValue": "INC493933", - "s4ExternalIDProperty": "", - "s4StatusValue": "new", - "s4StatusProperty": "", - "s4Filter": false, - "eventToTitleMapping": [] - } + name: 'signl4', + description: 'Successfull Track Call ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [], }, - "metadata": { - "jobId": 1 + }, + metadata: { + jobId: 1, + }, + message: { + event: 'New Alert', + type: 'track', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', }, - "message": { - "event": "New Alert", - "type": "track", - "sentAt": "2021-01-03T17:02:53.195Z", - "channel": "web", - "properties": { - "message": "Please check the alert", - "brand": "Zara", - "price": "12000" + context: { + os: { + name: '', + version: '', }, - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" - }, - "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" + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + locale: 'en-US', + screen: { + density: 2, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.11', }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }] - , "destType": "signl4" + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + destType: 'signl4', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", - "userId": "", - "method": "POST", - "endpoint": "https://connect.signl4.com/webhook/t1yurrb968zk", - "headers": { - "Content-Type": "application/json" + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'POST', + endpoint: 'https://connect.signl4.com/webhook/t1yurrb968zk', + headers: { + 'Content-Type': 'application/json', }, - "params": {}, - "body": { - "JSON": { - "message": "Please check the alert", - "Title": "New Alert", - "brand": "Zara", - "price": "12000", - "X-S4-Service": "service", - "X-S4-Location": "67.3, 32.3", - "X-S4-AlertingScenario": "single_ack", - "X-S4-ExternalID": "INC493933", - "X-S4-Status": "new" + params: {}, + body: { + JSON: { + message: 'Please check the alert', + Title: 'New Alert', + brand: 'Zara', + price: '12000', + 'X-S4-Service': 'service', + 'X-S4-Location': '67.3, 32.3', + 'X-S4-AlertingScenario': 'single_ack', + 'X-S4-ExternalID': 'INC493933', + 'X-S4-Status': 'new', }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - "files": {} + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 1 - } + jobId: 1, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "t1yurrb968zk", - "s4ServiceValue": "service", - "s4ServiceProperty": "", - "s4LocationValue": "67.3, 32.3", - "s4LocationProperty": "", - "s4AlertingScenarioValue": "single_ack", - "s4AlertingScenarioProperty": "", - "s4ExternalIDValue": "INC493933", - "s4ExternalIDProperty": "", - "s4StatusValue": "new", - "s4StatusProperty": "", - "s4Filter": false, - "eventToTitleMapping": [] - } - } - } - ] - } - } - } + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: 't1yurrb968zk', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "signl4", - "description": "Identify Event not Supported", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "apiKey": "urissi44sfgs", - "s4ServiceValue": "service", - "s4ServiceProperty": "", - "s4LocationValue": "67.3, 32.3", - "s4LocationProperty": "", - "s4AlertingScenarioValue": "single_ack", - "s4AlertingScenarioProperty": "", - "s4ExternalIDValue": "INC493933", - "s4ExternalIDProperty": "", - "s4StatusValue": "new", - "s4StatusProperty": "", - "s4Filter": false, - "eventToTitleMapping": [ - { - "from": "New Alert", - "to": "Alert Created" - } - ] - } + name: 'signl4', + description: 'Identify Event not Supported', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [ + { + from: 'New Alert', + to: 'Alert Created', + }, + ], }, - "metadata": { - "jobId": 2 + }, + metadata: { + jobId: 2, + }, + message: { + event: 'New Alert', + type: 'identify', + sentAt: '2021-01-03T17:02:53.195Z', + channel: 'web', + properties: { + message: 'Please check the alert', + brand: 'Zara', + price: '12000', }, - "message": { - "event": "New Alert", - "type": "identify", - "sentAt": "2021-01-03T17:02:53.195Z", - "channel": "web", - "properties": { - "message": "Please check the alert", - "brand": "Zara", - "price": "12000" + context: { + os: { + name: '', + version: '', }, - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" - }, - "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" + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.1.11', + namespace: 'com.rudderlabs.javascript', + }, + locale: 'en-US', + screen: { + density: 2, }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }] - , "destType": "signl4" + 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', + originalTimestamp: '2021-01-03T17:02:53.193Z', + }, + }, + ], + destType: 'signl4', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "destination": { - "Config": { - "apiKey": "urissi44sfgs", - "s4ServiceValue": "service", - "s4ServiceProperty": "", - "s4LocationValue": "67.3, 32.3", - "s4LocationProperty": "", - "s4AlertingScenarioValue": "single_ack", - "s4AlertingScenarioProperty": "", - "s4ExternalIDValue": "INC493933", - "s4ExternalIDProperty": "", - "s4StatusValue": "new", - "s4StatusProperty": "", - "s4Filter": false, - "eventToTitleMapping": [ + destination: { + Config: { + apiKey: 'urissi44sfgs', + s4ServiceValue: 'service', + s4ServiceProperty: '', + s4LocationValue: '67.3, 32.3', + s4LocationProperty: '', + s4AlertingScenarioValue: 'single_ack', + s4AlertingScenarioProperty: '', + s4ExternalIDValue: 'INC493933', + s4ExternalIDProperty: '', + s4StatusValue: 'new', + s4StatusProperty: '', + s4Filter: false, + eventToTitleMapping: [ { - "from": "New Alert", - "to": "Alert Created" - } - ] - } + from: 'New Alert', + to: 'Alert Created', + }, + ], + }, }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "statTags": { - "errorCategory": "dataValidation", - "destType": "SIGNL4", - "feature": "router", - "implementation": "native", - "module": "destination", - "errorType": "instrumentation" + statTags: { + errorCategory: 'dataValidation', + destType: 'SIGNL4', + feature: 'router', + implementation: 'native', + module: 'destination', + errorType: 'instrumentation', }, - "batched": false, - "statusCode": 400, - "error": "Event type identify is not supported" - } - ] - } - } - } + batched: false, + statusCode: 400, + error: 'Event type identify is not supported', + }, + ], + }, + }, + }, }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/singular/processor/data.js b/test/integrations/destinations/singular/processor/data.js index df7aa623e029..7807eefba2d4 100644 --- a/test/integrations/destinations/singular/processor/data.js +++ b/test/integrations/destinations/singular/processor/data.js @@ -1,397 +1,1973 @@ -const data = [{ - "name": "singular", - "description": "(Android) Session Event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "mysessionevent", "userId": "ruddersampleX3", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "referring_application": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "products": [{ "product_id": "789", "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" }, { "sku": "F-32", "name": "UNO", "price": 3.45, "quantity": 2, "category": "Games" }] }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", +const data = [ + { + name: 'singular', + description: '(Android) Session Event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX3', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + products: [ + { + product_id: '789', + 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', + }, + { sku: 'F-32', name: 'UNO', price: 3.45, quantity: 2, category: 'Games' }, + ], + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + c: 'wifi', + dnt: 0, + install_source: '2134dfg', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX3', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '(Android) Custom Event with multiple products', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'myevent', + userId: 'ruddersampleX4', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + products: [ + { + product_id: '789', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 2, + category: 'Games', + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.jpg', + }, + { sku: 'F-32', name: 'UNO', price: 3.45, quantity: 2, category: 'Games' }, + ], + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/evt', + headers: {}, + params: { + n: 'myevent', + p: 'Android', + i: 'com.rudderstack.demo.android', + ip: '14.5.67.21', + is_revenue_event: true, + ve: '9', + custom_user_id: 'ruddersampleX4', + utime: 1630511211, + cur: 'USD', + amt: 28, + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + receipt_signature: '1234dfghnh', + purchase_product_id: '789', + c: 'wifi', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + e: { + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + referring_application: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + fetch_token: '123asd23', + }, + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/evt', + headers: {}, + params: { + n: 'myevent', + p: 'Android', + i: 'com.rudderstack.demo.android', + ip: '14.5.67.21', + is_revenue_event: true, + ve: '9', + custom_user_id: 'ruddersampleX4', + utime: 1630511211, + cur: 'USD', + purchase_product_id: 'F-32', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + amt: 6.9, + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + receipt_signature: '1234dfghnh', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + c: 'wifi', + e: { + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + referring_application: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + fetch_token: '123asd23', + }, + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '[Error]: (Android) Custom Event without the event name', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + userId: 'ruddersampleX4', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + image_url: 'https://www.website.com/product/path.jpg', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + error: 'Event name is not present for the event', + statTags: { + destType: 'SINGULAR', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '(Android) Session Event without referring_application', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'titanium', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + is_revenue_event: true, + purchase_receipt: '12def12e3', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + image_url: 'https://www.website.com/product/path.jpg', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + sessionNotificationName: 'titanium', + custom_user_id: 'ruddersampleX5', + n: 'RudderAndroidClient', + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + utime: 1630511211, + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + dnt: 0, + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install_source: '', + c: 'wifi', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '(Android) Event with additional properties', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'myevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + is_revenue_event: true, + purchase_receipt: '12def12e3', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + image_url: 'https://www.website.com/product/path.jpg', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/evt', + headers: {}, + params: { + n: 'myevent', + p: 'Android', + i: 'com.rudderstack.demo.android', + ip: '14.5.67.21', + ve: '9', + custom_user_id: 'ruddersampleX5', + utime: 1630511211, + cur: 'USD', + purchase_receipt: '12def12e3', + purchase_product_id: '123', + purchase_transaction_id: '2134dfg', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + receipt_signature: '1234dfghnh', + amt: 20, + is_revenue_event: true, + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + c: 'wifi', + e: { + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + fetch_token: '123asd23', + name: 'Monopoly', + image_url: 'https://www.website.com/product/path.jpg', + }, + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '[Error]: (Android) Required Platform field missing for Custom Events', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'myevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + is_revenue_event: true, + purchase_receipt: '12def12e3', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + quantity: 1, + image_url: 'https://www.website.com/product/path.jpg', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + error: 'Platform name is missing from context.os.name', + statTags: { + destType: 'SINGULAR', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "Android", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "lc": "en-US", "c": "wifi", "dnt": 0, "install_source": "2134dfg", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "sessionNotificationName": "mysessionevent", "custom_user_id": "ruddersampleX3", "n": "RudderAndroidClient", "utime": 1630511211, "cn": "Android", "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "bd": "1", "install": "SM-G935F", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "install_time": 1630511211, "update_time": 1630511211, "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Custom Event with multiple products", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "myevent", "userId": "ruddersampleX4", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "referring_application": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "products": [{ "product_id": "789", "sku": "G-32", "name": "Monopoly", "price": 14, "quantity": 2, "category": "Games", "url": "https://www.website.com/product/path", "image_url": "https://www.website.com/product/path.jpg" }, { "sku": "F-32", "name": "UNO", "price": 3.45, "quantity": 2, "category": "Games" }] }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '(Android) Session Event mapped from config', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: false }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + referring_application: 'Amazon', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/evt", "headers": {}, "params": { "n": "myevent", "p": "Android", "i": "com.rudderstack.demo.android", "ip": "14.5.67.21", "is_revenue_event": true, "ve": "9", "custom_user_id": "ruddersampleX4", "utime": 1630511211, "cur": "USD", "amt": 28, "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "receipt_signature": "1234dfghnh", "purchase_product_id": "789", "c": "wifi", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "e": { "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "referring_application": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "fetch_token": "123asd23" } }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }, { - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/evt", "headers": {}, "params": { "n": "myevent", "p": "Android", "i": "com.rudderstack.demo.android", "ip": "14.5.67.21", "is_revenue_event": true, "ve": "9", "custom_user_id": "ruddersampleX4", "utime": 1630511211, "cur": "USD", "purchase_product_id": "F-32", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "amt": 6.9, "asid": "IISqwYJKoZIcNqts0jvcNvPc", "receipt_signature": "1234dfghnh", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "c": "wifi", "e": { "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "referring_application": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "fetch_token": "123asd23" } }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "[Error]: (Android) Custom Event without the event name", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "userId": "ruddersampleX4", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "referring_application": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "quantity": 1, "image_url": "https://www.website.com/product/path.jpg" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + c: 'carrier', + install_source: 'Amazon', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + dnt: 0, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX5', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, - "error": "Event name is not present for the event", "statTags": { - "destType": "SINGULAR", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Session Event without referring_application", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "titanium", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "is_revenue_event": true, "purchase_receipt": "12def12e3", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "quantity": 1, "image_url": "https://www.website.com/product/path.jpg" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '(Android) Session Event with a single product', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'Android', bluetooth: false, cellular: true, wifi: false }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'Android', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + referring_application: 'Amazon', + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "Android", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "lc": "en-US", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "sessionNotificationName": "titanium", "custom_user_id": "ruddersampleX5", "n": "RudderAndroidClient", "cn": "Android", "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "bd": "1", "install": "SM-G935F", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "utime": 1630511211, "install_time": 1630511211, "update_time": 1630511211, "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "dnt": 0, "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install_source": "", "c": "wifi", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Event with additional properties", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "myevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "is_revenue_event": true, "purchase_receipt": "12def12e3", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "quantity": 1, "image_url": "https://www.website.com/product/path.jpg" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + c: 'carrier', + lc: 'en-US', + install_source: 'Amazon', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + dnt: 0, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX5', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '[Error]: (Android) Session Event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'iOS', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + error: 'Missing required value from "properties.install_receipt"', + statTags: { + destType: 'SINGULAR', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'singular', + description: '(iOS) Session Event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attTrackingStatus: 3, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'ipados', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + skan_last_call_timestamp: '2021-09-05T15:46:51.000Z', + skan_first_call_timestamp: '2021-09-05T12:46:10.000Z', + skan_conversion_value: '2', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/evt", "headers": {}, "params": { "n": "myevent", "p": "Android", "i": "com.rudderstack.demo.android", "ip": "14.5.67.21", "ve": "9", "custom_user_id": "ruddersampleX5", "utime": 1630511211, "cur": "USD", "purchase_receipt": "12def12e3", "purchase_product_id": "123", "purchase_transaction_id": "2134dfg", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "receipt_signature": "1234dfghnh", "amt": 20, "is_revenue_event": true, "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "c": "wifi", "e": { "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "fetch_token": "123asd23", "name": "Monopoly", "image_url": "https://www.website.com/product/path.jpg" } }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "[Error]: (Android) Required Platform field missing for Custom Events", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "myevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "is_revenue_event": true, "purchase_receipt": "12def12e3", "install": "SM-G935F", "category": "Games", "checkout_id": "12345", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "quantity": 1, "image_url": "https://www.website.com/product/path.jpg" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'iOS', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + c: 'carrier', + lc: 'en-US', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + att_authorization_status: 3, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX5', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'iOS', + apns_token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + skan_conversion_value: '2', + skan_first_call_timestamp: 1630845970, + skan_last_call_timestamp: 1630856811, + bd: '1', + dnt: 0, + install: 'SM-G935F', + idfa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + idfv: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, - "error": "Platform name is missing from context.os.name", "statTags": { - "destType": "SINGULAR", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Session Event mapped from config", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "mysessionevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": false }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "referring_application": "Amazon" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '(iOS) Custom event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'myevent', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attTrackingStatus: 3, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'iOS', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + skan_last_call_timestamp: '2021-09-08T12:16:11.000Z', + skan_first_call_timestamp: '2021-09-05T15:46:51.000Z', + skan_conversion_value: '2', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "Android", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "lc": "en-US", "c": "carrier", "install_source": "Amazon", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "dnt": 0, "sessionNotificationName": "mysessionevent", "custom_user_id": "ruddersampleX5", "n": "RudderAndroidClient", "utime": 1630511211, "cn": "Android", "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "bd": "1", "install": "SM-G935F", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "install_time": 1630511211, "update_time": 1630511211, "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Session Event with a single product", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "mysessionevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "Android", "bluetooth": false, "cellular": true, "wifi": false }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "Android", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14, "referring_application": "Amazon" }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/evt', + headers: {}, + params: { + n: 'myevent', + p: 'iOS', + i: 'com.rudderstack.demo.android', + ip: '14.5.67.21', + is_revenue_event: true, + ve: '9', + att_authorization_status: 3, + custom_user_id: 'ruddersampleX5', + utime: 1630511211, + skan_conversion_value: '2', + skan_first_call_timestamp: 1630856811, + skan_last_call_timestamp: 1631103371, + cur: 'USD', + amt: 20, + purchase_product_id: '123', + purchase_transaction_id: '2134dfg', + idfa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + idfv: 'fc8d449516de0dfb', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + c: 'carrier', + e: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + fetch_token: '123asd23', + name: 'Monopoly', + }, + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "Android", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "c": "carrier", "lc": "en-US", "install_source": "Amazon", "asid": "IISqwYJKoZIcNqts0jvcNvPc", "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "dnt": 0, "sessionNotificationName": "mysessionevent", "custom_user_id": "ruddersampleX5", "n": "RudderAndroidClient", "utime": 1630511211, "cn": "Android", "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "bd": "1", "install": "SM-G935F", "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "andi": "fc8d449516de0dfb", "install_time": 1630511211, "update_time": 1630511211, "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "[Error]: (Android) Session Event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "mysessionevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "iOS", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '(Android) Lifeycle Session event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'Application Installed', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attTrackingStatus: 3, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'iOS', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, - "error": "Missing required value from \"properties.install_receipt\"", "statTags": { - "destType": "SINGULAR", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "singular", - "description": "(iOS) Session Event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "mysessionevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attTrackingStatus": 3, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "ipados", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "skan_last_call_timestamp": "2021-09-05T15:46:51.000Z", "skan_first_call_timestamp": "2021-09-05T12:46:10.000Z", "skan_conversion_value": "2", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'iOS', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + c: 'carrier', + dnt: 0, + lc: 'en-US', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + att_authorization_status: 3, + sessionNotificationName: 'Application Installed', + custom_user_id: 'ruddersampleX5', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'iOS', + apns_token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + bd: '1', + install: 'SM-G935F', + idfa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + idfv: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { JSON: {}, JSON_ARRAY: {}, XML: {}, FORM: {} }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "iOS", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "c": "carrier", "lc": "en-US", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "att_authorization_status": 3, "sessionNotificationName": "mysessionevent", "custom_user_id": "ruddersampleX5", "n": "RudderAndroidClient", "utime": 1630511211, "cn": "iOS", "apns_token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "skan_conversion_value": "2", "skan_first_call_timestamp": 1630845970, "skan_last_call_timestamp": 1630856811, "bd": "1", "dnt": 0, "install": "SM-G935F", "idfa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "idfv": "fc8d449516de0dfb", "install_time": 1630511211, "update_time": 1630511211, "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(iOS) Custom event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "myevent", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attTrackingStatus": 3, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "iOS", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "skan_last_call_timestamp": "2021-09-08T12:16:11.000Z", "skan_first_call_timestamp": "2021-09-05T15:46:51.000Z", "skan_conversion_value": "2", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '(Android) Session Event - Application Installed lifecycle event ', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'track', + event: 'Application Installed', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'window', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + skan_last_call_timestamp: '1654532056', + skan_first_call_timestamp: '1651853656', + skan_conversion_value: '2', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/evt", "headers": {}, "params": { "n": "myevent", "p": "iOS", "i": "com.rudderstack.demo.android", "ip": "14.5.67.21", "is_revenue_event": true, "ve": "9", "att_authorization_status": 3, "custom_user_id": "ruddersampleX5", "utime": 1630511211, "skan_conversion_value": "2", "skan_first_call_timestamp": 1630856811, "skan_last_call_timestamp": 1631103371, "cur": "USD", "amt": 20, "purchase_product_id": "123", "purchase_transaction_id": "2134dfg", "idfa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "idfv": "fc8d449516de0dfb", "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "c": "carrier", "e": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "fetch_token": "123asd23", "name": "Monopoly" } }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Lifeycle Session event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "Application Installed", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attTrackingStatus": 3, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "iOS", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + error: 'Platform window is not supported', + statTags: { + destType: 'SINGULAR', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - "output": - { "version": "1", "type": "REST", "method": "GET", "endpoint": "https://s2s.singular.net/api/v1/launch", "headers": {}, "params": { "p": "iOS", "i": "com.rudderstack.demo.android", "app_v": "1.0", "ip": "14.5.67.21", "ve": "9", "mo": "Android SDK built for x86", "ma": "Google", "c": "carrier", "dnt": 0, "lc": "en-US", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "att_authorization_status": 3, "sessionNotificationName": "Application Installed", "custom_user_id": "ruddersampleX5", "n": "RudderAndroidClient", "utime": 1630511211, "cn": "iOS", "apns_token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "bd": "1", "install": "SM-G935F", "idfa": "8ecd7512-2864-440c-93f3-a3cabe62525b", "idfv": "fc8d449516de0dfb", "install_time": 1630511211, "update_time": 1630511211, "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" }, "body": { "JSON": {}, "JSON_ARRAY": {}, "XML": {}, "FORM": {} }, "files": {}, "userId": "" }, - "statusCode": 200 - }] - } - } -}, { - "name": "singular", - "description": "(Android) Session Event - Application Installed lifecycle event ", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "track", "event": "Application Installed", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "window", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "skan_last_call_timestamp": "1654532056", "skan_first_call_timestamp": "1651853656", "skan_conversion_value": "2", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + }, + { + name: 'singular', + description: '[Error]: Unsupported Identify Call made', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + message: { + type: 'identify', + event: 'Application Installed', + userId: 'ruddersampleX5', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: true, + id: 'fc8d449516de0dfb', + adTrackingEnabled: true, + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { name: 'com.rudderstack.android.sdk.core', version: '0.1.4' }, + locale: 'en-US', + network: { carrier: 'iOS', bluetooth: false, cellular: true }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { name: 'window', version: '9' }, + screen: { density: 420, height: 1794, width: 1080 }, + timezone: 'Asia/Mumbai', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + purchase_transaction_id: '2134dfg', + skan_last_call_timestamp: '1654532056', + skan_first_call_timestamp: '1651853656', + skan_conversion_value: '2', + attribution_token: 'G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + install_receipt: 'MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==', + total: 20, + revenue: 15, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + sku: 'G-32', + name: 'Monopoly', + price: 14, + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, - "error": "Platform window is not supported", "statTags": { - "destType": "SINGULAR", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}, { - "name": "singular", - "description": "[Error]: Unsupported Identify Call made", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - { "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, "message": { "type": "identify", "event": "Application Installed", "userId": "ruddersampleX5", "request_ip": "14.5.67.21", "context": { "app": { "build": "1", "name": "RudderAndroidClient", "namespace": "com.rudderstack.demo.android", "version": "1.0" }, "device": { "manufacturer": "Google", "model": "Android SDK built for x86", "name": "generic_x86", "type": "android", "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", "attStatus": true, "id": "fc8d449516de0dfb", "adTrackingEnabled": true, "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" }, "library": { "name": "com.rudderstack.android.sdk.core", "version": "0.1.4" }, "locale": "en-US", "network": { "carrier": "iOS", "bluetooth": false, "cellular": true }, "campaign": { "source": "google", "medium": "medium", "term": "keyword", "content": "some content" }, "os": { "name": "window", "version": "9" }, "screen": { "density": 420, "height": 1794, "width": 1080 }, "timezone": "Asia/Mumbai" }, "properties": { "asid": "IISqwYJKoZIcNqts0jvcNvPc", "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", "install": "SM-G935F", "order_id": "1234", "affiliation": "Apple Store", "receipt_signature": "1234dfghnh", "purchase_transaction_id": "2134dfg", "skan_last_call_timestamp": "1654532056", "skan_first_call_timestamp": "1651853656", "skan_conversion_value": "2", "attribution_token": "G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQS=", "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", "install_receipt": "MIISqwYJKoZIcNqts0jvcNvPcK7yuj0KhJ9nTTQ54kDKfReihzc6aw==", "total": 20, "revenue": 15, "shipping": 22, "tax": 1, "discount": 1.5, "coupon": "ImagePro", "currency": "USD", "fetch_token": "123asd23", "product_id": "123", "sku": "G-32", "name": "Monopoly", "price": 14 }, "timestamp": "2021-09-01T15:46:51.000Z" } }, - ], - "method": "POST", - }, - "pathSuffix": "", + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { sessionEventName: 'mysessionevent' }, + { sessionEventName: 'randomuser' }, + { sessionEventName: 'titanium' }, + ], + }, + }, + error: 'Event type identify is not supported', + statTags: { + destType: 'SINGULAR', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, }, - "output": { - "response": { - "status": 200, - "body": [{ - - "destination": { "Config": { "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", "sessionEventList": [{ "sessionEventName": "mysessionevent" }, { "sessionEventName": "randomuser" }, { "sessionEventName": "titanium" }] } }, - "error": "Event type identify is not supported", "statTags": { - "destType": "SINGULAR", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } -}]; module.exports = { - data -} \ No newline at end of file + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/singular/router/data.js b/test/integrations/destinations/singular/router/data.js index 048b2b86288b..e3107582bcd6 100644 --- a/test/integrations/destinations/singular/router/data.js +++ b/test/integrations/destinations/singular/router/data.js @@ -1,1020 +1,1011 @@ const data = [ { - "name": "singular", - "description": "Successfull Track Call with sessionEventList from Config ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ - { - "sessionEventName": "mysessionevent" - }, - { - "sessionEventName": "randomuser" - }, - { - "sessionEventName": "titanium" - } - ] - } - }, - "metadata": { - "jobId": 1 - }, - "message": { - "type": "track", - "event": "mysessionevent", - "userId": "ruddersampleX3", - "request_ip": "14.5.67.21", - "context": { - "app": { - "build": "1", - "name": "RudderAndroidClient", - "namespace": "com.rudderstack.demo.android", - "version": "1.0" - }, - "device": { - "manufacturer": "Google", - "model": "Android SDK built for x86", - "name": "generic_x86", - "type": "android", - "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "attStatus": "true", - "id": "fc8d449516de0dfb", - "adTrackingEnabled": "true", - "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "0.1.4" - }, - "locale": "en-US", - "network": { - "carrier": "Android", - "bluetooth": false, - "cellular": true, - "wifi": true - }, - "campaign": { - "source": "google", - "medium": "medium", - "term": "keyword", - "content": "some content" - }, - "os": { - "name": "Android", - "version": "9" - }, - "screen": { - "density": 420, - "height": 1794, - "width": 1080 - }, - "timezone": "Asia/Mumbai", - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" + name: 'singular', + description: 'Successfull Track Call with sessionEventList from Config ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { + sessionEventName: 'mysessionevent', + }, + { + sessionEventName: 'randomuser', + }, + { + sessionEventName: 'titanium', + }, + ], + }, + }, + metadata: { + jobId: 1, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX3', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: 'true', + id: 'fc8d449516de0dfb', + adTrackingEnabled: 'true', + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', }, - "properties": { - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "install": "SM-G935F", - "category": "Games", - "checkout_id": "12345", - "order_id": "1234", - "affiliation": "Apple Store", - "receipt_signature": "1234dfghnh", - "referring_application": "2134dfg", - "total": 20, - "revenue": 15.0, - "shipping": 22, - "tax": 1, - "discount": 1.5, - "coupon": "ImagePro", - "currency": "USD", - "fetch_token": "123asd23", - "product_id": "123", - "products": [ - { - "product_id": "789", - "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" - }, - { - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ] + os: { + name: 'Android', + version: '9', }, - "timestamp": "2021-09-01T15:46:51.000Z" - } - }] - , "destType": "singular" + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15.0, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + products: [ + { + product_id: '789', + 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', + }, + { + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + destType: 'singular', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", "userId": "", - "method": "GET", - "endpoint": "https://s2s.singular.net/api/v1/launch", - "headers": {}, - "params": { - "p": "Android", - "i": "com.rudderstack.demo.android", - "app_v": "1.0", - "ip": "14.5.67.21", - "ve": "9", - "mo": "Android SDK built for x86", - "ma": "Google", - "lc": "en-US", - "install_source": "2134dfg", - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "dnt": 1, - "sessionNotificationName": "mysessionevent", - "custom_user_id": "ruddersampleX3", - "n": "RudderAndroidClient", - "utime": 1630511211, - "cn": "Android", - "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", - "bd": "1", - "install": "SM-G935F", - "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "andi": "fc8d449516de0dfb", - "install_time": 1630511211, - "update_time": 1630511211, - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", - "c": "wifi", - "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" - }, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + install_source: '2134dfg', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + dnt: 1, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX3', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + c: 'wifi', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 1 - } + jobId: 1, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ { - "sessionEventName": "mysessionevent" + sessionEventName: 'mysessionevent', }, { - "sessionEventName": "randomuser" + sessionEventName: 'randomuser', }, { - "sessionEventName": "titanium" - } - ] - } - } - } - ] - } - } - } + sessionEventName: 'titanium', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "singular", - "description": "Successful Track Event with properties.products", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ - { - "sessionEventName": "mysessionevent" - }, - { - "sessionEventName": "randomuser" - }, - { - "sessionEventName": "titanium" - } - ] - } - }, - "metadata": { - "jobId": 2 - }, - "message": { - "type": "track", - "event": "mysessionevent", - "userId": "ruddersampleX3", - "request_ip": "14.5.67.21", - "context": { - "app": { - "build": "1", - "name": "RudderAndroidClient", - "namespace": "com.rudderstack.demo.android", - "version": "1.0" - }, - "device": { - "manufacturer": "Google", - "model": "Android SDK built for x86", - "name": "generic_x86", - "type": "android", - "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "attStatus": "true", - "id": "fc8d449516de0dfb", - "adTrackingEnabled": "true", - "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "0.1.4" - }, - "locale": "en-US", - "network": { - "carrier": "Android", - "bluetooth": false, - "cellular": true, - "wifi": true - }, - "campaign": { - "source": "google", - "medium": "medium", - "term": "keyword", - "content": "some content" - }, - "os": { - "name": "Android", - "version": "9" - }, - "screen": { - "density": 420, - "height": 1794, - "width": 1080 - }, - "timezone": "Asia/Mumbai", - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" + name: 'singular', + description: 'Successful Track Event with properties.products', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { + sessionEventName: 'mysessionevent', + }, + { + sessionEventName: 'randomuser', + }, + { + sessionEventName: 'titanium', + }, + ], + }, + }, + metadata: { + jobId: 2, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX3', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: 'true', + id: 'fc8d449516de0dfb', + adTrackingEnabled: 'true', + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', }, - "properties": { - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "install": "SM-G935F", - "category": "Games", - "checkout_id": "12345", - "order_id": "1234", - "affiliation": "Apple Store", - "receipt_signature": "1234dfghnh", - "referring_application": "2134dfg", - "total": 20, - "revenue": 15.0, - "shipping": 22, - "tax": 1, - "discount": 1.5, - "coupon": "ImagePro", - "currency": "USD", - "fetch_token": "123asd23", - "product_id": "123", - "products": [ - { - "product_id": "789", - "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" - }, - { - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ] + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, }, - "timestamp": "2021-09-01T15:46:51.000Z" - } - }] - , "destType": "singular" + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15.0, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + products: [ + { + product_id: '789', + 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', + }, + { + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + destType: 'singular', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", "userId": "", - "method": "GET", - "endpoint": "https://s2s.singular.net/api/v1/launch", - "headers": {}, - "params": { - "p": "Android", - "i": "com.rudderstack.demo.android", - "app_v": "1.0", - "ip": "14.5.67.21", - "ve": "9", - "mo": "Android SDK built for x86", - "ma": "Google", - "lc": "en-US", - "install_source": "2134dfg", - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "dnt": 1, - "sessionNotificationName": "mysessionevent", - "custom_user_id": "ruddersampleX3", - "n": "RudderAndroidClient", - "utime": 1630511211, - "cn": "Android", - "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", - "bd": "1", - "install": "SM-G935F", - "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "andi": "fc8d449516de0dfb", - "install_time": 1630511211, - "update_time": 1630511211, - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", - "c": "wifi", - "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" - }, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + install_source: '2134dfg', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + dnt: 1, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX3', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + c: 'wifi', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ { - "sessionEventName": "mysessionevent" + sessionEventName: 'mysessionevent', }, { - "sessionEventName": "randomuser" + sessionEventName: 'randomuser', }, { - "sessionEventName": "titanium" - } - ] - } - } - } - ] - } - } - } + sessionEventName: 'titanium', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "singular", - "description": "Successfull Track Call with sessionEventList from Config", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ - { - "sessionEventName": "mysessionevent" - }, - { - "sessionEventName": "randomuser" - }, - { - "sessionEventName": "titanium" - } - ] - } - }, - "metadata": { - "jobId": 3 - }, - "message": { - "type": "track", - "event": "mysessionevent", - "userId": "ruddersampleX3", - "request_ip": "14.5.67.21", - "context": { - "app": { - "build": "1", - "name": "RudderAndroidClient", - "namespace": "com.rudderstack.demo.android", - "version": "1.0" - }, - "device": { - "manufacturer": "Google", - "model": "Android SDK built for x86", - "name": "generic_x86", - "type": "android", - "advertisingId": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "attStatus": "true", - "id": "fc8d449516de0dfb", - "adTrackingEnabled": "true", - "token": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "0.1.4" - }, - "locale": "en-US", - "network": { - "carrier": "Android", - "bluetooth": false, - "cellular": true, - "wifi": true - }, - "campaign": { - "source": "google", - "medium": "medium", - "term": "keyword", - "content": "some content" - }, - "os": { - "name": "Android", - "version": "9" - }, - "screen": { - "density": 420, - "height": 1794, - "width": 1080 - }, - "timezone": "Asia/Mumbai", - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)" + name: 'singular', + description: 'Successfull Track Call with sessionEventList from Config', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ + { + sessionEventName: 'mysessionevent', + }, + { + sessionEventName: 'randomuser', + }, + { + sessionEventName: 'titanium', + }, + ], + }, + }, + metadata: { + jobId: 3, + }, + message: { + type: 'track', + event: 'mysessionevent', + userId: 'ruddersampleX3', + request_ip: '14.5.67.21', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + advertisingId: '8ecd7512-2864-440c-93f3-a3cabe62525b', + attStatus: 'true', + id: 'fc8d449516de0dfb', + adTrackingEnabled: 'true', + token: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + }, + os: { + name: 'Android', + version: '9', }, - "properties": { - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "url": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "install": "SM-G935F", - "category": "Games", - "checkout_id": "12345", - "order_id": "1234", - "affiliation": "Apple Store", - "receipt_signature": "1234dfghnh", - "referring_application": "2134dfg", - "total": 20, - "revenue": 15.0, - "shipping": 22, - "tax": 1, - "discount": 1.5, - "coupon": "ImagePro", - "currency": "USD", - "fetch_token": "123asd23", - "product_id": "123", - "products": [ - { - "product_id": "789", - "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" - }, - { - "sku": "F-32", - "name": "UNO", - "price": 3.45, - "quantity": 2, - "category": "Games" - } - ] + screen: { + density: 420, + height: 1794, + width: 1080, }, - "timestamp": "2021-09-01T15:46:51.000Z" - } - }] - , "destType": "singular" + timezone: 'Asia/Mumbai', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + properties: { + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + url: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + install: 'SM-G935F', + category: 'Games', + checkout_id: '12345', + order_id: '1234', + affiliation: 'Apple Store', + receipt_signature: '1234dfghnh', + referring_application: '2134dfg', + total: 20, + revenue: 15.0, + shipping: 22, + tax: 1, + discount: 1.5, + coupon: 'ImagePro', + currency: 'USD', + fetch_token: '123asd23', + product_id: '123', + products: [ + { + product_id: '789', + 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', + }, + { + sku: 'F-32', + name: 'UNO', + price: 3.45, + quantity: 2, + category: 'Games', + }, + ], + }, + timestamp: '2021-09-01T15:46:51.000Z', + }, + }, + ], + destType: 'singular', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", "userId": "", - "method": "GET", - "endpoint": "https://s2s.singular.net/api/v1/launch", - "headers": {}, - "params": { - "p": "Android", - "i": "com.rudderstack.demo.android", - "app_v": "1.0", - "ip": "14.5.67.21", - "ve": "9", - "mo": "Android SDK built for x86", - "ma": "Google", - "lc": "en-US", - "install_source": "2134dfg", - "asid": "IISqwYJKoZIcNqts0jvcNvPc", - "openuri": "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1", - "dnt": 1, - "sessionNotificationName": "mysessionevent", - "custom_user_id": "ruddersampleX3", - "n": "RudderAndroidClient", - "utime": 1630511211, - "cn": "Android", - "fcm": "bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1", - "bd": "1", - "install": "SM-G935F", - "aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b", - "andi": "fc8d449516de0dfb", - "install_time": 1630511211, - "update_time": 1630511211, - "ua": "Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)", - "c": "wifi", - "a": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd" - }, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/launch', + headers: {}, + params: { + p: 'Android', + i: 'com.rudderstack.demo.android', + app_v: '1.0', + ip: '14.5.67.21', + ve: '9', + mo: 'Android SDK built for x86', + ma: 'Google', + lc: 'en-US', + install_source: '2134dfg', + asid: 'IISqwYJKoZIcNqts0jvcNvPc', + openuri: 'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1', + dnt: 1, + sessionNotificationName: 'mysessionevent', + custom_user_id: 'ruddersampleX3', + n: 'RudderAndroidClient', + utime: 1630511211, + cn: 'Android', + fcm: 'bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1', + bd: '1', + install: 'SM-G935F', + aifa: '8ecd7512-2864-440c-93f3-a3cabe62525b', + andi: 'fc8d449516de0dfb', + install_time: 1630511211, + update_time: 1630511211, + ua: 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + c: 'wifi', + a: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, }, - "metadata": [ + metadata: [ { - "jobId": 3 - } + jobId: 3, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "ab7eb717-cdd8-tr63-a7f5-93339d7beelkd", - "sessionEventList": [ + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: 'ab7eb717-cdd8-tr63-a7f5-93339d7beelkd', + sessionEventList: [ { - "sessionEventName": "mysessionevent" + sessionEventName: 'mysessionevent', }, { - "sessionEventName": "randomuser" + sessionEventName: 'randomuser', }, { - "sessionEventName": "titanium" - } - ] - } - } - } - ] - } - } - } + sessionEventName: 'titanium', + }, + ], + }, + }, + }, + ], + }, + }, + }, }, { - "name": "singular", - "description": "Successfull Track Call of event Application Backgrounded", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "type": "track", - "event": "Application Backgrounded", - "sentAt": "2023-01-19T14:25:24.234Z", - "userId": "68e214f1-ac84-4241-b27d-78a18f59f21e", - "channel": "mobile", - "context": { - "os": { - "name": "iOS", - "version": "16.2" - }, - "app": { - "build": "5013", - "version": "0.5.13", - "namespace": "com.yabimoney" - }, - "device": { - "id": "cc06ff5e-838b-4e33-9d90-4ab5a6068bec", - "name": "iPhone", - "type": "iOS", - "model": "iPhone", - "manufacturer": "Apple", - "advertisingId": "1", - "adTrackingEnabled": true, - "attTrackingStatus": 0 - }, - "locale": "en-AE", - "screen": { - "width": 844, - "height": 390, - "density": 3 - }, - "traits": { - "phone": "", - "userId": "68e214f1-ac84-4241-b27d-78a18f59f21e", - "tenant_id": "tgTV2Bbv", - "anonymousId": "cc06ff5e-838b-4e33-9d90-4ab5a6068bec", - "yabi_user_id": "uCh5IS8p", - "subscription_type": "" - }, - "library": { - "name": "rudder-ios-library", - "version": "1.8.0" - }, - "network": { - "wifi": true, - "carrier": "etisalat", - "cellular": false - }, - "timezone": "Asia/Dubai", - "sessionId": 1674138119 + name: 'singular', + description: 'Successfull Track Call of event Application Backgrounded', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + type: 'track', + event: 'Application Backgrounded', + sentAt: '2023-01-19T14:25:24.234Z', + userId: '68e214f1-ac84-4241-b27d-78a18f59f21e', + channel: 'mobile', + context: { + os: { + name: 'iOS', + version: '16.2', }, - "rudderId": "b7bbf406-aa7f-4d64-a388-925675e78f36", - "messageId": "b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b", - "timestamp": "2023-01-19T14:25:07.532Z", - "receivedAt": "2023-01-19T14:25:25.465Z", - "request_ip": "87.201.98.151", - "anonymousId": "cc06ff5e-838b-4e33-9d90-4ab5a6068bec", - "integrations": { - "All": true + app: { + build: '5013', + version: '0.5.13', + namespace: 'com.yabimoney', }, - "originalTimestamp": "2023-01-19T14:25:06.301Z" - }, - "destination": { - "secretConfig": {}, - "Config": { - "apiKey": "apiKey", - "apiSecret": "apiSecreth9h3984bnsdfkh98kjiu4h", - "sessionEventList": [ - { - "sessionEventName": "test_event" - } - ], - "blacklistedEvents": [ - { - "eventName": "" - } - ], - "whitelistedEvents": [ - { - "eventName": "" - } - ], - "eventFilteringOption": "whitelistedEvents", - "eventDelivery": false, - "eventDeliveryTS": 1663919255086 + device: { + id: 'cc06ff5e-838b-4e33-9d90-4ab5a6068bec', + name: 'iPhone', + type: 'iOS', + model: 'iPhone', + manufacturer: 'Apple', + advertisingId: '1', + adTrackingEnabled: true, + attTrackingStatus: 0, }, - "liveEventsConfig": { - "eventDelivery": false, - "eventDeliveryTS": 1663919255086 + locale: 'en-AE', + screen: { + width: 844, + height: 390, + density: 3, }, - "ID": "2EhlBrBduwN2NX4pJ7nrVDHAz6C", - "workspaceId": "1sUXvPs0hYgjBxSfjG4gqnRFNoP", - "DestinationDefinition": { - "config": { - "destConfig": { - "ios": [ - "useNativeSDK" - ], - "android": [ - "useNativeSDK" - ], - "cordova": [ - "useNativeSDK" - ], - "reactnative": [ - "useNativeSDK" - ], - "defaultConfig": [ - "apiKey", - "apiSecret", - "sessionEventList", - "blacklistedEvents", - "whitelistedEvents", - "eventFilteringOption" - ] - }, - "excludeKeys": [], - "includeKeys": [ - "apiKey", - "apiSecret", - "sessionEventList", - "blacklistedEvents", - "whitelistedEvents", - "eventFilteringOption" - ], - "transformAt": "processor", - "transformAtV1": "processor", - "supportedSourceTypes": [ - "android", - "ios", - "flutter", - "reactnative", - "cordova", - "web", - "amp", - "cloud", - "warehouse" + traits: { + phone: '', + userId: '68e214f1-ac84-4241-b27d-78a18f59f21e', + tenant_id: 'tgTV2Bbv', + anonymousId: 'cc06ff5e-838b-4e33-9d90-4ab5a6068bec', + yabi_user_id: 'uCh5IS8p', + subscription_type: '', + }, + library: { + name: 'rudder-ios-library', + version: '1.8.0', + }, + network: { + wifi: true, + carrier: 'etisalat', + cellular: false, + }, + timezone: 'Asia/Dubai', + sessionId: 1674138119, + }, + rudderId: 'b7bbf406-aa7f-4d64-a388-925675e78f36', + messageId: 'b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b', + timestamp: '2023-01-19T14:25:07.532Z', + receivedAt: '2023-01-19T14:25:25.465Z', + request_ip: '87.201.98.151', + anonymousId: 'cc06ff5e-838b-4e33-9d90-4ab5a6068bec', + integrations: { + All: true, + }, + originalTimestamp: '2023-01-19T14:25:06.301Z', + }, + destination: { + secretConfig: {}, + Config: { + apiKey: 'apiKey', + apiSecret: 'apiSecreth9h3984bnsdfkh98kjiu4h', + sessionEventList: [ + { + sessionEventName: 'test_event', + }, + ], + blacklistedEvents: [ + { + eventName: '', + }, + ], + whitelistedEvents: [ + { + eventName: '', + }, + ], + eventFilteringOption: 'whitelistedEvents', + eventDelivery: false, + eventDeliveryTS: 1663919255086, + }, + liveEventsConfig: { + eventDelivery: false, + eventDeliveryTS: 1663919255086, + }, + ID: '2EhlBrBduwN2NX4pJ7nrVDHAz6C', + workspaceId: '1sUXvPs0hYgjBxSfjG4gqnRFNoP', + DestinationDefinition: { + config: { + destConfig: { + ios: ['useNativeSDK'], + android: ['useNativeSDK'], + cordova: ['useNativeSDK'], + reactnative: ['useNativeSDK'], + defaultConfig: [ + 'apiKey', + 'apiSecret', + 'sessionEventList', + 'blacklistedEvents', + 'whitelistedEvents', + 'eventFilteringOption', ], - "saveDestinationResponse": true - }, - "configSchema": {}, - "responseRules": {}, - "options": null, - "id": "2642K92ztyRPghLlFL9GXfwjWDp", - "name": "SINGULAR", - "displayName": "Singular", - "category": null, - "createdAt": "2022-03-07T15:54:30.619Z", - "updatedAt": "2022-10-12T12:44:07.624Z" + }, + excludeKeys: [], + includeKeys: [ + 'apiKey', + 'apiSecret', + 'sessionEventList', + 'blacklistedEvents', + 'whitelistedEvents', + 'eventFilteringOption', + ], + transformAt: 'processor', + transformAtV1: 'processor', + supportedSourceTypes: [ + 'android', + 'ios', + 'flutter', + 'reactnative', + 'cordova', + 'web', + 'amp', + 'cloud', + 'warehouse', + ], + saveDestinationResponse: true, }, - "transformations": [], - "isConnectionEnabled": true, - "isProcessorEnabled": true, - "name": "Singular", - "enabled": true, - "deleted": false, - "createdAt": "2022-09-13T07:52:44.981Z", - "updatedAt": "2022-09-23T07:47:35.092Z", - "revisionId": "2F9znalm2FSPmdj99jJbsoVLSVM", - "secretVersion": 1 - }, - "metadata": { - "sourceId": "1vPJD7KzElDJ0N7SRf1fZ32z1SW", - "workspaceId": "1sUXvPs0hYgjBxSfjG4gqnRFNoP", - "namespace": "mynamespace", - "instanceId": "mynamespace-v0-rudderstack-0", - "sourceType": "Javascript", - "sourceCategory": "", - "trackingPlanId": "", - "trackingPlanVersion": 0, - "sourceTpConfig": null, - "mergedTpConfig": null, - "destinationId": "2EhlBrBduwN2NX4pJ7nrVDHAz6C", - "jobRunId": "", - "jobId": 68205922, - "sourceBatchId": "", - "sourceJobId": "", - "sourceJobRunId": "", - "sourceTaskId": "", - "sourceTaskRunId": "", - "recordId": null, - "destinationType": "SINGULAR", - "messageId": "b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b", - "oauthAccessToken": "", - "messageIds": null, - "rudderId": "67895e15-d37f-49d6-9017-e8d29264e31f<<>>yolanda.rivera2@yahoo.com", - "receivedAt": "2022-05-02T07:20:13.809Z", - "eventName": "", - "eventType": "track", - "sourceDefinitionId": "1TW48i2bIzEl1HPf825cEznfIM8", - "destinationDefinitionId": "" - } - }] - , "destType": "singular" + configSchema: {}, + responseRules: {}, + options: null, + id: '2642K92ztyRPghLlFL9GXfwjWDp', + name: 'SINGULAR', + displayName: 'Singular', + category: null, + createdAt: '2022-03-07T15:54:30.619Z', + updatedAt: '2022-10-12T12:44:07.624Z', + }, + transformations: [], + isConnectionEnabled: true, + isProcessorEnabled: true, + name: 'Singular', + enabled: true, + deleted: false, + createdAt: '2022-09-13T07:52:44.981Z', + updatedAt: '2022-09-23T07:47:35.092Z', + revisionId: '2F9znalm2FSPmdj99jJbsoVLSVM', + secretVersion: 1, + }, + metadata: { + sourceId: '1vPJD7KzElDJ0N7SRf1fZ32z1SW', + workspaceId: '1sUXvPs0hYgjBxSfjG4gqnRFNoP', + namespace: 'mynamespace', + instanceId: 'mynamespace-v0-rudderstack-0', + sourceType: 'Javascript', + sourceCategory: '', + trackingPlanId: '', + trackingPlanVersion: 0, + sourceTpConfig: null, + mergedTpConfig: null, + destinationId: '2EhlBrBduwN2NX4pJ7nrVDHAz6C', + jobRunId: '', + jobId: 68205922, + sourceBatchId: '', + sourceJobId: '', + sourceJobRunId: '', + sourceTaskId: '', + sourceTaskRunId: '', + recordId: null, + destinationType: 'SINGULAR', + messageId: 'b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b', + oauthAccessToken: '', + messageIds: null, + rudderId: '67895e15-d37f-49d6-9017-e8d29264e31f<<>>yolanda.rivera2@yahoo.com', + receivedAt: '2022-05-02T07:20:13.809Z', + eventName: '', + eventType: 'track', + sourceDefinitionId: '1TW48i2bIzEl1HPf825cEznfIM8', + destinationDefinitionId: '', + }, + }, + ], + destType: 'singular', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "version": "1", - "type": "REST", "userId": "", - "method": "GET", - "endpoint": "https://s2s.singular.net/api/v1/evt", - "headers": {}, - "params": { - "n": "Application Backgrounded", - "p": "iOS", - "i": "com.yabimoney", - "ip": "87.201.98.151", - "ve": "16.2", - "att_authorization_status": 0, - "custom_user_id": "68e214f1-ac84-4241-b27d-78a18f59f21e", - "utime": 1674138307, - "idfa": "1", - "idfv": "cc06ff5e-838b-4e33-9d90-4ab5a6068bec", - "c": "wifi", - "a": "apiKey", - "e": {} - }, - "body": { - "JSON": {}, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} + batchedRequest: { + version: '1', + type: 'REST', + userId: '', + method: 'GET', + endpoint: 'https://s2s.singular.net/api/v1/evt', + headers: {}, + params: { + n: 'Application Backgrounded', + p: 'iOS', + i: 'com.yabimoney', + ip: '87.201.98.151', + ve: '16.2', + att_authorization_status: 0, + custom_user_id: '68e214f1-ac84-4241-b27d-78a18f59f21e', + utime: 1674138307, + idfa: '1', + idfv: 'cc06ff5e-838b-4e33-9d90-4ab5a6068bec', + c: 'wifi', + a: 'apiKey', + e: {}, + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, }, - "metadata": [ + metadata: [ { - "sourceId": "1vPJD7KzElDJ0N7SRf1fZ32z1SW", - "workspaceId": "1sUXvPs0hYgjBxSfjG4gqnRFNoP", - "namespace": "mynamespace", - "instanceId": "mynamespace-v0-rudderstack-0", - "sourceType": "Javascript", - "sourceCategory": "", - "trackingPlanId": "", - "trackingPlanVersion": 0, - "sourceTpConfig": null, - "mergedTpConfig": null, - "destinationId": "2EhlBrBduwN2NX4pJ7nrVDHAz6C", - "jobRunId": "", - "jobId": 68205922, - "sourceBatchId": "", - "sourceJobId": "", - "sourceJobRunId": "", - "sourceTaskId": "", - "sourceTaskRunId": "", - "recordId": null, - "destinationType": "SINGULAR", - "messageId": "b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b", - "oauthAccessToken": "", - "messageIds": null, - "rudderId": "67895e15-d37f-49d6-9017-e8d29264e31f<<>>yolanda.rivera2@yahoo.com", - "receivedAt": "2022-05-02T07:20:13.809Z", - "eventName": "", - "eventType": "track", - "sourceDefinitionId": "1TW48i2bIzEl1HPf825cEznfIM8", - "destinationDefinitionId": "" - } + sourceId: '1vPJD7KzElDJ0N7SRf1fZ32z1SW', + workspaceId: '1sUXvPs0hYgjBxSfjG4gqnRFNoP', + namespace: 'mynamespace', + instanceId: 'mynamespace-v0-rudderstack-0', + sourceType: 'Javascript', + sourceCategory: '', + trackingPlanId: '', + trackingPlanVersion: 0, + sourceTpConfig: null, + mergedTpConfig: null, + destinationId: '2EhlBrBduwN2NX4pJ7nrVDHAz6C', + jobRunId: '', + jobId: 68205922, + sourceBatchId: '', + sourceJobId: '', + sourceJobRunId: '', + sourceTaskId: '', + sourceTaskRunId: '', + recordId: null, + destinationType: 'SINGULAR', + messageId: 'b9e9534b-b3b7-4bdb-8d59-062e1fbf4e2b', + oauthAccessToken: '', + messageIds: null, + rudderId: '67895e15-d37f-49d6-9017-e8d29264e31f<<>>yolanda.rivera2@yahoo.com', + receivedAt: '2022-05-02T07:20:13.809Z', + eventName: '', + eventType: 'track', + sourceDefinitionId: '1TW48i2bIzEl1HPf825cEznfIM8', + destinationDefinitionId: '', + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "secretConfig": {}, - "Config": { - "apiKey": "apiKey", - "apiSecret": "apiSecreth9h3984bnsdfkh98kjiu4h", - "sessionEventList": [ + batched: false, + statusCode: 200, + destination: { + secretConfig: {}, + Config: { + apiKey: 'apiKey', + apiSecret: 'apiSecreth9h3984bnsdfkh98kjiu4h', + sessionEventList: [ { - "sessionEventName": "test_event" - } + sessionEventName: 'test_event', + }, ], - "blacklistedEvents": [ + blacklistedEvents: [ { - "eventName": "" - } + eventName: '', + }, ], - "whitelistedEvents": [ + whitelistedEvents: [ { - "eventName": "" - } + eventName: '', + }, ], - "eventFilteringOption": "whitelistedEvents", - "eventDelivery": false, - "eventDeliveryTS": 1663919255086 - }, - "liveEventsConfig": { - "eventDelivery": false, - "eventDeliveryTS": 1663919255086 - }, - "ID": "2EhlBrBduwN2NX4pJ7nrVDHAz6C", - "workspaceId": "1sUXvPs0hYgjBxSfjG4gqnRFNoP", - "DestinationDefinition": { - "config": { - "destConfig": { - "ios": [ - "useNativeSDK" - ], - "android": [ - "useNativeSDK" - ], - "cordova": [ - "useNativeSDK" - ], - "reactnative": [ - "useNativeSDK" + eventFilteringOption: 'whitelistedEvents', + eventDelivery: false, + eventDeliveryTS: 1663919255086, + }, + liveEventsConfig: { + eventDelivery: false, + eventDeliveryTS: 1663919255086, + }, + ID: '2EhlBrBduwN2NX4pJ7nrVDHAz6C', + workspaceId: '1sUXvPs0hYgjBxSfjG4gqnRFNoP', + DestinationDefinition: { + config: { + destConfig: { + ios: ['useNativeSDK'], + android: ['useNativeSDK'], + cordova: ['useNativeSDK'], + reactnative: ['useNativeSDK'], + defaultConfig: [ + 'apiKey', + 'apiSecret', + 'sessionEventList', + 'blacklistedEvents', + 'whitelistedEvents', + 'eventFilteringOption', ], - "defaultConfig": [ - "apiKey", - "apiSecret", - "sessionEventList", - "blacklistedEvents", - "whitelistedEvents", - "eventFilteringOption" - ] - }, - "excludeKeys": [], - "includeKeys": [ - "apiKey", - "apiSecret", - "sessionEventList", - "blacklistedEvents", - "whitelistedEvents", - "eventFilteringOption" + }, + excludeKeys: [], + includeKeys: [ + 'apiKey', + 'apiSecret', + 'sessionEventList', + 'blacklistedEvents', + 'whitelistedEvents', + 'eventFilteringOption', ], - "transformAt": "processor", - "transformAtV1": "processor", - "supportedSourceTypes": [ - "android", - "ios", - "flutter", - "reactnative", - "cordova", - "web", - "amp", - "cloud", - "warehouse" + transformAt: 'processor', + transformAtV1: 'processor', + supportedSourceTypes: [ + 'android', + 'ios', + 'flutter', + 'reactnative', + 'cordova', + 'web', + 'amp', + 'cloud', + 'warehouse', ], - "saveDestinationResponse": true + saveDestinationResponse: true, }, - "configSchema": {}, - "responseRules": {}, - "options": null, - "id": "2642K92ztyRPghLlFL9GXfwjWDp", - "name": "SINGULAR", - "displayName": "Singular", - "category": null, - "createdAt": "2022-03-07T15:54:30.619Z", - "updatedAt": "2022-10-12T12:44:07.624Z" - }, - "transformations": [], - "isConnectionEnabled": true, - "isProcessorEnabled": true, - "name": "Singular", - "enabled": true, - "deleted": false, - "createdAt": "2022-09-13T07:52:44.981Z", - "updatedAt": "2022-09-23T07:47:35.092Z", - "revisionId": "2F9znalm2FSPmdj99jJbsoVLSVM", - "secretVersion": 1 - } - } - ] - } - } - } + configSchema: {}, + responseRules: {}, + options: null, + id: '2642K92ztyRPghLlFL9GXfwjWDp', + name: 'SINGULAR', + displayName: 'Singular', + category: null, + createdAt: '2022-03-07T15:54:30.619Z', + updatedAt: '2022-10-12T12:44:07.624Z', + }, + transformations: [], + isConnectionEnabled: true, + isProcessorEnabled: true, + name: 'Singular', + enabled: true, + deleted: false, + createdAt: '2022-09-13T07:52:44.981Z', + updatedAt: '2022-09-23T07:47:35.092Z', + revisionId: '2F9znalm2FSPmdj99jJbsoVLSVM', + secretVersion: 1, + }, + }, + ], + }, + }, + }, }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/testTypes.d.ts b/test/integrations/destinations/testTypes.d.ts index d0da7254afd3..57a221517b6d 100644 --- a/test/integrations/destinations/testTypes.d.ts +++ b/test/integrations/destinations/testTypes.d.ts @@ -1,39 +1,37 @@ interface requestType { - method: string, - body?: any, - headers?: Record, - params?: Record + method: string; + body?: any; + headers?: Record; + params?: Record; } interface responseType { - status: number, - body?: any, - headers?: Record + status: number; + body?: any; + headers?: Record; } interface inputType { - request: requestType, - pathSuffix?: string + request: requestType; + pathSuffix?: string; } interface outputType { - response?: responseType + response?: responseType; } interface mockType { - request: requestType, - response: responseType + request: requestType; + response: responseType; } interface testCaseDataType { - name: string, - description: string, - feature: string, - module: string, - version?: string - input: inputType, - output: outputType, - mock?: mockType[] -}; - - + name: string; + description: string; + feature: string; + module: string; + version?: string; + input: inputType; + output: outputType; + mock?: mockType[]; +} diff --git a/test/integrations/destinations/user/processor/data.js b/test/integrations/destinations/user/processor/data.js index 8fab3a5dfe62..d6566fe62142 100644 --- a/test/integrations/destinations/user/processor/data.js +++ b/test/integrations/destinations/user/processor/data.js @@ -1,255 +1,730 @@ -const data = [{ - "name": "user", - "description": "No Message type", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"userId":"test@123","context":{"traits":{"email":"test@rudderstack.com","username":"Samle_putUserName","firstName":"uday"}},"integrations":{"All":true,"user.com":{"lookup":"email"}}},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userEvents":[{"rsEventName":"login","userEventName":"product viewed"}],"companyAttributesMapping":[{"from":"category","to":"companycategory"},{"from":"owner","to":"companyowner"}]}}}, - ], - "method": "POST", +const data = [ + { + name: 'user', + description: 'No Message type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'test@123', + context: { + traits: { + email: 'test@rudderstack.com', + username: 'Samle_putUserName', + firstName: 'uday', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userEvents":[{"rsEventName":"login","userEventName":"product viewed"}],"companyAttributesMapping":[{"from":"category","to":"companycategory"},{"from":"owner","to":"companyowner"}]}}, - "error": "Event type is required", "statTags": { - "destType": "USER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "user", - "description": "Unsupported Type", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"userId":"test@123","type":"trackUser","context":{"traits":{"email":"test@rudderstack.com","firstName":"test","lastName":"rudderstack","age":15,"gender":"male","status":"user","city":"Kalkata","country":"india","tags":["productuser"],"phone":"9225467887"},"externalId":[{"type":"userKey","id":"masncbjasbdljajdl"}]},"traits":{"googleUrl":"www.google.com"}},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}}, - ], - "method": "POST", + }, + integrations: { All: true, 'user.com': { lookup: 'email' } }, + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userEvents: [{ rsEventName: 'login', userEventName: 'product viewed' }], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userEvents: [{ rsEventName: 'login', userEventName: 'product viewed' }], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], + }, + }, + error: 'Event type is required', + statTags: { + destType: 'USER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'Unsupported Type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'test@123', + type: 'trackUser', + context: { + traits: { + email: 'test@rudderstack.com', + firstName: 'test', + lastName: 'rudderstack', + age: 15, + gender: 'male', + status: 'user', + city: 'Kalkata', + country: 'india', + tags: ['productuser'], + phone: '9225467887', + }, + externalId: [{ type: 'userKey', id: 'masncbjasbdljajdl' }], + }, + traits: { googleUrl: 'www.google.com' }, + }, + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + error: 'Event type trackuser is not supported', + statTags: { + destType: 'USER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'track call without event', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'user@123', + type: 'track', + properties: { category: 'e-commerce', activity: 'user logged in' }, + traits: { email: 'rudderstack@test.com' }, + integrations: { 'user.com': { lookup: 'email' } }, + timestamp: '2020-02-02T00:23:09.544Z', + }, + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + error: 'Parameter event is required', + statTags: { + destType: 'USER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'group call without name', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '507f191e810c19729de860ea', + channel: 'browser', + context: { + 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 }, + messageId: '022bb90c-bbac-11e4-8dfc-aa07a5b093db', + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + email: 'business@rudderstack.com', + plan: 'premium', + logins: 5, + address: { + street: '6th St', + city: 'San Francisco', + state: 'CA', + postalCode: '94103', + country: 'USA', + }, + }, + type: 'group', + userId: 'user@123', + }, + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { + Config: { apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', appSubdomain: 'commander' }, + }, + error: 'Parameter name is required', + statTags: { + destType: 'USER', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'identify call with userKey as externalId', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'test@16', + type: 'identify', + context: { + traits: { + email: 'test@rudderstack.com', + firstName: 'test', + lastName: 'rudderstack', + age: 15, + gender: 'male', + status: 'user', + city: 'Kalkata', + country: 'india', + tags: ['productuser'], + phone: '9225467887', + useroccupation: 'software engineer', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}, - "error": "Event type trackuser is not supported", "statTags": { - "destType": "USER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "user", - "description": "track call without event", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"userId":"user@123","type":"track","properties":{"category":"e-commerce","activity":"user logged in"},"traits":{"email":"rudderstack@test.com"},"integrations":{"user.com":{"lookup":"email"}},"timestamp":"2020-02-02T00:23:09.544Z"},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}}, - ], - "method": "POST", + externalId: [{ type: 'userKey', id: 'lel1c5u1wuk8' }], + }, + traits: { googleUrl: 'www.google.com' }, + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + FORM: {}, + JSON: { + age: 15, + country: 'india', + custom_id: 'test@16', + email: 'test@rudderstack.com', + first_name: 'test', + gender: 2, + google_url: 'www.google.com', + last_name: 'rudderstack', + occupation: 'software engineer', + phone_number: '9225467887', + status: 2, + tags: ['productuser'], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://commander.user.com/api/public/users/27/', + files: {}, + headers: { + Accept: '*/*;version=2', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', + 'Content-Type': 'application/json', + }, + method: 'PUT', + params: {}, + type: 'REST', + version: '1', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'identify call with email as lookup field', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + userId: 'test@12', + type: 'identify', + context: { + traits: { + email: 'test@rudderstack.com', + firstName: 'test', + lastName: 'rudderstack', + age: 15, + gender: 'female', + status: 'visitor', + city: 'ahmedabad', + country: 'india', + phone: '9225467887', + useroccupation: 'mechanical engineer', + }, + }, + traits: { googleUrl: 'www.google.com' }, + integrations: { All: true, 'user.com': { lookup: 'email' } }, + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + age: 15, + email: 'test@rudderstack.com', + gender: 3, + status: 1, + country: 'india', + custom_id: 'test@12', + last_name: 'rudderstack', + first_name: 'test', + google_url: 'www.google.com', + occupation: 'mechanical engineer', + phone_number: '9225467887', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'PUT', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', + }, + version: '1', + endpoint: 'https://commander.user.com/api/public/users/59/', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'track call without any lookup field(fallback to userId)', + 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.1.1-rc.2', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}, - "error": "Parameter event is required", "statTags": { - "destType": "USER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "user", - "description": "group call without name", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"507f191e810c19729de860ea","channel":"browser","context":{"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},"messageId":"022bb90c-bbac-11e4-8dfc-aa07a5b093db","receivedAt":"2015-02-23T22:28:55.387Z","sentAt":"2015-02-23T22:28:55.111Z","timestamp":"2015-02-23T22:28:55.111Z","traits":{"email":"business@rudderstack.com","plan":"premium","logins":5,"address":{"street":"6th St","city":"San Francisco","state":"CA","postalCode":"94103","country":"USA"}},"type":"group","userId":"user@123"},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}}, - ], - "method": "POST", + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.1-rc.2' }, + locale: 'en-GB', + os: { name: '', version: '' }, + page: { + path: '/tests/html/index4.html', + referrer: '', + search: '', + title: '', + url: 'http://localhost/tests/html/index4.html', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander"}}, - "error": "Parameter name is required", "statTags": { - "destType": "USER", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "user", - "description": "identify call with userKey as externalId", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"userId":"test@16","type":"identify","context":{"traits":{"email":"test@rudderstack.com","firstName":"test","lastName":"rudderstack","age":15,"gender":"male","status":"user","city":"Kalkata","country":"india","tags":["productuser"],"phone":"9225467887","useroccupation":"software engineer"},"externalId":[{"type":"userKey","id":"lel1c5u1wuk8"}]},"traits":{"googleUrl":"www.google.com"}},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userAttributesMapping":[{"from":"useroccupation","to":"occupation"}]}}}, - ], - "method": "POST", + screen: { density: 2 }, + traits: { age: 23, email: 'testmp@rudderstack.com', firstname: 'Test Kafka' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36', + }, + event: 'login', + messageId: '37b75e61-9bd2-4fb8-91ed-e3a064905f3a', + originalTimestamp: '2020-04-17T14:42:44.724Z', + properties: { test_prop_1: 'test prop', test_prop_2: 1232 }, + timestamp: '2022-09-13T20:12:44.757+05:30', + type: 'track', + userId: '43', + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ + { + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + data: { test_prop_1: 'test prop', test_prop_2: 1232 }, + name: 'product viewed', + user_id: 44, + timestamp: 1663080164, }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"FORM":{},"JSON":{"age":15,"country":"india","custom_id":"test@16","email":"test@rudderstack.com","first_name":"test","gender":2,"google_url":"www.google.com","last_name":"rudderstack","occupation":"software engineer","phone_number":"9225467887","status":2,"tags":["productuser"]},"JSON_ARRAY":{},"XML":{}},"endpoint":"https://commander.user.com/api/public/users/27/","files":{},"headers":{"Accept":"*/*;version=2","Authorization":"Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf","Content-Type":"application/json"},"method":"PUT","params":{},"type":"REST","version":"1","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "user", - "description": "identify call with email as lookup field", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"userId":"test@12","type":"identify","context":{"traits":{"email":"test@rudderstack.com","firstName":"test","lastName":"rudderstack","age":15,"gender":"female","status":"visitor","city":"ahmedabad","country":"india","phone":"9225467887","useroccupation":"mechanical engineer"}},"traits":{"googleUrl":"www.google.com"},"integrations":{"All":true,"user.com":{"lookup":"email"}}},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userAttributesMapping":[{"from":"useroccupation","to":"occupation"}]}}}, - ], - "method": "POST", + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', + }, + version: '1', + endpoint: 'https://commander.user.com/api/public/events/', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'page call without any lookup field(fallback to userId)', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + category: 'page category', + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.9', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{"age":15,"email":"test@rudderstack.com","gender":3,"status":1,"country":"india","custom_id":"test@12","last_name":"rudderstack","first_name":"test","google_url":"www.google.com","occupation":"mechanical engineer","phone_number":"9225467887"},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"PUT","params":{},"headers":{"Accept":"*/*;version=2","Content-Type":"application/json","Authorization":"Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf"},"version":"1","endpoint":"https://commander.user.com/api/public/users/59/","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "user", - "description": "track call without any lookup field(fallback to userId)", - "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.1.1-rc.2"},"library":{"name":"RudderLabs JavaScript SDK","version":"1.1.1-rc.2"},"locale":"en-GB","os":{"name":"","version":""},"page":{"path":"/tests/html/index4.html","referrer":"","search":"","title":"","url":"http://localhost/tests/html/index4.html"},"screen":{"density":2},"traits":{"age":23,"email":"testmp@rudderstack.com","firstname":"Test Kafka"},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"},"event":"login","messageId":"37b75e61-9bd2-4fb8-91ed-e3a064905f3a","originalTimestamp":"2020-04-17T14:42:44.724Z","properties":{"test_prop_1":"test prop","test_prop_2":1232},"timestamp":"2022-09-13T20:12:44.757+05:30","type":"track","userId":"43"},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userAttributesMapping":[{"from":"useroccupation","to":"occupation"}],"userEvents":[{"rsEventName":"login","userEventName":"product viewed","eventProperties":[{"from":"count","to":"productcount"}]}]}}}, - ], - "method": "POST", + campaign: {}, + library: { name: 'RudderLabs JavaScript SDK', version: '1.1.9' }, + locale: 'en-GB', + os: { name: '', version: '' }, + page: { + path: '/testing', + referrer: '', + search: '', + title: '', + url: 'https://pagecall.com/testing', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{"data":{"test_prop_1":"test prop","test_prop_2":1232},"name":"product viewed","user_id":44,"timestamp":1663080164},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"POST","params":{},"headers":{"Accept":"*/*;version=2","Content-Type":"application/json","Authorization":"Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf"},"version":"1","endpoint":"https://commander.user.com/api/public/events/","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "user", - "description": "page call without any lookup field(fallback to userId)", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"category":"page category","channel":"web","context":{"app":{"build":"1.0.0","name":"RudderLabs JavaScript SDK","namespace":"com.rudderlabs.javascript","version":"1.1.9"},"campaign":{},"library":{"name":"RudderLabs JavaScript SDK","version":"1.1.9"},"locale":"en-GB","os":{"name":"","version":""},"page":{"path":"/testing","referrer":"","search":"","title":"","url":"https://pagecall.com/testing"},"screen":{"density":2},"traits":{},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"},"integrations":{"All":true},"messageId":"397fdf96-daee-46c8-ac38-5d717cd8cabd","name":"page name","originalTimestamp":"2021-01-04T14:13:05.801+05:30","properties":{"category":"page category","name":"page name","path":"/testing","referrer":"","search":"","title":"","url":"https://pagecall.com/testing"},"request_ip":"[::1]","rudderId":"2d03081c-8053-4cce-9abf-bb024f747900","timestamp":"2021-01-04T14:13:05.801+05:30","type":"page","userId":"43"},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userAttributesMapping":[{"from":"useroccupation","to":"occupation"}],"userEvents":[{"rsEventName":"login","userEventName":"product viewed","eventProperties":[{"from":"count","to":"productcount"}]}]}}}, - ], - "method": "POST", + screen: { density: 2 }, + traits: {}, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', + }, + integrations: { All: true }, + messageId: '397fdf96-daee-46c8-ac38-5d717cd8cabd', + name: 'page name', + originalTimestamp: '2021-01-04T14:13:05.801+05:30', + properties: { + category: 'page category', + name: 'page name', + path: '/testing', + referrer: '', + search: '', + title: '', + url: 'https://pagecall.com/testing', + }, + request_ip: '[::1]', + rudderId: '2d03081c-8053-4cce-9abf-bb024f747900', + timestamp: '2021-01-04T14:13:05.801+05:30', + type: 'page', + userId: '43', + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ + { + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + page_path: '/testing', + timestamp: '2021-01-04T14:13:05.801+05:30', + client_user: 'rpl0vjwysmc0', + page_domain: 'https://pagecall.com/testing', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{"page_path":"/testing","timestamp":"2021-01-04T14:13:05.801+05:30","client_user":"rpl0vjwysmc0","page_domain":"https://pagecall.com/testing"},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"POST","params":{},"headers":{"Accept":"*/*;version=2","Content-Type":"application/json","Authorization":"Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf"},"version":"1","endpoint":"https://commander.user.com/api/public/site-views/","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "user", - "description": "User.com group call", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"channel":"browser","context":{"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},"userId":"user@123","groupId":"group@795","messageId":"022bb90c-bbac-11e4-8dfc-aa07a5b093db","receivedAt":"2015-02-23T22:28:55.387Z","sentAt":"2015-02-23T22:28:55.111Z","timestamp":"2015-02-23T22:28:55.111Z","traits":{"name":"rudder ventures","email":"business@rudderstack.com","address":{"street":"6th St","city":"San Francisco","state":"CA","postalCode":"94103","country":"USA","owner":"testuser"}},"type":"group"},"destination":{"Config":{"apiKey":"262fbbda-b85b-48b8-a719-c2fceaf8afaf","appSubdomain":"commander","userAttributesMapping":[{"from":"useroccupation","to":"occupation"}],"userEvents":[{"rsEventName":"login","userEventName":"product viewed","eventProperties":[{"from":"count","to":"productcount"}]}],"companyAttributesMapping":[{"from":"category","to":"companycategory"},{"from":"owner","to":"companyowner"}]}}}, - ], - "method": "POST", + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', + }, + version: '1', + endpoint: 'https://commander.user.com/api/public/site-views/', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'user', + description: 'User.com group call', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'browser', + context: { + 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 }, + userId: 'user@123', + groupId: 'group@795', + messageId: '022bb90c-bbac-11e4-8dfc-aa07a5b093db', + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + name: 'rudder ventures', + email: 'business@rudderstack.com', + address: { + street: '6th St', + city: 'San Francisco', + state: 'CA', + postalCode: '94103', + country: 'USA', + owner: 'testuser', }, - "pathSuffix": "", - }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{"user_id":52,"user_custom_id":"user@123"},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"POST","params":{},"headers":{"Accept":"*/*;version=2","Content-Type":"application/json","Authorization":"Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf"},"version":"1","endpoint":"https://commander.user.com/api/public/companies/21/add_member/","userId":""}, - "statusCode": 200}] - } - } - }]; module.exports = { - data - } \ No newline at end of file + }, + type: 'group', + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ + { + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], + }, + }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { user_id: 52, user_custom_id: 'user@123' }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', + }, + version: '1', + endpoint: 'https://commander.user.com/api/public/companies/21/add_member/', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/user/router/data.js b/test/integrations/destinations/user/router/data.js index 018bd5c26f47..4a48d3953615 100644 --- a/test/integrations/destinations/user/router/data.js +++ b/test/integrations/destinations/user/router/data.js @@ -1,272 +1,273 @@ const data = [ { - "name": "user", - "description": "Succesfull Group call ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "channel": "browser", - "context": { - "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 - }, - "userId": "user@123", - "groupId": "group@795", - "messageId": "022bb90c-bbac-11e4-8dfc-aa07a5b093db", - "receivedAt": "2015-02-23T22:28:55.387Z", - "sentAt": "2015-02-23T22:28:55.111Z", - "timestamp": "2015-02-23T22:28:55.111Z", - "traits": { - "name": "rudder ventures", - "email": "business@rudderstack.com", - "address": { - "street": "6th St", - "city": "San Francisco", - "state": "CA", - "postalCode": "94103", - "country": "USA", - "owner": "testuser" - } + name: 'user', + description: 'Succesfull Group call ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + channel: 'browser', + context: { + 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, + }, + userId: 'user@123', + groupId: 'group@795', + messageId: '022bb90c-bbac-11e4-8dfc-aa07a5b093db', + receivedAt: '2015-02-23T22:28:55.387Z', + sentAt: '2015-02-23T22:28:55.111Z', + timestamp: '2015-02-23T22:28:55.111Z', + traits: { + name: 'rudder ventures', + email: 'business@rudderstack.com', + address: { + street: '6th St', + city: 'San Francisco', + state: 'CA', + postalCode: '94103', + country: 'USA', + owner: 'testuser', }, - "type": "group" }, - "metadata": { - "jobId": 1 + type: 'group', + }, + metadata: { + jobId: 1, + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ + { + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], }, - "destination": { - "Config": { - "apiKey": "262fbbda-b85b-48b8-a719-c2fceaf8afaf", - "appSubdomain": "commander", - "userAttributesMapping": [{ "from": "useroccupation", "to": "occupation" }], - "userEvents": [ - { - "rsEventName": "login", - "userEventName": "product viewed", - "eventProperties": [{ "from": "count", "to": "productcount" }] - } - ], - "companyAttributesMapping": [ - { "from": "category", "to": "companycategory" }, - { "from": "owner", "to": "companyowner" } - ] - } - } - }] - , "destType": "user" + }, + }, + ], + destType: 'user', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": { - "user_id": 52, - "user_custom_id": "user@123" + batchedRequest: { + body: { + XML: {}, + FORM: {}, + JSON: { + user_id: 52, + user_custom_id: 'user@123', }, - "JSON_ARRAY": {} + JSON_ARRAY: {}, }, - "type": "REST", - "files": {}, - "method": "POST", - "params": {}, - "headers": { - "Accept": "*/*;version=2", - "Content-Type": "application/json", - "Authorization": "Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf" + type: 'REST', + files: {}, + method: 'POST', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', }, - "version": "1", + version: '1', - "userId": "", - "endpoint": "https://commander.user.com/api/public/companies/21/add_member/" + userId: '', + endpoint: 'https://commander.user.com/api/public/companies/21/add_member/', }, - "metadata": [ + metadata: [ { - "jobId": 1 - } + jobId: 1, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "262fbbda-b85b-48b8-a719-c2fceaf8afaf", - "appSubdomain": "commander", - "userAttributesMapping": [{ "from": "useroccupation", "to": "occupation" }], - "userEvents": [ + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ { - "rsEventName": "login", - "userEventName": "product viewed", - "eventProperties": [{ "from": "count", "to": "productcount" }] - } + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, ], - "companyAttributesMapping": [ - { "from": "category", "to": "companycategory" }, - { "from": "owner", "to": "companyowner" } - ] - } - } + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], + }, + }, }, - ] - } - } - } + ], + }, + }, + }, }, { - "name": "user", - "description": "Test 1", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "userId": "test@12", - "type": "identify", - "context": { - "traits": { - "email": "test@rudderstack.com", - "firstName": "test", - "lastName": "rudderstack", - "age": 15, - "gender": "female", - "status": "visitor", - "city": "ahmedabad", - "country": "india", - "phone": "9225467887", - "useroccupation": "mechanical engineer" - } + name: 'user', + description: 'Test 1', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + userId: 'test@12', + type: 'identify', + context: { + traits: { + email: 'test@rudderstack.com', + firstName: 'test', + lastName: 'rudderstack', + age: 15, + gender: 'female', + status: 'visitor', + city: 'ahmedabad', + country: 'india', + phone: '9225467887', + useroccupation: 'mechanical engineer', }, - "traits": { - "googleUrl": "www.google.com" + }, + traits: { + googleUrl: 'www.google.com', + }, + integrations: { + All: true, + user: { + lookup: 'email', }, - "integrations": { - "All": true, - "user": { - "lookup": "email" - } - } }, - "metadata": { - "jobId": 2 + }, + metadata: { + jobId: 2, + }, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ + { + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, + ], }, - "destination": { - "Config": { - "apiKey": "262fbbda-b85b-48b8-a719-c2fceaf8afaf", - "appSubdomain": "commander", - "userAttributesMapping": [{ "from": "useroccupation", "to": "occupation" }], - "userEvents": [ - { - "rsEventName": "login", - "userEventName": "product viewed", - "eventProperties": [{ "from": "count", "to": "productcount" }] - } - ], - "companyAttributesMapping": [ - { "from": "category", "to": "companycategory" }, - { "from": "owner", "to": "companyowner" } - ] - } - } - }] - , "destType": "user" + }, + }, + ], + destType: 'user', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": { - "age": 15, - "email": "test@rudderstack.com", - "gender": 3, - "status": 1, - "country": "india", - "custom_id": "test@12", - "last_name": "rudderstack", - "first_name": "test", - "google_url": "www.google.com", - "occupation": "mechanical engineer", - "phone_number": "9225467887" + batchedRequest: { + body: { + XML: {}, + FORM: {}, + JSON: { + age: 15, + email: 'test@rudderstack.com', + gender: 3, + status: 1, + country: 'india', + custom_id: 'test@12', + last_name: 'rudderstack', + first_name: 'test', + google_url: 'www.google.com', + occupation: 'mechanical engineer', + phone_number: '9225467887', }, - "JSON_ARRAY": {} + JSON_ARRAY: {}, }, - "type": "REST", + type: 'REST', - "userId": "", - "files": {}, - "method": "PUT", - "params": {}, - "headers": { - "Accept": "*/*;version=2", - "Content-Type": "application/json", - "Authorization": "Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf" + userId: '', + files: {}, + method: 'PUT', + params: {}, + headers: { + Accept: '*/*;version=2', + 'Content-Type': 'application/json', + Authorization: 'Token 262fbbda-b85b-48b8-a719-c2fceaf8afaf', }, - "version": "1", - "endpoint": "https://commander.user.com/api/public/users/59/" + version: '1', + endpoint: 'https://commander.user.com/api/public/users/59/', }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200, - "destination": { - "Config": { - "apiKey": "262fbbda-b85b-48b8-a719-c2fceaf8afaf", - "appSubdomain": "commander", - "userAttributesMapping": [{ "from": "useroccupation", "to": "occupation" }], - "userEvents": [ + batched: false, + statusCode: 200, + destination: { + Config: { + apiKey: '262fbbda-b85b-48b8-a719-c2fceaf8afaf', + appSubdomain: 'commander', + userAttributesMapping: [{ from: 'useroccupation', to: 'occupation' }], + userEvents: [ { - "rsEventName": "login", - "userEventName": "product viewed", - "eventProperties": [{ "from": "count", "to": "productcount" }] - } + rsEventName: 'login', + userEventName: 'product viewed', + eventProperties: [{ from: 'count', to: 'productcount' }], + }, + ], + companyAttributesMapping: [ + { from: 'category', to: 'companycategory' }, + { from: 'owner', to: 'companyowner' }, ], - "companyAttributesMapping": [ - { "from": "category", "to": "companycategory" }, - { "from": "owner", "to": "companyowner" } - ] - } - } - } - ] - } - } - } - } + }, + }, + }, + ], + }, + }, + }, + }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/test/integrations/destinations/woopra/processor/data.js b/test/integrations/destinations/woopra/processor/data.js index 2a88a5389063..1aeac7c1c3c1 100644 --- a/test/integrations/destinations/woopra/processor/data.js +++ b/test/integrations/destinations/woopra/processor/data.js @@ -1,141 +1,320 @@ -const data = [{ - "name": "woopra", - "description": "Create a new Visitor with projectName inside Integration Object and no externalId", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"21e13f4bc7ceddad","context":{"app":{"build":"4","name":"RuddCDN"},"device":{"id":"3f034872-5e28-45a1-9eda-ce22a3e36d1a","name":"generic_x86_arm"},"os":{"name":"Android","version":"9"},"timezone":"Asia/Kolkata","traits":{"anonymousId":"21e13f4bc7ceddad"},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"},"event":"First Investment","integrations":{"woopra":{"projectName":"abc.com"}},"messageId":"1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb","originalTimestamp":"2020-09-28T19:53:31.900Z","traits":{"name":"Anant jain","email":"anant@r.com","hasPurchased":"yes","address":"H.No. abc Street PQRS ","state":"Delhi","title":"Mr"},"receivedAt":"2020-09-29T14:50:43.005+05:30","sentAt":"2020-09-28T19:53:44.998Z","timestamp":"2020-09-29T14:50:29.907+05:30","type":"identify"},"destination":{"Config":{"projectName":"int.com"}}}, - ], - "method": "POST", - }, - "pathSuffix": "", +const data = [ + { + name: 'woopra', + description: + 'Create a new Visitor with projectName inside Integration Object and no externalId', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + context: { + app: { build: '4', name: 'RuddCDN' }, + device: { id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', name: 'generic_x86_arm' }, + os: { name: 'Android', version: '9' }, + timezone: 'Asia/Kolkata', + traits: { anonymousId: '21e13f4bc7ceddad' }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + }, + event: 'First Investment', + integrations: { woopra: { projectName: 'abc.com' } }, + messageId: '1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb', + originalTimestamp: '2020-09-28T19:53:31.900Z', + traits: { + name: 'Anant jain', + email: 'anant@r.com', + hasPurchased: 'yes', + address: 'H.No. abc Street PQRS ', + state: 'Delhi', + title: 'Mr', + }, + receivedAt: '2020-09-29T14:50:43.005+05:30', + sentAt: '2020-09-28T19:53:44.998Z', + timestamp: '2020-09-29T14:50:29.907+05:30', + type: 'identify', }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"GET","params":{"os":"Android","app":"RuddCDN","browser":"Chrome86.0.4240.111","cookie":"21e13f4bc7ceddad","Project":"abc.com","cv_email":"anant@r.com","cv_name":"Anant jain","cv_state":"Delhi","cv_title":"Mr","cv_hasPurchased":"yes","timestamp":"1601371229907","cv_address":"H.No. abc Street PQRS "},"headers":{},"version":"1","endpoint":"https://www.woopra.com/track/identify","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "woopra", - "description": "Send track event with app name but no app build and woopraid inside externalid", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"21e13f4bc7ceddad","channel":"mobile","context":{"externalId":[{"type":"woopraId","id":"abcd123451"}],"app":{"build":"4"},"device":{"id":"3f034872-5e28-45a1-9eda-ce22a3e36d1a","name":"generic_x86_arm"},"library":{"name":"com.rudderstack.android.sdk.core","version":"1.0.6"},"os":{"name":"Android","version":"9"},"timezone":"Asia/Kolkata","traits":{"anonymousId":"21e13f4bc7ceddad","customProp":"customValue"},"userAgent":"Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)"},"event":"First Investment","messageId":"1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb","originalTimestamp":"2020-09-28T19:53:31.900Z","properties":{"currency":"EUR","revenue":20.37566},"receivedAt":"2020-09-29T14:50:43.005+05:30","sentAt":"2020-09-28T19:53:44.998Z","timestamp":"2020-09-29T14:50:29.907+05:30","type":"track"},"destination":{"Config":{"projectName":"int.com"}}}, - ], - "method": "POST", - }, - "pathSuffix": "", + destination: { Config: { projectName: 'int.com' } }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { XML: {}, FORM: {}, JSON: {}, JSON_ARRAY: {} }, + type: 'REST', + files: {}, + method: 'GET', + params: { + os: 'Android', + app: 'RuddCDN', + browser: 'Chrome86.0.4240.111', + cookie: '21e13f4bc7ceddad', + Project: 'abc.com', + cv_email: 'anant@r.com', + cv_name: 'Anant jain', + cv_state: 'Delhi', + cv_title: 'Mr', + cv_hasPurchased: 'yes', + timestamp: '1601371229907', + cv_address: 'H.No. abc Street PQRS ', + }, + headers: {}, + version: '1', + endpoint: 'https://www.woopra.com/track/identify', + userId: '', }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"GET","params":{"os":"Android","event":"First Investment","cookie":"abcd123451","Project":"int.com","timestamp":"1601371229907","ce_currency":"EUR","ce_revenue":20.37566,"cv_customProp":"customValue","cv_anonymousId":"21e13f4bc7ceddad"},"headers":{},"version":"1","endpoint":"https://www.woopra.com/track/ce","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "woopra", - "description": "Send Page event with projectName from Config and no cv_id sources", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"21e13f4bc7ceddad","channel":"mobile","context":{"app":{"build":"4","name":"RuddCDN"},"page":{"referrer":"google.com"},"device":{"id":"3f034872-5e28-45a1-9eda-ce22a3e36d1a","name":"generic_x86_arm"},"library":{"name":"com.rudderstack.android.sdk.core","version":"1.0.6"},"os":{"name":"Android","version":"9"},"timezone":"Asia/Kolkata","traits":{"customProp":"customValue"},"userAgent":"Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)"},"name":"Home","messageId":"1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb","originalTimestamp":"2020-09-28T19:53:31.900Z","properties":{"title":"Home | RudderStack","url":"http://www.rudderstack.com"},"receivedAt":"2020-09-29T14:50:43.005+05:30","sentAt":"2020-09-28T19:53:44.998Z","timestamp":"2020-09-29T14:50:29.907+05:30","type":"page"},"destination":{"Config":{"projectName":"abc.com"}}}, - ], - "method": "POST", - }, - "pathSuffix": "", + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'woopra', + description: 'Send track event with app name but no app build and woopraid inside externalid', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + context: { + externalId: [{ type: 'woopraId', id: 'abcd123451' }], + app: { build: '4' }, + device: { id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', name: 'generic_x86_arm' }, + library: { name: 'com.rudderstack.android.sdk.core', version: '1.0.6' }, + os: { name: 'Android', version: '9' }, + timezone: 'Asia/Kolkata', + traits: { anonymousId: '21e13f4bc7ceddad', customProp: 'customValue' }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + event: 'First Investment', + messageId: '1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb', + originalTimestamp: '2020-09-28T19:53:31.900Z', + properties: { currency: 'EUR', revenue: 20.37566 }, + receivedAt: '2020-09-29T14:50:43.005+05:30', + sentAt: '2020-09-28T19:53:44.998Z', + timestamp: '2020-09-29T14:50:29.907+05:30', + type: 'track', }, - "output":{ - "response": { - "status": 200, - "body": [{ - "output": - {"body":{"XML":{},"FORM":{},"JSON":{},"JSON_ARRAY":{}},"type":"REST","files":{},"method":"GET","params":{"os":"Android","app":"RuddCDN","event":"Viewed Home Page","ce_url":"http://www.rudderstack.com","timestamp":"1601371229907","Project":"abc.com","ce_title":"Home | RudderStack","cv_customProp":"customValue","cookie":"21e13f4bc7ceddad","ce_referrer":"google.com"},"headers":{},"version":"1","endpoint":"https://www.woopra.com/track/ce","userId":""}, - "statusCode": 200}] - } - } - },{ - "name": "woopra", - "description": "Unsupported Message Type", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"21e13f4bc7ceddad","channel":"mobile","event":"First Investment","integrations":{"woopra":"int.com"},"type":"group"},"destination":{"Config":{"projectName":"int.com"}}}, - ], - "method": "POST", - }, - "pathSuffix": "", + destination: { Config: { projectName: 'int.com' } }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { XML: {}, FORM: {}, JSON: {}, JSON_ARRAY: {} }, + type: 'REST', + files: {}, + method: 'GET', + params: { + os: 'Android', + event: 'First Investment', + cookie: 'abcd123451', + Project: 'int.com', + timestamp: '1601371229907', + ce_currency: 'EUR', + ce_revenue: 20.37566, + cv_customProp: 'customValue', + cv_anonymousId: '21e13f4bc7ceddad', + }, + headers: {}, + version: '1', + endpoint: 'https://www.woopra.com/track/ce', + userId: '', }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"projectName":"int.com"}}, - "error": "Message type group is not supported", "statTags": { - "destType": "WOOPRA", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - },{ - "name": "woopra", - "description": "Event Name Not Provided ", - "feature": "processor", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": [ - {"message":{"anonymousId":"21e13f4bc7ceddad","channel":"mobile","integrations":{"woopra":"int.com"},"type":"track"},"destination":{"Config":{"projectName":"int.com"}}}, - ], - "method": "POST", - }, - "pathSuffix": "", + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'woopra', + description: 'Send Page event with projectName from Config and no cv_id sources', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + context: { + app: { build: '4', name: 'RuddCDN' }, + page: { referrer: 'google.com' }, + device: { id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', name: 'generic_x86_arm' }, + library: { name: 'com.rudderstack.android.sdk.core', version: '1.0.6' }, + os: { name: 'Android', version: '9' }, + timezone: 'Asia/Kolkata', + traits: { customProp: 'customValue' }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + name: 'Home', + messageId: '1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb', + originalTimestamp: '2020-09-28T19:53:31.900Z', + properties: { title: 'Home | RudderStack', url: 'http://www.rudderstack.com' }, + receivedAt: '2020-09-29T14:50:43.005+05:30', + sentAt: '2020-09-28T19:53:44.998Z', + timestamp: '2020-09-29T14:50:29.907+05:30', + type: 'page', }, - "output":{ - "response": { - "status": 200, - "body": [{ - - "destination": {"Config":{"projectName":"int.com"}}, - "error": "Event Name can not be empty", "statTags": { - "destType": "WOOPRA", - "errorCategory": "dataValidation", - "errorType": "instrumentation", - "feature": "processor", - "implementation": "native", - "module": "destination", - }, - "statusCode": 400 - }] - } - } - }]; module.exports = { - data - } \ No newline at end of file + destination: { Config: { projectName: 'abc.com' } }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { XML: {}, FORM: {}, JSON: {}, JSON_ARRAY: {} }, + type: 'REST', + files: {}, + method: 'GET', + params: { + os: 'Android', + app: 'RuddCDN', + event: 'Viewed Home Page', + ce_url: 'http://www.rudderstack.com', + timestamp: '1601371229907', + Project: 'abc.com', + ce_title: 'Home | RudderStack', + cv_customProp: 'customValue', + cookie: '21e13f4bc7ceddad', + ce_referrer: 'google.com', + }, + headers: {}, + version: '1', + endpoint: 'https://www.woopra.com/track/ce', + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'woopra', + description: 'Unsupported Message Type', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + event: 'First Investment', + integrations: { woopra: 'int.com' }, + type: 'group', + }, + destination: { Config: { projectName: 'int.com' } }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { Config: { projectName: 'int.com' } }, + error: 'Message type group is not supported', + statTags: { + destType: 'WOOPRA', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, + { + name: 'woopra', + description: 'Event Name Not Provided ', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + integrations: { woopra: 'int.com' }, + type: 'track', + }, + destination: { Config: { projectName: 'int.com' } }, + }, + ], + method: 'POST', + }, + pathSuffix: '', + }, + output: { + response: { + status: 200, + body: [ + { + destination: { Config: { projectName: 'int.com' } }, + error: 'Event Name can not be empty', + statTags: { + destType: 'WOOPRA', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, +]; +module.exports = { + data, +}; diff --git a/test/integrations/destinations/woopra/router/data.js b/test/integrations/destinations/woopra/router/data.js index 13c322574c1d..6dd124acd298 100644 --- a/test/integrations/destinations/woopra/router/data.js +++ b/test/integrations/destinations/woopra/router/data.js @@ -1,309 +1,311 @@ const data = [ { - "name": "woopra", - "description": "Succesfull Idenitfy Call", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "traits": { - "anonymousId": "21e13f4bc7ceddad" - }, - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + name: 'woopra', + description: 'Succesfull Idenitfy Call', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + context: { + app: { + build: '4', + name: 'RuddCDN', + }, + device: { + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + name: 'generic_x86_arm', }, - "integrations": { - "woopra": { - "projectName": "abc.com" - } + os: { + name: 'Android', + version: '9', }, - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "traits": { - "Name": "Anant jain", - "email": "anant@r.com", - "hasPurchased": "yes", - "address": "H.No. abc Street PQRS ", - "state": "Delhi", - "title": "Mr" + timezone: 'Asia/Kolkata', + traits: { + anonymousId: '21e13f4bc7ceddad', }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "identify" + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + integrations: { + woopra: { + projectName: 'abc.com', + }, + }, + messageId: '1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb', + originalTimestamp: '2020-09-28T19:53:31.900Z', + traits: { + Name: 'Anant jain', + email: 'anant@r.com', + hasPurchased: 'yes', + address: 'H.No. abc Street PQRS ', + state: 'Delhi', + title: 'Mr', }, - "destination": { - "Config": { - "projectName": "int.com" - } + receivedAt: '2020-09-29T14:50:43.005+05:30', + sentAt: '2020-09-28T19:53:44.998Z', + timestamp: '2020-09-29T14:50:29.907+05:30', + type: 'identify', + }, + destination: { + Config: { + projectName: 'int.com', }, - "metadata": { - "jobId": 1 - } - }] - , "destType": "woopra" + }, + metadata: { + jobId: 1, + }, + }, + ], + destType: 'woopra', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": {}, - "JSON_ARRAY": {} + batchedRequest: { + body: { + XML: {}, + FORM: {}, + JSON: {}, + JSON_ARRAY: {}, }, - "userId": "", - "type": "REST", - "files": {}, - "method": "GET", - "params": { - "os": "Android", - "app": "RuddCDN", - "cookie": "21e13f4bc7ceddad", - "Project": "abc.com", - "cv_email": "anant@r.com", - "cv_state": "Delhi", - "cv_title": "Mr", - "cv_hasPurchased": "yes", - "cv_address": "H.No. abc Street PQRS ", - "timestamp": "1601371229907", - "cv_Name": "Anant jain" + userId: '', + type: 'REST', + files: {}, + method: 'GET', + params: { + os: 'Android', + app: 'RuddCDN', + cookie: '21e13f4bc7ceddad', + Project: 'abc.com', + cv_email: 'anant@r.com', + cv_state: 'Delhi', + cv_title: 'Mr', + cv_hasPurchased: 'yes', + cv_address: 'H.No. abc Street PQRS ', + timestamp: '1601371229907', + cv_Name: 'Anant jain', }, - "headers": {}, - "version": "1", - "endpoint": "https://www.woopra.com/track/identify" + headers: {}, + version: '1', + endpoint: 'https://www.woopra.com/track/identify', }, - "destination": { - "Config": { - "projectName": "int.com" - } + destination: { + Config: { + projectName: 'int.com', + }, }, - "metadata": [ + metadata: [ { - "jobId": 1 - } + jobId: 1, + }, ], - "batched": false, - "statusCode": 200 - } - ] - } - } - } + batched: false, + statusCode: 200, + }, + ], + }, + }, + }, }, { - "name": "woopra", - "description": "Successful Track Call ", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "mobile", - "context": { - "app": { - "build": "4", - "name": "RuddCDN" - }, - "device": { - "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a", - "name": "generic_x86_arm" - }, - "library": { - "name": "com.rudderstack.android.sdk.core", - "version": "1.0.6" - }, - "os": { - "name": "Android", - "version": "9" - }, - "timezone": "Asia/Kolkata", - "userAgent": "Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)" + name: 'woopra', + description: 'Successful Track Call ', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + context: { + app: { + build: '4', + name: 'RuddCDN', + }, + device: { + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + name: 'generic_x86_arm', }, - "event": "First Investment", - "integrations": { - "woopra": "int.com" + library: { + name: 'com.rudderstack.android.sdk.core', + version: '1.0.6', }, - "messageId": "1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb", - "originalTimestamp": "2020-09-28T19:53:31.900Z", - "properties": { - "currency": "EUR", - "revenue": 20.37566 + os: { + name: 'Android', + version: '9', }, - "receivedAt": "2020-09-29T14:50:43.005+05:30", - "sentAt": "2020-09-28T19:53:44.998Z", - "timestamp": "2020-09-29T14:50:29.907+05:30", - "type": "track" + timezone: 'Asia/Kolkata', + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + event: 'First Investment', + integrations: { + woopra: 'int.com', }, - "destination": { - "Config": { - "projectName": "int.com" - } + messageId: '1601322811899-d9c7dd00-50dc-4364-95c8-e89423eb3cfb', + originalTimestamp: '2020-09-28T19:53:31.900Z', + properties: { + currency: 'EUR', + revenue: 20.37566, + }, + receivedAt: '2020-09-29T14:50:43.005+05:30', + sentAt: '2020-09-28T19:53:44.998Z', + timestamp: '2020-09-29T14:50:29.907+05:30', + type: 'track', + }, + destination: { + Config: { + projectName: 'int.com', }, - "metadata": { - "jobId": 2 - } - }] - , "destType": "woopra" + }, + metadata: { + jobId: 2, + }, + }, + ], + destType: 'woopra', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "batchedRequest": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": {}, - "JSON_ARRAY": {} + batchedRequest: { + body: { + XML: {}, + FORM: {}, + JSON: {}, + JSON_ARRAY: {}, }, - "type": "REST", - "userId": "", - "files": {}, - "method": "GET", - "params": { - "os": "Android", - "app": "RuddCDN", - "event": "First Investment", - "Project": "int.com", - "timestamp": "1601371229907", - "ce_revenue": 20.37566, - "ce_currency": "EUR", - "cookie": "21e13f4bc7ceddad" + type: 'REST', + userId: '', + files: {}, + method: 'GET', + params: { + os: 'Android', + app: 'RuddCDN', + event: 'First Investment', + Project: 'int.com', + timestamp: '1601371229907', + ce_revenue: 20.37566, + ce_currency: 'EUR', + cookie: '21e13f4bc7ceddad', }, - "headers": {}, - "version": "1", - "endpoint": "https://www.woopra.com/track/ce" + headers: {}, + version: '1', + endpoint: 'https://www.woopra.com/track/ce', }, - "destination": { - "Config": { - "projectName": "int.com" - } + destination: { + Config: { + projectName: 'int.com', + }, }, - "metadata": [ + metadata: [ { - "jobId": 2 - } + jobId: 2, + }, ], - "batched": false, - "statusCode": 200 + batched: false, + statusCode: 200, }, - ] - } - } - } + ], + }, + }, + }, }, { - "name": "woopra", - "description": "Unsupported Message Type", - "feature": "router", - "module": "destination", - "version": "v0", - "input": { - "request": { - "body": { - "input": - [ - { - "message": { - "anonymousId": "21e13f4bc7ceddad", - "channel": "mobile", - "event": "First Investment", - "integrations": { - "woopra": "int.com" - }, - "type": "group" + name: 'woopra', + description: 'Unsupported Message Type', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + message: { + anonymousId: '21e13f4bc7ceddad', + channel: 'mobile', + event: 'First Investment', + integrations: { + woopra: 'int.com', }, - "destination": { - "Config": { - "projectName": "int.com" - } + type: 'group', + }, + destination: { + Config: { + projectName: 'int.com', }, - "metadata": { - "jobId": 3 - } - }] - , "destType": "woopra" + }, + metadata: { + jobId: 3, + }, + }, + ], + destType: 'woopra', }, - "method": "POST" + method: 'POST', }, - "pathSuffix": "" + pathSuffix: '', }, - "output": { - "response": { - "status": 200, - "body": { - "output": [ + output: { + response: { + status: 200, + body: { + output: [ { - "destination": { - "Config": { - "projectName": "int.com" - } + destination: { + Config: { + projectName: 'int.com', + }, }, - "metadata": [ + metadata: [ { - "jobId": 3 - } + jobId: 3, + }, ], - "statTags": { - "errorCategory": "dataValidation", - "implementation": "native", - "feature": "router", - "destType": "WOOPRA", - "module": "destination", - "errorType": "instrumentation" + statTags: { + errorCategory: 'dataValidation', + implementation: 'native', + feature: 'router', + destType: 'WOOPRA', + module: 'destination', + errorType: 'instrumentation', }, - "batched": false, - "statusCode": 400, - "error": "Message type group is not supported" - } - ] - } - } - } + batched: false, + statusCode: 400, + error: 'Message type group is not supported', + }, + ], + }, + }, + }, }, ]; module.exports = { - data -}; \ No newline at end of file + data, +}; diff --git a/tsconfig.json b/tsconfig.json index 9475c3894b01..3d91523d78db 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,9 @@ /* Language and Environment */ "target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - "lib": ["es2019"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + "lib": [ + "es2019" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ @@ -40,7 +42,7 @@ /* JavaScript Support */ "allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */, - "checkJs": false, /* Enable error reporting in type-checked JavaScript files. */ + "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ /* Emit */ @@ -51,7 +53,7 @@ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ "outDir": "./dist" /* Specify an output folder for all emitted files. */, // "removeComments": true, /* Disable emitting comments. */ - "noEmit": false, /* Disable emitting files from a compilation. */ + "noEmit": false /* Disable emitting files from a compilation. */, // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ @@ -100,6 +102,6 @@ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "exclude": ["./test"], - "include": ["./src","./**/*.json"] + "exclude": ["./src/**/*.test.js", "./src/**/*.test.ts"], + "include": ["./src", "./src/**/*.json"] }