@mediarithmics/plugins-nodejs-sdk
Version:
This is the mediarithmics nodejs to help plugin developers bootstrapping their plugin without having to deal with most of the plugin boilerplate
322 lines (285 loc) • 10.1 kB
text/typescript
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unused-vars */
import 'mocha';
import { expect } from 'chai';
import sinon from 'sinon';
import request from 'supertest';
import { core } from '../';
import {
AudienceFeedBatchContext,
UserPointIdentifierInfo,
UserSegmentUpdatePluginBatchDeliveryResponseData,
UserSegmentUpdatePluginFileDeliveryResponseData,
} from '../mediarithmics';
import {
BatchUpdatePluginResponse,
BatchUpdateRequest,
} from '../mediarithmics/api/core/batchupdate/BatchUpdateInterface';
const PLUGIN_AUTHENTICATION_TOKEN = 'Manny';
const PLUGIN_WORKER_ID = 'Calavera';
// set by the plugin runner in production
process.env.PLUGIN_AUTHENTICATION_TOKEN = PLUGIN_AUTHENTICATION_TOKEN;
process.env.PLUGIN_WORKER_ID = PLUGIN_WORKER_ID;
interface BatchLine {
uuid: string;
user_list: number;
}
class MyFakeBatchedAudienceFeedConnector extends core.BatchedAudienceFeedConnectorBasePlugin<BatchLine> {
protected onBatchUpdate(
request: BatchUpdateRequest<core.AudienceFeedBatchContext, BatchLine>,
instanceContext: core.AudienceFeedConnectorBaseInstanceContext,
): Promise<BatchUpdatePluginResponse> {
const response: BatchUpdatePluginResponse = {
status: 'OK',
message: JSON.stringify(request.batch_content),
sent_items_in_success: request.batch_content.length,
sent_items_in_error: 0,
};
return Promise.resolve(response);
}
protected onExternalSegmentCreation(
request: core.ExternalSegmentCreationRequest,
instanceContext: core.AudienceFeedConnectorBaseInstanceContext,
): Promise<core.ExternalSegmentCreationPluginResponse> {
const response: core.ExternalSegmentCreationPluginResponse = {
status: 'ok',
};
return Promise.resolve(response);
}
protected onExternalSegmentConnection(
request: core.ExternalSegmentConnectionRequest,
instanceContext: core.AudienceFeedConnectorBaseInstanceContext,
): Promise<core.ExternalSegmentConnectionPluginResponse> {
const response: core.ExternalSegmentConnectionPluginResponse = {
status: 'ok',
};
return Promise.resolve(response);
}
protected onUserSegmentUpdate(
request: core.UserSegmentUpdateRequest,
instanceContext: core.AudienceFeedConnectorBaseInstanceContext,
): Promise<core.BatchedUserSegmentUpdatePluginResponse<BatchLine>> {
const data: UserSegmentUpdatePluginBatchDeliveryResponseData<BatchLine>[] = request.user_identifiers.flatMap(
(id) => {
switch (id.type) {
case 'USER_POINT':
return [
{
type: 'BATCH_DELIVERY',
content: { uuid: (id as UserPointIdentifierInfo).user_point_id, user_list: 123 },
grouping_key: request.operation,
},
];
default:
return [];
}
},
);
const response: core.BatchedUserSegmentUpdatePluginResponse<BatchLine> = {
status: 'ok',
data,
};
return Promise.resolve(response);
}
}
const rpMockup: sinon.SinonStub = sinon.stub().returns(
new Promise((resolve, reject) => {
resolve('Yolo');
}),
);
describe('Fetch Audience Feed Gateway API', () => {
// All the magic is here
const plugin = new MyFakeBatchedAudienceFeedConnector(false);
const runner = new core.TestingPluginRunner(plugin, rpMockup);
it('Check that feed_id is passed correctly in fetchAudienceFeedProperties', function (done) {
const fakeId = '42000000';
// We try a call to the Gateway
void (runner.plugin as MyFakeBatchedAudienceFeedConnector).fetchAudienceFeedProperties(fakeId).then(() => {
expect(rpMockup.args[0][0].uri).to.be.eq(
`${runner.plugin.outboundPlatformUrl}/v1/audience_segment_external_feeds/${fakeId}/properties`,
);
done();
});
});
it('Check that feed_id is passed correctly in fetchAudienceSegment', function (done) {
const fakeId = '42000000';
// We try a call to the Gateway
void (runner.plugin as MyFakeBatchedAudienceFeedConnector).fetchAudienceSegment(fakeId).then(() => {
expect(rpMockup.args[1][0].uri).to.be.eq(
`${runner.plugin.outboundPlatformUrl}/v1/audience_segment_external_feeds/${fakeId}/audience_segment`,
);
done();
});
});
});
describe('External Audience Feed API test', function () {
// All the magic is here
const plugin = new MyFakeBatchedAudienceFeedConnector(false);
let runner: core.TestingPluginRunner;
it('Check that the plugin is giving good results with a simple handler', function (done) {
const rpMockup: sinon.SinonStub = sinon.stub();
const audienceFeed: core.DataResponse<core.AudienceSegmentExternalFeedResource> = {
status: 'ok',
data: {
id: '74',
plugin_id: '984',
organisation_id: '95',
group_id: 'com.mediarithmics.audience-feed',
artifact_id: 'awesome-audience-feed',
version_id: '1254',
},
};
rpMockup
.withArgs(
sinon.match.has(
'uri',
sinon.match(function (value: string) {
return value.match(/\/v1\/audience_segment_external_feeds\/(.){1,10}/) !== null;
}),
),
)
.returns(audienceFeed);
const properties: core.DataListResponse<core.PluginProperty> = {
status: 'ok',
count: 1,
data: [
{
technical_name: 'hello_world',
value: {
value: 'Yay',
},
property_type: 'STRING',
origin: 'PLUGIN',
writable: true,
deletable: false,
},
],
};
rpMockup
.withArgs(
sinon.match.has(
'uri',
sinon.match(function (value: string) {
return value.match(/\/v1\/audience_segment_external_feeds\/(.){1,10}\/properties/) !== null;
}),
),
)
.returns(properties);
runner = new core.TestingPluginRunner(plugin, rpMockup);
const externalSegmentCreation: core.ExternalSegmentCreationRequest = {
feed_id: '42',
datamart_id: '1023',
segment_id: '451256',
};
const externalSegmentConnection: core.ExternalSegmentConnectionRequest = {
feed_id: '42',
datamart_id: '1023',
segment_id: '451256',
};
const upid = '26340584-f777-404c-82c5-56220667464b';
const userSegmentUpdateRequest: core.UserSegmentUpdateRequest = {
feed_id: '42',
session_id: '43',
datamart_id: '1023',
segment_id: '451256',
ts: 1254412,
operation: 'UPSERT',
user_identifiers: [
{
type: 'USER_POINT',
user_point_id: upid,
} as core.UserPointIdentifierInfo,
{
type: 'USER_ACCOUNT',
user_account_id: '914eb2aa50cef7f3a8705b6bb54e50bb',
creation_ts: 1493118667529,
} as core.UserAccountIdentifierInfo,
{
type: 'USER_EMAIL',
hash: 'e2749f6f4d8104ec385a75490b587c86',
email: undefined,
operator: undefined,
creation_ts: 1493118667529,
last_activity_ts: 1493127642622,
providers: [],
} as core.UserEmailIdentifierInfo,
{
type: 'USER_AGENT',
vector_id: 'vec:886742516',
device: {
form_factor: 'PERSONAL_COMPUTER',
os_family: 'MAC_OS',
browser_family: 'CHROME',
brand: undefined,
model: undefined,
os_version: undefined,
carrier: undefined,
},
creation_ts: 1493118667529,
last_activity_ts: 1493126966889,
providers: [],
mappings: [],
} as core.UserAgentIdentifierInfo,
],
user_profiles: [],
};
const batchUpdateRequest: BatchUpdateRequest<AudienceFeedBatchContext, string> = {
batch_content: [
'{"uuid":"1234","user_list":123}',
'{"uuid":"1235","user_list":123}',
'{"uuid":"1236","user_list":123}',
],
ts: new Date().getTime(),
context: {
endpoint: '/v1/user-segment-update',
feed_id: '42',
feed_session_id: '43',
segment_id: '451256',
datamart_id: '1023',
grouping_key: '',
},
};
void request(runner.plugin.app)
.post('/v1/external_segment_creation')
.send(externalSegmentCreation)
.end(function (err, res) {
expect(res.status).to.equal(200);
expect(JSON.parse(res.text).status).to.be.eq('ok');
void request(runner.plugin.app)
.post('/v1/external_segment_connection')
.send(externalSegmentConnection)
.end(function (err, res) {
expect(res.status).to.equal(200);
expect(JSON.parse(res.text).status).to.be.eq('ok');
void request(runner.plugin.app)
.post('/v1/user_segment_update')
.send(userSegmentUpdateRequest)
.end(function (err, res) {
expect(res.status).to.equal(200);
expect(JSON.parse(res.text).data).to.deep.equal([
{
type: 'BATCH_DELIVERY',
content: { uuid: upid, user_list: 123 },
grouping_key: userSegmentUpdateRequest.operation,
},
]);
expect(JSON.parse(res.text).status).to.be.eq('ok');
});
void request(runner.plugin.app)
.post('/v1/batch_update')
.send(batchUpdateRequest)
.end(function (err, res) {
expect(res.status).to.equal(200);
let result = JSON.parse(res.text) as BatchUpdatePluginResponse;
expect(result.status).to.be.eq('OK');
expect(result.message).to.be.eq(JSON.stringify(batchUpdateRequest.batch_content));
done();
});
});
});
});
afterEach(() => {
// We clear the cache so that we don't have any processing still running in the background
runner.plugin.pluginCache.clear();
});
});