import { expect } from "chai"; import { ContextService } from "../../../../src/services/targeting/ContextService"; import { FakeRequestBuilder } from "../../fakeRequestBuilder"; import { RequestInventorySource } from "../../../../src/models"; import { CampaignCreative } from "../../../../src/steps/ordering/ordering.model"; import { FakeCampaign } from "../../fake/Campaign"; import { ContextHashMap } from "../../../../src/services/scoringSystem/contextHashMap.service"; const sinon = require("sinon"); let contextHashmapService: Partial; describe("contextService", function () { before(() => { contextHashmapService = { getScore: (features) => { if (features.campaignId) { return parseFloat((parseInt(features.campaignId) * 0.02).toPrecision(4)); } return undefined; }, getStatistics: (ecType, format, campaignId) => ({ bucketsMap: [], }), }; }); describe("getScores", function () { let request: any; let campaignCreatives: CampaignCreative[]; beforeEach(() => { const campaigns = [ new FakeCampaign("1", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("2", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("3", undefined, { economicType: "cpv", format: "-1" }), new FakeCampaign("4", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("5", undefined, { economicType: "cpv", format: "-1" }), new FakeCampaign("6", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("7", undefined, { economicType: "cpm", format: "-1" }), new FakeCampaign("8", undefined, { economicType: "cpe", format: "-1" }), ]; request = new FakeRequestBuilder() .withCampaigns(...campaigns) .withAppBundleOrDomain("an.app") .withSSP("ogury") .withAdUnitId("aui1") .build(); campaignCreatives = campaigns.map((c) => ({ campaign: c, creativeId: 0, metadata: Object.assign({}, c.metadata), metadataTmp: Object.assign({}, c.metadataTmp), })); }); const expectedHashMapScores = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16]; it("should use context hashmap", async () => { const contextServiceReal = new ContextService(contextHashmapService as any); const scores = campaignCreatives.map((cc) => contextServiceReal.getContextHashMapScore(request, cc) ); expect(scores).to.deep.equal(expectedHashMapScores); }); it("should set default score for header-bidding display", async () => { const contextServiceReal = new ContextService(contextHashmapService as any); const hbRequest = (request = new FakeRequestBuilder() .withCampaigns( new FakeCampaign("1", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("2", undefined, { economicType: "cpv", format: "-1" }) ) .withAppBundleOrDomain("?") .withSSP("?") .withAdUnitId("?") .withInventorySource(RequestInventorySource.HEADER_BIDDING) .build()); const scores = request.campaigns.map((c: any) => { const campaignCreative: CampaignCreative = { campaign: c, creativeId: 0, metadata: Object.assign({}, c.metadata), metadataTmp: Object.assign({}, c.metadataTmp), }; return contextServiceReal.getContextHashMapScore(hbRequest, campaignCreative); }); expect(scores).to.deep.equal([0.02, 0.04]); }); }); describe("addScores", function () { const campaigns = [ new FakeCampaign("1"), new FakeCampaign("2"), new FakeCampaign("3"), new FakeCampaign("4"), ]; const request = new FakeRequestBuilder() .withCampaigns(...campaigns) .withAppBundleOrDomain("an.app") .withSSP("ogury") .withAdUnitId("aui1") .build(); let contextGetScoresStub: any; const campaignCreatives: CampaignCreative[] = campaigns.map((c) => { return { campaign: c, creativeId: 0, metadata: Object.assign({}, c.metadata), metadataTmp: Object.assign({}, c.metadataTmp), }; }); before(() => { contextGetScoresStub = sinon.stub(ContextService.prototype, "getContextHashMapScore"); contextGetScoresStub.callsFake((req: any, cc: CampaignCreative) => { switch (cc.campaign.id) { case "1": return 0.05; case "2": return 0.8; case "3": return 0; default: return undefined; } }); }); after(() => { contextGetScoresStub.restore(); }); it("should add scores to query", async () => { const contextServiceReal = new ContextService(contextHashmapService as any); await contextServiceReal.addScores(request, campaignCreatives); const expectedScores = { "1": { contextScore: 0.05, accRate: 0.05 }, "2": { contextScore: 0.8, accRate: 0.8 }, "3": { contextScore: 0, accRate: 0 }, "4": { contextScore: null, accRate: null }, }; const actualScores: any = {}; campaignCreatives.map( (cc) => (actualScores[cc.campaign.id] = { contextScore: cc.metadata.context_score, accRate: cc.metadata.acc_rate, }) ); expect(actualScores).to.deep.equal(expectedScores); }); }); describe("build features from request", () => { it("should build good features for web request", async () => { const contextServiceReal = new ContextService(contextHashmapService as any); const campaigns = [ new FakeCampaign("1", undefined, { economicType: "cpc", format: "-1" }), new FakeCampaign("2", undefined, { economicType: "cpc", format: "-1" }), ]; const hbRequest = new FakeRequestBuilder() .withCampaigns(...campaigns) .withAppBundleOrDomain("?") .withPage("http://page.com/page") .withSSP("?") .withAdUnitId("?") .withEnvironmentType("web") .withInventorySource(RequestInventorySource.HEADER_BIDDING) .build(); const campaignCreatives = campaigns.map((c) => ({ campaign: c, creativeId: 0, metadata: Object.assign({}, c.metadata), metadataTmp: Object.assign({}, c.metadataTmp), })); const features = contextServiceReal.buildFeaturesFromRequest(hbRequest, campaignCreatives[0]); const expectedFeatures = { economicType: "cpc", format: "-1", ssp: "?", campaignId: "1", assetId: "page.com", assetUnit: "http://page.com/page", environmentType: "web", priceModel: "first_price", adUnitType: undefined, apiKey: "82349", }; expect(features).to.deep.equal(expectedFeatures); }); }); });