import { StepBuilder } from "../../../src/steps/stepBuilder"; import { FakeRequestBuilder } from "../fakeRequestBuilder"; import CategoryService from "../../../src/services/category.service"; import { CategoryRating, CategoryProviderType } from "../../../src/categories/categoryProvider"; import { reset, verify, mock, when, instance, objectContaining } from "ts-mockito"; import FeatureConfigFake from "../fake/FeatureConfigFake"; import { FeatureConfigService } from "../../../src/services/FeatureConfig.service"; import { expect } from "chai"; import { StepResult } from "../../../src/steps/stepResult"; import { FakeCampaign } from "../fake/Campaign"; import { MockCategoryValue } from "../../../src/categories/mockCategoryProvider"; import { CampaignModelFake } from "../fake/CampaignModelFake"; import { CampaignModel } from "../../../src/models/CampaignModel"; import DeviceFraudStep from "../../../src/steps/prebid/deviceFraud.step"; import { ChoiceRequest } from "../../../src/models"; const featureConfigService = FeatureConfigService.getInstance(); const mockedFeatureConf: FeatureConfigFake = new FeatureConfigFake(); const campaignModel: CampaignModel = new CampaignModelFake(); const innerDeviceFraudStep = new DeviceFraudStep(campaignModel, CategoryProviderType.DV); const deviceFraudStep = new StepBuilder(innerDeviceFraudStep).build(); let categoryService: CategoryService; describe("DeviceFraudStep", function () { before(async () => { categoryService = mock(CategoryService); innerDeviceFraudStep.categoryService = instance(categoryService); (innerDeviceFraudStep as any).featureConfigService = featureConfigService; featureConfigService.setFeatureConfig(mockedFeatureConf); }); after(async () => {}); beforeEach(async () => { mockedFeatureConf.clearParams(); reset(categoryService); when( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.1")), CategoryProviderType.DV ) ).thenResolve(new MockCategoryValue("2.2.2.1")); when( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).thenResolve(new MockCategoryValue("2.2.2.2")); when( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.3")), CategoryProviderType.DV ) ).thenResolve(new MockCategoryValue("2.2.2.3")); }); describe("Device fraud", function () { it("should flag this ip as unsafe", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.2") .withPage("http://www.ogury.com") .withPrebid({ type: "device-fraud", provider: "dv" }) .withEnvironmentType("web") .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, false, CategoryRating.Unsafe); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Unsafe); const excluded = request?.excluded || []; expect(excluded[0].stepsPassedStatus["pass_device_fraud_dv"]).to.be.equal("false"); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).once(); }); it("should flag this ip as unsafe with multiple campaigns", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.2") .withPage("http://www.ogury.com") .withEnvironmentType("web") .withCampaigns( new FakeCampaign("10001"), new FakeCampaign("10002"), new FakeCampaign("10003") ) .withCampaignPrebid("10002", { type: "device-fraud", provider: "ias" }) .withPrebid({ type: "device-fraud", provider: "dv" }) .withCampaignPrebid("10003", { type: "device-fraud", provider: "ias" }) .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, false, CategoryRating.Unsafe); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Unsafe); const excluded = request?.excluded || []; expect(excluded[0].stepsPassedStatus["pass_device_fraud_dv"]).to.be.equal("false"); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).once(); }); it("should flag this domain as unsafe with multiple campaigns on other provider", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.2") .withPage("http://www.ogury.com") .withEnvironmentType("web") .withCampaigns( new FakeCampaign("10001"), new FakeCampaign("10002"), new FakeCampaign("10003") ) .withPrebid({ type: "device-fraud", provider: "ias" }) .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, true, undefined); expect(request.campaigns[0].stepsPassedStatus["pass_device_fraud_dv"]).to.be.equal( "bypassed" ); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).never(); }); it("should flag this domain as unsafe with multiple campaigns on other provider with force cach", async function () { mockedFeatureConf.setParam("ms-choices.device-fraud.fill-cache.dv", "1"); const request = new FakeRequestBuilder() .withIP("2.2.2.2") .withPage("http://www.ogury.com") .withEnvironmentType("web") .withCampaigns( new FakeCampaign("10001"), new FakeCampaign("10002"), new FakeCampaign("10003") ) .withPrebid({ type: "device-fraud", provider: "ias" }) .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, true, undefined); expect(request.campaigns[0].stepsPassedStatus["pass_device_fraud_dv"]).to.be.equal( "bypassed" ); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).once(); }); it("should flag this domain as unsafe with multiple campaigns and various provider", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.2") .withPage("http://www.ogury.com") .withEnvironmentType("web") .withCampaigns( new FakeCampaign("10001"), new FakeCampaign("10002"), new FakeCampaign("10003") ) .withCampaignPrebid("10001", { type: "device-fraud", provider: "dv" }) .withCampaignPrebid("10002", { type: "device-fraud", provider: "ias" }) .withCampaignPrebid("10003", { type: "device-fraud", provider: "dv" }) .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafeWithoutCampaignLength(stepRes, true, false, CategoryRating.Unsafe); stepRes.passedCampaigns.length.should.be.equal(1); stepRes.passedCampaigns[0].id.should.be.equal("10002"); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Unsafe); const excluded = request?.excluded || []; expect(excluded[0].stepsPassedStatus["pass_device_fraud_dv"]).to.be.equal("false"); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).once(); }); it("should flag this ip as safe", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.1") .withPage("http://www.ogury.com/") .withPrebid({ type: "device-fraud", provider: "dv" }) .withEnvironmentType("web") .build(); const stepRes = await deviceFraudStep.execute(request); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Safe); shouldBeSafe(stepRes, true, true, CategoryRating.Safe); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.1")), CategoryProviderType.DV ) ).once(); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("http://www.ogury.com/unsafe")), CategoryProviderType.DV ) ).never(); }); it("should flag this unknown ip as safe", async function () { const request = new FakeRequestBuilder() .withIP("2.2.2.3") .withPage("http://www.ogury.com") .withPrebid({ type: "device-fraud", provider: "dv" }) .withEnvironmentType("web") .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, true, CategoryRating.Unknown); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Unknown); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.3")), CategoryProviderType.DV ) ).once(); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).never(); }); it("should flag this unknown ip as unsafe with feature config", async function () { mockedFeatureConf.setParam("ms-choices.device-fraud.allow-unknown.dv", "false"); const request = new FakeRequestBuilder() .withIP("2.2.2.3") .withPage("http://www.ogury.com") .withPrebid({ type: "device-fraud", provider: "dv" }) .withEnvironmentType("web") .build(); const stepRes = await deviceFraudStep.execute(request); shouldBeSafe(stepRes, true, false, CategoryRating.Unknown); checkPrebidResult(request, CategoryProviderType.DV, CategoryRating.Unknown); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.3")), CategoryProviderType.DV ) ).once(); verify( categoryService.getDeviceCategoryValue( objectContaining(expectedRequest("2.2.2.2")), CategoryProviderType.DV ) ).never(); }); }); }); function shouldBeSafe( stepRes: StepResult, webmobile: boolean, passed: boolean, result: CategoryRating | undefined ) { const passedCampaignLength = stepRes.passedCampaigns.length; if (passed) { passedCampaignLength.should.be.above(0); } else { passedCampaignLength.should.be.equal(0); } shouldBeSafeWithoutCampaignLength(stepRes, webmobile, passed, result); } function shouldBeSafeWithoutCampaignLength( stepRes: StepResult, webmobile: boolean, passed: boolean, result: CategoryRating | undefined ) { expect(stepRes.getMetricLabel("is_web_mobile")).to.be.equal(String(webmobile)); expect(stepRes.getMetricLabel("passed_device_fraud")).to.be.equal(String(passed)); expect(stepRes.getMetricLabel("device_fraud")).to.be.equal(result); } function expectedRequest(ip: string): Object { return { device: { ip: ip, }, }; } function checkPrebidResult(request: ChoiceRequest, provider: CategoryProviderType, value: string) { expect(request.metadata.prebid_result).to.be.not.null; const result = request.metadata.prebid_result?.filter( (value) => value.step === "device_fraud" && value.provider === provider ); expect(result?.length).to.be.equal(1); expect(result![0].result).to.be.equal(value); }