Skip to content

Commit

Permalink
fix: algolia add validation for currency fields (#3329)
Browse files Browse the repository at this point in the history
* fix: algolia add validation for currency fields

* fix: minor edit

* fix: adding unit test cases for validate payload
  • Loading branch information
shrouti1507 authored Apr 30, 2024
1 parent 1701005 commit ce9f5db
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/cdk/v2/destinations/algolia/procWorkflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ steps:
const objectIDs = ~r products.objectId;
$.context.payload.objectIDs = Array.isArray(objectIDs) ? objectIDs[:20]:$.context.payload.objectIDs;
$.context.payload.objectData = $.outputs.prepareObjectDataBlock
$.validatePayload($.context.payload)
- name: validateDestPayload
template: |
Expand Down
19 changes: 19 additions & 0 deletions src/v0/destinations/algolia/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,28 @@ const clickPayloadValidator = (payload) => {
return updatedPayload;
};

// ref : https://www.algolia.com/doc/rest-api/insights/#method-param-objectdata-2:~:text=currency-,%23,currency%20as%20ISO%2D4217%20currency%20code%2C%20such%20as%20USD%20or%20EUR.,-ObjectData
function validatePayload(payload) {
if (payload.objectData && Array.isArray(payload.objectData)) {
const hasRelevantFields = payload.objectData.some(
(obj) =>
obj.hasOwnProperty('price') ||
obj.hasOwnProperty('quantity') ||
obj.hasOwnProperty('discount'),
);

if (hasRelevantFields && !payload.currency) {
throw new InstrumentationError(
'Currency missing when objectData fields has price informations.',
);
}
}
}

module.exports = {
genericpayloadValidator,
createObjectArray,
eventTypeMapping,
clickPayloadValidator,
validatePayload,
};
58 changes: 58 additions & 0 deletions src/v0/destinations/algolia/util.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const { InstrumentationError } = require('@rudderstack/integrations-lib');
const { validatePayload } = require('./util');

describe('validatePayload', () => {
// When payload is valid and contains relevant fields and currency
it('should validate payload when it is valid and contains relevant fields and currency', () => {
const payload = {
objectData: [
{ price: 10, quantity: 2, discount: 0.1 },
{ price: 20, quantity: 1, discount: 0 },
],
currency: 'USD',
};

expect(() => validatePayload(payload)).not.toThrow();
});

// When payload contains objects with missing relevant fields
it('should throw an error when payload contains objects with missing relevant fields', () => {
const payload = {
objectData: [
{ price: 10, quantity: 2 },
{ price: 20, discount: 0 },
],
};

expect(() => validatePayload(payload)).toThrow(InstrumentationError);
});

// When payload is valid and contains relevant fields but no currency
it('should throw an InstrumentationError when currency is missing', () => {
const payload = {
objectData: [
{ price: 10, quantity: 2, discount: 0.1 },
{ price: 20, quantity: 1, discount: 0 },
],
};

expect(() => validatePayload(payload)).toThrow(InstrumentationError);
});

// When payload is valid but does not contain relevant fields
it('should not throw an error when payload does not contain relevant fields', () => {
const payload = {
objectData: [{ position: 'Product A' }, { position: 'Product B' }],
currency: 'USD',
};

expect(() => validatePayload(payload)).not.toThrow();
});

// When payload is empty
it('should not throw an error when payload is empty', () => {
const payload = {};

expect(() => validatePayload(payload)).not.toThrow();
});
});
142 changes: 142 additions & 0 deletions test/integrations/destinations/algolia/processor/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,7 @@ export const data = [
properties: {
index: 'products',
eventSubtype: 'addToCart',
currency: 'USD',
products: [
{
objectId: 'ecommerce-sample-data-919',
Expand Down Expand Up @@ -1751,6 +1752,7 @@ export const data = [
events: [
{
index: 'products',
currency: 'USD',
queryID: '43b15df305339e827f0ac0bdc5ebcaa7',
objectIDs: ['ecommerce-sample-data-919', '9780439784542'],
userToken: 'testuserId1',
Expand All @@ -1760,11 +1762,13 @@ export const data = [
objectData: [
{
quantity: 2,
price: '10',
queryID: '123',
discount: '10',
},
{
quantity: 3,
price: '30',
queryID: '123',
discount: '10',
},
Expand Down Expand Up @@ -1858,6 +1862,7 @@ export const data = [
userId: 'testuserId1',
properties: {
index: 'products',
currency: 'USD',
eventSubtype: 'purchase',
products: [
{
Expand Down Expand Up @@ -1922,6 +1927,7 @@ export const data = [
events: [
{
index: 'products',
currency: 'USD',
queryID: '43b15df305339e827f0ac0bdc5ebcaa7',
objectIDs: ['ecommerce-sample-data-919', '9780439784542'],
userToken: 'testuserId1',
Expand All @@ -1933,11 +1939,13 @@ export const data = [
quantity: 2,
queryID: '123',
discount: '10',
price: '10',
},
{
quantity: 3,
queryID: '123',
discount: '10',
price: '30',
},
],
},
Expand Down Expand Up @@ -2287,4 +2295,138 @@ export const data = [
},
},
},
{
name: 'algolia',
description: 'When price information is present in objectData, currency is mandatory',
feature: 'processor',
module: 'destination',
version: 'v0',
input: {
request: {
body: [
{
message: {
channel: 'web',
context: {
app: {
build: '1.0.0',
name: 'RudderLabs JavaScript SDK',
namespace: 'com.rudderlabs.javascript',
version: '1.0.0',
},
traits: {
email: '[email protected]',
firstName: 'test',
lastName: 'one',
},
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,
},
page: {
path: '/destinations/ometria',
referrer: '',
search: '',
title: '',
url: 'https://docs.rudderstack.com/destinations/ometria',
category: 'destination',
initial_referrer: 'https://docs.rudderstack.com',
initial_referring_domain: 'docs.rudderstack.com',
},
},
type: 'track',
messageId: '84e26acc-56a5-4835-8233-591137fca468',
session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22',
originalTimestamp: '2019-10-14T09:03:17.562Z',
anonymousId: '123456',
event: 'product list viewed',
userId: 'testuserId1',
properties: {
index: 'products',
products: [
{
objectId: 'ecommerce-sample-data-919',
position: 7,
quantity: '2',
price: 10,
},
{
objectId: '9780439784542',
position: 8,
quantity: '3',
price: 30,
},
],
queryId: '43b15df305339e827f0ac0bdc5ebcaa7',
},
integrations: {
All: true,
},
sentAt: '2019-10-14T09:03:22.563Z',
},
metadata: {
destinationId: 'destId',
workspaceId: 'wspId',
},
destination: {
DestinationDefinition: {
Config: {
cdkV2Enabled: true,
excludeKeys: [],
includeKeys: [],
},
},
Config: {
apiKey: 'dummyApiKey',
applicationId: 'O2YARRI15I',
eventTypeSettings: [
{
from: 'product list viewed',
to: 'conversion',
},
],
},
},
},
],
},
},
output: {
response: {
status: 200,
body: [
{
error:
'Currency missing when objectData fields has price informations.: Workflow: procWorkflow, Step: populateProductsData, ChildStep: populateForClickEvent, OriginalError: Currency missing when objectData fields has price informations.',
statTags: {
destType: 'ALGOLIA',
errorCategory: 'dataValidation',
errorType: 'instrumentation',
feature: 'processor',
implementation: 'cdkV2',
module: 'destination',
destinationId: 'destId',
workspaceId: 'wspId',
},
statusCode: 400,
metadata: {
destinationId: 'destId',
workspaceId: 'wspId',
},
},
],
},
},
},
];

0 comments on commit ce9f5db

Please sign in to comment.