import { assert, expect } from "chai"; import nock from "nock"; import { BrandSafetySeverity, CategoryRating, CategoryProviderValue, FraudSeverity, CategoryProviderType, } from "../../../src/categories/categoryProvider"; import { config } from "../../../src/utils/config"; import IASCategoryProvider from "../../../src/categories/IASCategoryProvider"; import { DeviceOS, EnvironmentType, RequestSource } from "../../../src/utils/RequestUtils"; describe("IASCategoryProvider", function () { const defaultExpireTTL: number = 5 * 24 * 3600 * 1000; const defaultNoDataExpireTTL: number = 1 * 24 * 3600 * 1000; describe("generatePath", function () { const testDataPath = [ { url: "google.com", requestSource: { environmentType: "web", deviceOS: "android" }, result: "/db2/client/1234/segt?adsafe_url=google.com", }, { url: "google.com", requestSource: { environmentType: "in-app", deviceOS: "android" }, result: "/db2/client/1234/segt?bundle_id=google.com&app_store=android", }, { url: "google.com", requestSource: { environmentType: "in-app", deviceOS: "ios" }, result: "/db2/client/1234/segt?bundle_id=google.com&app_store=apple", }, { url: "xyz.com", requestSource: { environmentType: "web", deviceOS: "android" }, result: "/db2/client/1234/segt?adsafe_url=xyz.com", }, { url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "web", deviceOS: "android" }, result: "/db2/client/1234/segt?adsafe_url=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23", }, ]; beforeEach(() => { config["IAS_CAT_CLIENTID"] = "1234"; config["IAS_CAT_LOGIN"] ?? "mylogin"; }); testDataPath.forEach((data) => { it(`generatePath ${data.url} ${data.requestSource.environmentType} ${data.requestSource.deviceOS}`, function () { const provider: any = new IASCategoryProvider(); const auth: string = provider.generateURL({ urlOrBundle: data.url, provider: CategoryProviderType.IAS, requestSource: data.requestSource, }); expect(auth).to.be.equal(data.result); }); }); }); describe("sendRequest Publisher", function () { beforeEach(() => { config["IAS_CAT_CLIENTID"] = "1234"; config["IAS_CAT_LOGIN"] = "mylogin"; }); afterEach(() => { if (!nock.isDone()) { const missingMocks = nock.pendingMocks().join("\n"); nock.cleanAll(); nock.restore(); assert.fail("mocks not called \n" + missingMocks); } }); const testDataRequest = [ { name: "unsafe data", url: "google.com", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_url=google.com", response: '{"segment_ids":["80023001","80312001","513","551"]}', segments: ["80023001", "80312001", "513", "551"], high: CategoryRating.Unsafe, medium: CategoryRating.Unsafe, low: CategoryRating.Unsafe, }, { name: "unknown data", url: "google.com", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_url=google.com", response: { segment_ids: ["512", "546", "513"] }, segments: ["512", "546", "513"], high: CategoryRating.Unknown, medium: CategoryRating.Unknown, low: CategoryRating.Unknown, }, { name: "no data should be unknown", url: "google.com", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_url=google.com", response: '{"segment_ids":[]}', segments: [], high: CategoryRating.Unknown, medium: CategoryRating.Unknown, low: CategoryRating.Unknown, }, { name: "positive category only should be safe with urlencoding", url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_url=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23", response: '{"segment_ids":["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"]}', segments: [ "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", ], high: CategoryRating.Safe, medium: CategoryRating.Safe, low: CategoryRating.Safe, }, { name: "medium risk only should be safe with urlencoding (removed 534)", url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_url=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23", response: '{"segment_ids":["501","535","503","537","507","541","505","539","509","543","502","536","504","538","508","542","506","540","510","544","512","546","532","511","545","531","533","513","551"]}', segments: [ "501", "535", "503", "537", "507", "541", "505", "539", "509", "543", "502", "536", "504", "538", "508", "542", "506", "540", "510", "544", "512", "546", "532", "511", "545", "531", "533", "513", "551", ], high: CategoryRating.Safe, medium: CategoryRating.Unsafe, low: CategoryRating.Unsafe, }, { name: "web categories only should be unknow with android with urlencoding", url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "in-app", deviceOS: "android" }, request: "/db2/client/1234/segt?bundle_id=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23&app_store=android", response: '{"segment_ids":["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"]}', segments: [ "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", ], high: CategoryRating.Unknown, medium: CategoryRating.Unknown, low: CategoryRating.Unknown, }, { name: "app categories only should be safe with android with urlencoding", url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "in-app", deviceOS: "ios" }, request: "/db2/client/1234/segt?bundle_id=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23&app_store=apple", response: '{"segment_ids":["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"]}', segments: [ "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", ], high: CategoryRating.Safe, medium: CategoryRating.Safe, low: CategoryRating.Safe, }, { name: "app categories with moderate only should be safe with android with urlencoding", url: "xyz.com/toto?sdfh=gfghh+2%2F23", requestSource: { environmentType: "in-app", deviceOS: "android" }, request: "/db2/client/1234/segt?bundle_id=xyz.com%2Ftoto%3Fsdfh%3Dgfghh%2B2%252F23&app_store=android", response: '{"segment_ids":["4000","4001","4002","4003","4004","4005","4006","4007","4008","4009","4010","4012","4013","4018","4019","8000","8001","8002","8003","8004","8005","8006","8007","8008","8009","8010","8011","8012","8013","8018","8019","4014","8014"]}', segments: [ "4000", "4001", "4002", "4003", "4004", "4005", "4006", "4007", "4008", "4009", "4010", "4012", "4013", "4018", "4019", "8000", "8001", "8002", "8003", "8004", "8005", "8006", "8007", "8008", "8009", "8010", "8011", "8012", "8013", "8018", "8019", "4014", "8014", ], high: CategoryRating.Safe, medium: CategoryRating.Unsafe, low: CategoryRating.Unsafe, }, ]; testDataRequest.forEach((data) => { it(`simulate end to end request: ${data.name}`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const scope = nock( data.requestSource.environmentType === "web" ? "https://api.adsafeprotected.com" : "https://appapi.adsafeprotected.com" ) .matchHeader("authorization", "bearer mytoken") .get(data.request) .reply(200, data.response, { "Cache-Control": "max-age=889", }); const provider: IASCategoryProvider = new IASCategoryProvider(); const values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: data.url, provider: CategoryProviderType.IAS, requestSource: data.requestSource as RequestSource, }); expect(values.ttl).to.be.equal(defaultExpireTTL); const decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(data.high); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(data.medium); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(data.low); compareTTL(decoded.getRefreshTTL(), 889000); const segments = decoded.toSegmentList(); expect(segments).to.deep.equal(data.segments); for (const segment of data.segments) { expect(decoded.isBlockedBySegment(segment)).to.be.false; } expect(decoded.isBlockedBySegment("80122999")).to.be.true; }); }); it(`when ias respond with error, we should store unknown`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const scope = nock("https://api.adsafeprotected.com") .get("/db2/client/1234/segt?adsafe_url=google.com") .reply(200, '{"segment_ids":[]}', { "Cache-Control": "no-cache", }); const provider: IASCategoryProvider = new IASCategoryProvider(); const values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: "google.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultNoDataExpireTTL); const decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Unknown); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Unknown); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Unknown); compareTTL(decoded.getRefreshTTL(), 15 * 60 * 1000); }); it(`when ias respond with empty and nocache, we should store unknown`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const scope = nock("https://api.adsafeprotected.com") .get("/db2/client/1234/segt?adsafe_url=google.com") .reply(400, "{}"); const provider: IASCategoryProvider = new IASCategoryProvider(); const values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: "google.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultNoDataExpireTTL); const decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Unknown); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Unknown); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Unknown); compareTTL(decoded.getRefreshTTL(), 15 * 60 * 1000); }); it(`test parallel requests`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}') .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const con = nock("https://api.adsafeprotected.com") .get("/db2/client/1234/segt?adsafe_url=google.com") .delay(20) .reply( 200, '{"segment_ids":["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"]}', { "Cache-Control": "max-age=889", } ) .get("/db2/client/1234/segt?adsafe_url=xyz.com") .reply( 200, '{"segment_ids":["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"]}', { "Cache-Control": "max-age=889", } ); const provider: IASCategoryProvider = new IASCategoryProvider(); const promise: Promise = provider.getCategories({ device: false, urlOrBundle: "google.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); let values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: "xyz.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultExpireTTL); let decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); compareTTL(decoded.getRefreshTTL(), 889 * 1000); values = await promise; expect(values.ttl).to.be.equal(defaultExpireTTL); decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); compareTTL(decoded.getRefreshTTL(), 889 * 1000); }); it(`test token cache requests`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 1000}'); const con = nock("https://api.adsafeprotected.com") .matchHeader("authorization", "bearer mytoken") .get("/db2/client/1234/segt?adsafe_url=xyz.com") .reply( 200, '{"segment_ids":["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"]}', { "Cache-Control": "max-age=889", } ); const provider: IASCategoryProvider = new IASCategoryProvider(); let values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: "xyz.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultExpireTTL); let decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); compareTTL(decoded.getRefreshTTL(), 889 * 1000); nock("https://api.adsafeprotected.com") .get("/db2/client/1234/segt?adsafe_url=google.com") .delay(20) .reply( 200, '{"segment_ids":["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"]}', { "Cache-Control": "max-age=889", } ); values = await provider.getCategories({ device: false, urlOrBundle: "google.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultExpireTTL); decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); compareTTL(decoded.getRefreshTTL(), 889 * 1000); }); it(`test changing the config`, async function () { config["IAS_CAT_WEB_URL"] = "https://www.ogury.co"; config["IAS_CAT_CLIENTID"] = "7894"; const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const con = nock("https://www.ogury.co") .get("/db2/client/7894/segt?adsafe_url=google.com") .reply( 200, '{"segment_ids":["501","535","503","537","507","541","505","539","509","543","502","536","504","538","508","542","506","540","510","544","512","546","532","511","545","531","533","513","551"]}', { "Cache-Control": "max-age=889", } ); const provider: IASCategoryProvider = new IASCategoryProvider(); const values: CategoryProviderValue = await provider.getCategories({ device: false, urlOrBundle: "google.com", provider: CategoryProviderType.IAS, requestSource: { environmentType: "web", deviceOS: "android", }, }); expect(values.ttl).to.be.equal(defaultExpireTTL); const decoded = provider.decode(values.encodedValue); expect(decoded.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(decoded.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Unsafe); expect(decoded.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Unsafe); compareTTL(decoded.getRefreshTTL(), 889 * 1000); }); }); describe("sendRequest Device Fraud", function () { beforeEach(() => { config["IAS_CAT_CLIENTID"] = "1234"; delete config.IAS_CAT_WEB_URL; delete config.IAS_CAT_APP_URL; delete config.IAS_CAT_AUTH_URL; delete config.IAS_CAT_CLIENTID; delete config.IAS_CAT_LOGIN; delete config.IAS_CAT_PASS; }); afterEach(() => { if (!nock.isDone()) { const missingMocks = nock.pendingMocks().join("\n"); nock.cleanAll(); nock.restore(); assert.fail("mocks not called \n" + missingMocks); } }); const testDataRequest = [ { name: "unsafe ip ", ip: "2.2.2.1", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_ip=2.2.2.1", response: '{"segment_ids":["80023001","80312001","513","551"]}', segments: ["80023001", "80312001", "513", "551"], result: CategoryRating.Unsafe, }, { name: "unsafe ip empty segments ", ip: "2.2.2.1", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_ip=2.2.2.1", response: '{"segment_ids":[]}', segments: [], result: CategoryRating.Unsafe, }, { name: "safe ip ", ip: "2.2.2.1", requestSource: { environmentType: "web", deviceOS: "android" }, request: "/db2/client/1234/segt?adsafe_ip=2.2.2.1", response: '{"segment_ids":["411"]}', segments: ["411"], result: CategoryRating.Safe, }, ]; for (const environmentType of ["web", "in-app"] as EnvironmentType[]) { for (const deviceOS of ["android", "ios"] as DeviceOS[]) { testDataRequest.forEach((data) => { it(`simulate end to end device fraud request: ${data.name} on ${environmentType} ${deviceOS}`, async function () { const authscope = nock("https://auth.adsafeprotected.com") .post("/uaa/oauth/token?grant_type=client_credentials") .basicAuth({ user: "mylogin", pass: "mypass" }) .reply(200, '{"access_token":"mytoken", "expires_in": 0}'); const scope = nock("https://api.adsafeprotected.com") .matchHeader("authorization", "bearer mytoken") .get(data.request) .reply(200, data.response, { "Cache-Control": "max-age=889", }); const provider: IASCategoryProvider = new IASCategoryProvider(); const values: CategoryProviderValue = await provider.getCategories({ device: true, ip: data.ip, provider: CategoryProviderType.IAS, requestSource: { environmentType: environmentType, deviceOS: deviceOS }, }); expect(values.ttl).to.be.equal(defaultExpireTTL); const decoded = provider.decode(values.encodedValue); expect(decoded.getDeviceFraud()).to.equal(data.result); compareTTL(decoded.getRefreshTTL(), 889000); const segments = decoded.toSegmentList(); expect(segments).to.deep.equal(data.segments); }); }); } } }); describe("decoding", function () { it(`web safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|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" ); expect(value.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); expect(value.isBlockedBySegment("501")).to.false; expect(value.isBlockedBySegment("5001")).to.true; }); it(`app safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "ia|623c8365.999998|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" ); expect(value.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); }); it(`web high unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|501|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" ); expect(value.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Unsafe); expect(value.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); }); it(`web high unknown`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|501|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" ); expect(value.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Unknown); expect(value.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Safe); expect(value.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Safe); }); it(`no segment unknown`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("wa|623c8365.999998|"); expect(value.getBrandSafety(BrandSafetySeverity.High)).to.equal(CategoryRating.Unknown); expect(value.getBrandSafety(BrandSafetySeverity.Medium)).to.equal(CategoryRating.Unknown); expect(value.getBrandSafety(BrandSafetySeverity.Low)).to.equal(CategoryRating.Unknown); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Unknown); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Unknown); }); it(`fraud web safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("wa|623c8365.999998|401|402|407|400|410|404"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Safe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Safe); }); it(`fraud web high unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("wa|623c8365.999998|401|402|400|410"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Unsafe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Unsafe); }); it(`fraud web moderate unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("wa|623c8365.999998|401|402|400|410|404"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Safe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Unsafe); }); it(`fraud app safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("ia|623c8365.999998|4016|8016|4017|8017|4015|8015"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Safe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Safe); }); it(`fraud app high unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("ia|623c8365.999998|8016|8017|4015|8015"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Unsafe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Unsafe); }); it(`fraud app moderate unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("ia|623c8365.999998|8016|4016|8017|4015|8015"); expect(value.getPublisherFraud(FraudSeverity.High)).to.equal(CategoryRating.Safe); expect(value.getPublisherFraud(FraudSeverity.Medium)).to.equal(CategoryRating.Unsafe); }); it(`fraud device unsafe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("ia|623c8365.999998"); expect(value.getDeviceFraud()).to.equal(CategoryRating.Unsafe); }); it(`fraud device app safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("ia|623c8365.999998|411"); expect(value.getDeviceFraud()).to.equal(CategoryRating.Safe); }); it(`fraud device web safe`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode("wi|623c8365.999998|411"); expect(value.getDeviceFraud()).to.equal(CategoryRating.Safe); }); it(`custom segment`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|501|503|537|1000002|1000001|1999999|2000000|3000000|3999999" ); expect(value.isBlockedBySegment("3999999")).to.be.false; expect(value.isBlockedBySegment("3000000")).to.be.false; expect(value.isBlockedBySegment("3050000")).to.be.true; expect(value.isBlockedBySegment("1000004")).to.be.false; expect(value.isBlockedBySegment("1000005")).to.be.false; expect(value.isBlockedBySegment("1000002")).to.be.true; expect(value.isBlockedBySegment("1000001")).to.be.false; expect(value.isBlockedBySegment("4000000")).to.be.false; expect(value.isBlockedBySegment("1999999")).to.be.true; expect(value.isBlockedBySegment("2000000")).to.be.false; expect(value.isBlockedBySegment("2000001")).to.be.true; expect(value.isBlockedBySegment("4999999")).to.be.false; expect(value.isBlockedBySegment("5000000")).to.be.true; expect(value.isBlockedBySegment("537")).to.be.false; expect(value.isBlockedBySegment("504")).to.be.true; }); it(`brand suitability custom segment`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|501|503|537|1000002|1000001|1999999|2000000|3000000|3999999" ); expect(value.isBrandSuitable("3999999", false)).to.be.true; expect(value.isBrandSuitable("3000000", false)).to.be.true; expect(value.isBrandSuitable("3050000", false)).to.be.false; expect(value.isBrandSuitable("1000004", false)).to.be.true; expect(value.isBrandSuitable("1000005", false)).to.be.true; expect(value.isBrandSuitable("1000002", false)).to.be.false; expect(value.isBrandSuitable("1000001", false)).to.be.true; expect(value.isBrandSuitable("4000000", false)).to.be.true; expect(value.isBrandSuitable("1999999", false)).to.be.false; expect(value.isBrandSuitable("2000000", false)).to.be.true; expect(value.isBrandSuitable("2000001", false)).to.be.false; expect(value.isBrandSuitable("4999999", false)).to.be.true; expect(value.isBrandSuitable("5000000", false)).to.be.false; expect(value.isBrandSuitable("537", false)).to.be.true; expect(value.isBrandSuitable("504", false)).to.be.false; }); it(`brand suitability custom segment unknown`, async function () { const provider = new IASCategoryProvider(); const value = provider.decode( "wa|623c8365.999998|1000075|501|503|537|1000002|1000001|1999999|2000000|3000000|3999999" ); expect(value.isBrandSuitable("3999999", true)).to.be.true; expect(value.isBrandSuitable("3000000", true)).to.be.true; expect(value.isBrandSuitable("3050000", true)).to.be.false; expect(value.isBrandSuitable("1000004", true)).to.be.true; expect(value.isBrandSuitable("1000005", true)).to.be.true; expect(value.isBrandSuitable("1000002", true)).to.be.false; expect(value.isBrandSuitable("1000001", true)).to.be.true; expect(value.isBrandSuitable("4000000", true)).to.be.true; expect(value.isBrandSuitable("1999999", true)).to.be.false; expect(value.isBrandSuitable("2000000", true)).to.be.true; expect(value.isBrandSuitable("2000001", true)).to.be.false; expect(value.isBrandSuitable("4999999", true)).to.be.true; expect(value.isBrandSuitable("5000000", true)).to.be.false; expect(value.isBrandSuitable("537", true)).to.be.true; expect(value.isBrandSuitable("504", true)).to.be.false; expect(value.isBrandSuitable("3999999", false)).to.be.false; expect(value.isBrandSuitable("3000000", false)).to.be.false; expect(value.isBrandSuitable("3050000", false)).to.be.false; expect(value.isBrandSuitable("1000004", false)).to.be.false; expect(value.isBrandSuitable("1000005", false)).to.be.false; expect(value.isBrandSuitable("1000002", false)).to.be.false; expect(value.isBrandSuitable("1000001", false)).to.be.false; expect(value.isBrandSuitable("4000000", false)).to.be.false; expect(value.isBrandSuitable("1999999", false)).to.be.false; expect(value.isBrandSuitable("2000000", false)).to.be.false; expect(value.isBrandSuitable("2000001", false)).to.be.false; expect(value.isBrandSuitable("4999999", false)).to.be.false; expect(value.isBrandSuitable("5000000", false)).to.be.false; expect(value.isBrandSuitable("537", false)).to.be.false; expect(value.isBrandSuitable("504", false)).to.be.false; }); }); function compareTTL(ttl: number, expected: number) { const delay = ttl - Date.now(); expect(delay).to.be.lessThanOrEqual(expected); expect(delay).to.be.greaterThan(expected - 5000); } });