import sinon from "sinon"; import request, { Test } from "supertest"; import AWSMock from "aws-sdk-mock"; import { mockDynamoCampaigns } from "../../mocks/dynamo.mock"; import createS3Stub from "../../mocks/s3.mock"; import CallToActionHashMap from "../../../src/services/scoringSystem/callToActionHashMap.service"; import { mockMsAuction, restoreMsAuction } from "../../mocks/ms-auction.mock"; import AudienceHashMap from "../../../src/services/scoringSystem/audienceHashMap.service"; import { ContextHashMap } from "../../../src/services/scoringSystem/contextHashMap.service"; import { mockSpeedThreshold } from "../../mocks/speed-threshold.mock"; import { RedisService } from "../../../src/services/redis.service"; import { initKafkaSpy } from "../../mocks/kafka.mock"; import { readMockCampaigns } from "../../mocks/data.mock"; import { closeServer, start } from "../../../src/main"; import { bid } from "../../../src/beeswax-protos/beeswax"; import { ChoiceRequest } from "../../../src/models"; import { RequestContract } from "../../../src/data-contract/request.contract"; import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; import { assert } from "chai"; export class IntegrationTestContext { private app?: Express.Application; private uri: string; private campaignDataFolder: string; private s3RootDir: string; private thresholdScores: { [k: string]: number }; private dvFraudRedisValues: string[]; private auctionWinner: string; private marketplaceWinner: string; private kafkaSpy: any; private s3Stub: any; constructor( uri: string, campaignDataFolder: string, s3RootDir: string, thresholdScores: { [p: string]: number }, dvFraudRedisValues: string[], auctionWinner: string, marketplaceWinner: string ) { this.uri = uri; this.campaignDataFolder = campaignDataFolder; this.s3RootDir = s3RootDir; this.thresholdScores = thresholdScores; this.dvFraudRedisValues = dvFraudRedisValues; this.auctionWinner = auctionWinner; this.marketplaceWinner = marketplaceWinner; } public async init() { // mock dynamo (needs to be done before initializing the app) const mockCampaigns = await readMockCampaigns(this.campaignDataFolder); await mockDynamoCampaigns(mockCampaigns); // mock s3 this.s3Stub = createS3Stub(this.s3RootDir); // getting app this.app = await start(); // create kafka spy this.kafkaSpy = initKafkaSpy(); // wait for scoring services to be ready await ContextHashMap.getInstance().refreshMaps(); await AudienceHashMap.getInstance().refresh(); await CallToActionHashMap.getInstance().refreshMaps(); // mock speedThreshold mockSpeedThreshold(this.thresholdScores); const redisClient = RedisService.getClient("mockedClient", false); await redisClient.client.flushall(); await Promise.all([ ...this.dvFraudRedisValues.map(async (value) => { const buf = Buffer.from(value, "hex"); await redisClient.client.hmset(buf.slice(0, 3), buf.slice(3, 8), 1); }), // brand safety redisClient.client.set( "cat:dv:a0a250ff440fd5064b09105214d26a1e2a070f6caf2b0a0ba30a5ccc774fee91", "845107fa|4c55811|4c6deb1" ), redisClient.client.set( "cat:ias:a0a250ff440fd5064b09105214d26a1e2a070f6caf2b0a0ba30a5ccc774fee91", "wa|845107fa|501|535|503|537|507|541|505|539|509|543|502|536|504|538|508|542|506|540|510|544|512|546|532|534|511|545|531|533|513|551|401|402|400|410|404" ), redisClient.client.set( "cat:ias:1a291e09c0f9b33e4f157837edebf7758439f632c753d3294d3cb7fd6310ffd5:android", "ia|845107fa|4000|4001|4002|4003|4004|4005|4006|4007|4008|4009|4010|4011|4012|4013|4018|4019|8000|8001|8002|8003|8004|8005|8006|8007|8008|8009|8010|8011|8012|8013|8018|8019|4014|8014|4016|8016|4017|8017|4015|8015" ), redisClient.client.set( "cat:ias:f9317e8b341a5094b2fb7d5a7712f7e1010acb420d0c8357f330fbb789086eaf:android", "ia|845107fa|4000|4001|4002|4003|4004|4005|4006|4007|4008|4009|4010|4011|4012|4013|4018|4019|8000|8001|8002|8003|8004|8005|8006|8007|8008|8009|8010|8011|8012|8013|8018|8019|4014|8014|4016|8016|4017|8017|4015|8015" ), redisClient.client.set( "cat:ias:1a291e09c0f9b33e4f157837edebf7758439f632c753d3294d3cb7fd6310ffd5:ios", "ii|845107fa|4000|4001|4002|4003|4004|4005|4006|4007|4008|4009|4010|4011|4012|4013|4018|4019|8000|8001|8002|8003|8004|8005|8006|8007|8008|8009|8010|8011|8012|8013|8018|8019|4014|8014|4016|8016|4017|8017|4015|8015" ), ]); // mock ms-auction mockMsAuction(this.auctionWinner, this.marketplaceWinner); } public mockHttp(body: ChoiceRequest | RequestContract): Test { return request(this.app) .post(this.uri) .send(JSON.stringify(body)) .set("Accept", "application/json"); } public async sendHttpProtobuf( body: bid.IBidAgentRequest, expectedStatus: number = 200 ): Promise { try { const err = bid.BidAgentRequest.verify(body); if (err) { assert.fail(`Failed to verify protobuf: ${err}`); } const encoded: Uint8Array = bid.BidAgentRequest.encode(body).finish(); const reqConfig: AxiosRequestConfig = { method: "POST", url: `http://127.0.0.1:8080${this.uri}`, data: encoded, headers: { "Content-Type": "application/protobuf" }, responseType: "arraybuffer", validateStatus: () => true, }; const res: AxiosResponse = await axios(reqConfig); if (res.status !== expectedStatus) { assert.fail(`Request returned unexpected status code: ${res.status} - ${res.statusText}`); } return res.status === 200 ? bid.BidAgentResponse.decode(Buffer.from(res.data)) : {}; } catch (e: any) { assert.fail(`Failed to send protobuf request: ${e.message} ${e.stack}`); } } public afterEachRestore() { this.kafkaSpy.reset(); } public afterRestore() { sinon.restore(); restoreMsAuction(); AWSMock.restore(); closeServer(); } public getKafkaSpy() { return this.kafkaSpy; } }