Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: onboard script to generate testdata and test integration #3112

Merged
merged 7 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,5 @@ dist
.idea

# component test report
test_reports/
test_reports/
temp/
2 changes: 1 addition & 1 deletion test/integrations/destinations/salesforce/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,5 +466,5 @@ export const networkCallsData = [
...tfProxyMocksData,
...transformationMocksData,
...businessMockData,
...otherMocksData
...otherMocksData,
];
1 change: 1 addition & 0 deletions test/integrations/testTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface mockType {
}

export interface TestCaseData {
id?: string;
name: string;
description: string;
scenario?: string;
Expand Down
56 changes: 46 additions & 10 deletions test/integrations/testUtils.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
import { z } from 'zod';
import { globSync } from 'glob';
import { join } from 'path';
import { MockHttpCallsData, TestCaseData } from './testTypes';
import MockAdapter from 'axios-mock-adapter';
import isMatch from 'lodash/isMatch';
import { OptionValues } from 'commander';
import { removeUndefinedAndNullValues } from '@rudderstack/integrations-lib';
import {
Destination,
Metadata,
ProxyMetdata,
ProxyV0Request,
ProxyV1Request,
} from '../../src/types';
import tags from '../../src/v0/util/tags';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { Destination, ProxyMetdata, ProxyV0Request, ProxyV1Request } from '../../src/types';
import {
DeliveryV0ResponseSchema,
DeliveryV0ResponseSchemaForOauth,
DeliveryV1ResponseSchema,
DeliveryV1ResponseSchemaForOauth,
ProcessorTransformationResponseListSchema,
ProcessorTransformationResponseSchema,
ProxyV0RequestSchema,
ProxyV1RequestSchema,
RouterTransformationResponseListSchema,
RouterTransformationResponseSchema,
} from '../../src/types/zodTypes';

const generateAlphanumericId = (size = 36) =>
Expand Down Expand Up @@ -104,6 +97,49 @@ export const overrideDestination = (destination: Destination, overrideConfigValu
});
};

export const produceTestData = (testData: TestCaseData[], filterKeys = []) => {
const result: any = [];
testData.forEach((tcData) => {
let events;
try {
switch (tcData.feature) {
case tags.FEATURES.PROCESSOR:
saikumarrs marked this conversation as resolved.
Show resolved Hide resolved
events = tcData.input.request.body;
break;
case tags.FEATURES.BATCH:
events = tcData.input.request.body.input;
break;
case tags.FEATURES.ROUTER:
events = tcData.input.request.body.input;
break;
}
} catch (e) {
throw new Error(
`Error in producing test data for destination:${tcData.name}, id:${tcData.id}: ${e}`,
);
}

events.forEach((event) => {
const { message } = event;
// remove unwanted keys
filterKeys.forEach((key) => {
delete message[key];
});
result.push(message);
});
});

// write the data to a file

// create directory if not exists
const dir = join(__dirname, '../../temp');
if (!existsSync(dir)) {
mkdirSync(dir);
}
writeFileSync(join(__dirname, '../../temp/test_data.json'), JSON.stringify(result, null, 2));
console.log('Data generated successfully at temp/test_data.json');
};

export const generateIndentifyPayload: any = (parametersOverride: any) => {
const payload = {
type: 'identify',
Expand Down
88 changes: 88 additions & 0 deletions test/scripts/testDataGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import path from 'path';
import { TestCaseData } from '../integrations/testTypes';
import { getTestData, getTestDataFilePaths, produceTestData } from '../integrations/testUtils';
import { Command } from 'commander';
import axios from 'axios';
import * as fs from 'fs';

// Produces test data for a given destination
// Example usage
// npx ts-node test/scripts/testDataGenerator.ts --destination=klaviyo --feature=processor

const command = new Command();
command
.allowUnknownOption()
.option('-d, --destination <string>', 'Enter Destination Name')
.option('-f, --feature <string>', 'Enter Feature Name(processor, router)')
.option('-i, --index <number>', 'Enter Test index')
.option('-id, --id <string>', 'Enter unique "Id" of the test case you want to run')
.option('-dp, --dataPlane <string>', 'Enter Data Plane URL')
.option('-wk, --writeKey <string>', 'Enter Write Key')
.option(
'-fk, --filterKeys <string>',
'Enter Keys to filter from the test data(originalTimestamp, timestamp, messageId etc)',
)
.parse();

const opts = command.opts();

if (opts.destination === undefined) {
throw new Error('Destination is not provided');
}

const filterKeys = opts.filterKeys ? opts.filterKeys.split(',') : [];

const rootDir = __dirname;
const resolvedpath = path.resolve(rootDir, '../integrations');
const destinationTestDataPaths = getTestDataFilePaths(resolvedpath, opts);

destinationTestDataPaths.forEach((testDataPath) => {
let testData: TestCaseData[] = getTestData(testDataPath);
if (opts.index !== undefined) {
testData = [testData[parseInt(opts.index)]];
}
if (opts.id) {
testData = testData.filter((data) => {
if (data['id'] === opts.id) {
return true;
}
return false;
});
}
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
console.log('Writing test data to ../../temp/test_data.json');
produceTestData(testData, filterKeys);

if (opts.dataPlane && opts.writeKey) {
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
// read file ../../temp/test_data.json
console.log('Sending data to data plane URL: ', opts.dataPlane);

const resolvedpathForData = path.resolve(rootDir, '../../temp/test_data.json');

fs.readFile(resolvedpathForData, 'utf8', function (err, data) {
if (err) {
console.log(err);
} else {
const parsedData = JSON.parse(data);
axios
saikumarrs marked this conversation as resolved.
Show resolved Hide resolved
.post(
`${opts.dataPlane}/v1/batch`,
{
batch: parsedData,
},
{
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${Buffer.from(opts.writeKey + ':').toString('base64')}`,
},
},
)
.then((response) => {
console.log(response);
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
})
.catch((error) => {
console.log(error);
});
}
});
}
});
Loading