From 1695be016daba9e97ea6a09ecc09a1ed03ecf734 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Mon, 4 Apr 2022 14:23:01 -0400 Subject: [PATCH] Revert "Glimpse: update api and request shape, optimize and refactor (#8237)" This reverts commit 28b4c69e0b96578536b06b750e9fad2f5ab7cc1b. --- modules/glimpseBidAdapter.js | 265 +++++---- modules/glimpseBidAdapter.md | 15 +- test/spec/modules/glimpseBidAdapter_spec.js | 586 ++++++++------------ 3 files changed, 393 insertions(+), 473 deletions(-) diff --git a/modules/glimpseBidAdapter.js b/modules/glimpseBidAdapter.js index fc8f8dd4849..678e35729da 100644 --- a/modules/glimpseBidAdapter.js +++ b/modules/glimpseBidAdapter.js @@ -1,27 +1,18 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { - isArray, - isEmpty, - isEmptyStr, - isStr, - isPlainObject, -} from '../src/utils.js'; - -const GVLID = 1012; -const BIDDER_CODE = 'glimpse'; -const storageManager = getStorageManager({ - gvlid: GVLID, - bidderCode: BIDDER_CODE, -}); -const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid'; +import { BANNER } from '../src/mediaTypes.js' +import { config } from '../src/config.js' +import { getStorageManager } from '../src/storageManager.js' +import { isArray } from '../src/utils.js' +import { registerBidder } from '../src/adapters/bidderFactory.js' + +const GVLID = 1012 +const BIDDER_CODE = 'glimpse' +const storageManager = getStorageManager({bidderCode: BIDDER_CODE}) +const ENDPOINT = 'https://api.glimpsevault.io/ads/serving/public/v1/prebid' const LOCAL_STORAGE_KEY = { vault: { jwt: 'gp_vault_jwt', }, -}; +} export const spec = { gvlid: GVLID, @@ -29,121 +20,126 @@ export const spec = { supportedMediaTypes: [BANNER], /** - * Determines if the bid request is valid + * Determines whether or not the given bid request is valid * @param bid {BidRequest} The bid to validate * @return {boolean} */ isBidRequestValid: (bid) => { - const pid = bid?.params?.pid; - return isStr(pid) && !isEmptyStr(pid); + return ( + hasValue(bid) && + hasValue(bid.params) && + hasStringValue(bid.params.placementId) + ) }, /** - * Builds the http request + * Builds http request for Glimpse bids * @param validBidRequests {BidRequest[]} * @param bidderRequest {BidderRequest} * @returns {ServerRequest} */ buildRequests: (validBidRequests, bidderRequest) => { - const url = buildQuery(bidderRequest); - const auth = getVaultJwt(); - const referer = getReferer(bidderRequest); - const imp = validBidRequests.map(processBidRequest); - const fpd = getFirstPartyData(); + const auth = getVaultJwt() + const referer = getReferer(bidderRequest) + const gdprConsent = getGdprConsentChoice(bidderRequest) + const bidRequests = validBidRequests.map(processBidRequest) + const firstPartyData = getFirstPartyData() const data = { auth, data: { referer, - imp, - fpd, - }, - }; + gdprConsent, + bidRequests, + site: firstPartyData.site, + user: firstPartyData.user, + bidderCode: spec.code, + } + } return { method: 'POST', - url, + url: ENDPOINT, data: JSON.stringify(data), options: {}, - }; + } }, /** - * Parse http response - * @param response {ServerResponse} + * Parse response from Glimpse server + * @param bidResponse {ServerResponse} * @returns {Bid[]} */ - interpretResponse: (response) => { - if (isValidResponse(response)) { - const { auth, data } = response.body; - setVaultJwt(auth); - const bids = data.bids.map(processBidResponse); - return bids; + interpretResponse: (bidResponse) => { + const isValidResponse = isValidBidResponse(bidResponse) + + if (isValidResponse) { + const {auth, data} = bidResponse.body + setVaultJwt(auth) + return data.bids } - return []; + + return [] }, -}; +} function setVaultJwt(auth) { - storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth); + storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth) } function getVaultJwt() { - return ( - storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || '' - ); + return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || '' } function getReferer(bidderRequest) { - return bidderRequest?.refererInfo?.referer || ''; + const hasReferer = + hasValue(bidderRequest) && + hasValue(bidderRequest.refererInfo) && + hasStringValue(bidderRequest.refererInfo.referer) + + if (hasReferer) { + return bidderRequest.refererInfo.referer + } + + return '' } -function buildQuery(bidderRequest) { - let url = appendQueryParam(ENDPOINT, 'ver', '$prebid.version$'); +function getGdprConsentChoice(bidderRequest) { + const hasGdprConsent = + hasValue(bidderRequest) && + hasValue(bidderRequest.gdprConsent) - const timeout = config.getConfig('bidderTimeout'); - url = appendQueryParam(url, 'tmax', timeout); + if (hasGdprConsent) { + const gdprConsent = bidderRequest.gdprConsent + const hasGdprApplies = hasBooleanValue(gdprConsent.gdprApplies) - if (gdprApplies(bidderRequest)) { - const consentString = bidderRequest.gdprConsent.consentString; - url = appendQueryParam(url, 'reg', 'gdpr'); - url = appendQueryParam(url, 'cs', consentString); - } else if (ccpaApplies(bidderRequest)) { - url = appendQueryParam(url, 'reg', 'ccpa'); - url = appendQueryParam(url, 'cs', bidderRequest.uspConsent); - } else { - url = appendQueryParam(url, 'reg', 'none'); + return { + consentString: gdprConsent.consentString || '', + vendorData: gdprConsent.vendorData || {}, + gdprApplies: hasGdprApplies ? gdprConsent.gdprApplies : true, + } } - return url; -} -function appendQueryParam(url, key, value) { - if (!value) { - return url; + return { + consentString: '', + vendorData: {}, + gdprApplies: false, } - const prefix = url.includes('?') ? '&' : '?'; - return `${url}${prefix}${key}=${encodeURIComponent(value)}`; -} - -function gdprApplies(bidderRequest) { - return Boolean(bidderRequest?.gdprConsent?.gdprApplies); } -function ccpaApplies(bidderRequest) { - return ( - !isEmptyStr(bidderRequest.uspConsent) && - bidderRequest.uspConsent.substr(1, 3) !== '---' - ); -} - -function processBidRequest(bid) { - const sizes = normalizeSizes(bid.sizes); +function processBidRequest(bidRequest) { + const demand = bidRequest.params.demand || 'glimpse' + const sizes = normalizeSizes(bidRequest.sizes) + const keywords = bidRequest.params.keywords || {} return { - bid: bid.bidId, - pid: bid.params.pid, + demand, sizes, - }; + keywords, + bidId: bidRequest.bidId, + placementId: bidRequest.params.placementId, + unitCode: bidRequest.adUnitCode, + } } function normalizeSizes(sizes) { @@ -151,51 +147,84 @@ function normalizeSizes(sizes) { isArray(sizes) && sizes.length === 2 && !isArray(sizes[0]) && - !isArray(sizes[1]); + !isArray(sizes[1]) if (isSingleSize) { - return [sizes]; + return [sizes] } - return sizes; + return sizes } function getFirstPartyData() { - let fpd = config.getConfig('ortb2') || {}; - optimizeObject(fpd); - return fpd; -} + const siteKeywords = parseGlobalKeywords('site') + const userKeywords = parseGlobalKeywords('user') -function optimizeObject(obj) { - if (!isPlainObject(obj)) { - return; - } - for (const [key, value] of Object.entries(obj)) { - optimizeObject(value); - // only delete empty object, array, or string - if ( - (isPlainObject(value) || isArray(value) || isStr(value)) && - isEmpty(value) - ) { - delete obj[key]; - } + const siteAttributes = getConfig('ortb2.site.ext.data', {}) + const userAttributes = getConfig('ortb2.user.ext.data', {}) + + return { + site: { + keywords: siteKeywords, + attributes: siteAttributes, + }, + user: { + keywords: userKeywords, + attributes: userAttributes, + }, } } -function isValidResponse(bidResponse) { - const auth = bidResponse?.body?.auth; - const bids = bidResponse?.body?.data?.bids; - return isStr(auth) && isArray(bids) && !isEmpty(bids); +function parseGlobalKeywords(scope) { + const keywords = getConfig(`ortb2.${scope}.keywords`, '') + + return keywords + .split(', ') + .filter((keyword) => keyword !== '') } -function processBidResponse(bid) { - const meta = bid.meta || {}; - meta.advertiserDomains = bid.meta?.advertiserDomains || []; +function getConfig(path, defaultValue) { + return config.getConfig(path) || defaultValue +} - return { - ...bid, - meta, - }; +function isValidBidResponse(bidResponse) { + return ( + hasValue(bidResponse) && + hasValue(bidResponse.body) && + hasValue(bidResponse.body.data) && + hasArrayValue(bidResponse.body.data.bids) && + hasStringValue(bidResponse.body.auth) + ) +} + +function hasValue(value) { + return ( + value !== undefined && + value !== null + ) +} + +function hasBooleanValue(value) { + return ( + hasValue(value) && + typeof value === 'boolean' + ) +} + +function hasStringValue(value) { + return ( + hasValue(value) && + typeof value === 'string' && + value.length > 0 + ) +} + +function hasArrayValue(value) { + return ( + hasValue(value) && + isArray(value) && + value.length > 0 + ) } -registerBidder(spec); +registerBidder(spec) diff --git a/modules/glimpseBidAdapter.md b/modules/glimpseBidAdapter.md index e82c5d8f32e..767efcecf54 100644 --- a/modules/glimpseBidAdapter.md +++ b/modules/glimpseBidAdapter.md @@ -24,14 +24,15 @@ const adUnits = [ sizes: [[300, 250]], }, }, - bids: [ - { - bidder: 'glimpse', - params: { - pid: 'e53a7f564f8f44cc913b', + bids: [{ + bidder: 'glimpse', + params: { + placementId: 'e53a7f564f8f44cc913b', + keywords: { + country: 'uk', }, }, - ], + }], }, -]; +] ``` diff --git a/test/spec/modules/glimpseBidAdapter_spec.js b/test/spec/modules/glimpseBidAdapter_spec.js index e4ca36e4403..02f5b502a1b 100644 --- a/test/spec/modules/glimpseBidAdapter_spec.js +++ b/test/spec/modules/glimpseBidAdapter_spec.js @@ -1,13 +1,9 @@ -import { expect } from 'chai'; -import { spec } from 'modules/glimpseBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config'; -import { BANNER } from '../../../src/mediaTypes'; +import { BANNER } from '../../../src/mediaTypes' +import { expect } from 'chai' +import { newBidder } from 'src/adapters/bidderFactory.js' +import { spec } from 'modules/glimpseBidAdapter.js' -const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid'; - -const nonStringValues = [null, undefined, 123, true, {}, [], () => {}]; -const nonArrayValues = [null, undefined, 123, true, {}, 'str', () => {}]; +const ENDPOINT = 'https://api.glimpsevault.io/ads/serving/public/v1/prebid' const mock = { bidRequest: { @@ -18,7 +14,7 @@ const mock = { adUnitCode: 'banner-div-a', sizes: [[300, 250]], params: { - pid: 'glimpse-demo-300x250', + placementId: 'glimpse-demo-300x250', }, }, bidderRequest: { @@ -27,8 +23,7 @@ const mock = { auctionId: '96692a73-307b-44b8-8e4f-ddfb40341570', timeout: 3000, gdprConsent: { - consentString: - 'COzP517OzP517AcABBENAlCsAP_AAAAAAAwIF8NX-T5eL2vju2Zdt7JEaYwfZxyigOgThgQIsW8NwIeFbBoGP2EgHBG4JCQAGBAkkgCBAQMsHGBcCQAAgIgRiRKMYE2MjzNKBJJAigkbc0FACDVunsHS2ZCY70-8O__bPAviADAvUC-AAAAA.YAAAAAAAAAAA', + consentString: 'COzP517OzP517AcABBENAlCsAP_AAAAAAAwIF8NX-T5eL2vju2Zdt7JEaYwfZxyigOgThgQIsW8NwIeFbBoGP2EgHBG4JCQAGBAkkgCBAQMsHGBcCQAAgIgRiRKMYE2MjzNKBJJAigkbc0FACDVunsHS2ZCY70-8O__bPAviADAvUC-AAAAA.YAAAAAAAAAAA', vendorData: {}, gdprApplies: true, }, @@ -44,6 +39,7 @@ const mock = { data: { bids: [ { + bidder: 'glimpse', requestId: '133baeded6ac94', creativeId: 'glimpse-demo-300x250', adUnitCode: 'banner-div-a', @@ -52,379 +48,273 @@ const mock = { width: 300, height: 250, cpm: 1.04, + pbAg: '1.04', + pbDg: '1.04', + pbHg: '1.04', + pbLg: '1.00', + pbMg: '1.05', netRevenue: true, mediaType: 'banner', ttl: 300, - }, + } ], }, }, -}; +} -const getBidRequest = () => getDeepCopy(mock.bidRequest); +const getBidRequest = () => getDeepCopy(mock.bidRequest) const getBidderRequest = () => ({ bids: [getBidRequest()], ...getDeepCopy(mock.bidderRequest), -}); +}) +const getBidResponseHelper = () => getDeepCopy(mock.bidResponse) const getBidResponse = () => ({ - body: getDeepCopy(mock.bidResponse), -}); + body: getBidResponseHelper(), +}) function getDeepCopy(object) { - return JSON.parse(JSON.stringify(object)); + return JSON.parse(JSON.stringify(object)) } describe('GlimpseProtocolAdapter', () => { - const glimpseAdapter = newBidder(spec); + const glimpseAdapter = newBidder(spec) describe('spec', () => { it('Has defined the glimpse gvlid', () => { - expect(spec.gvlid).to.equal(1012); - }); + expect(spec.gvlid).to.equal(1012) + }) it('Has defined glimpse as the bidder', () => { - expect(spec.code).to.equal('glimpse'); - }); + expect(spec.code).to.equal('glimpse') + }) it('Has defined valid mediaTypes', () => { - expect(spec.supportedMediaTypes).to.deep.equal([BANNER]); - }); - }); + expect(spec.supportedMediaTypes).to.deep.equal([BANNER]) + }) + }) describe('Inherited functions', () => { it('Functions exist and are valid types', () => { - expect(glimpseAdapter.callBids).to.exist.and.to.be.a('function'); - expect(glimpseAdapter.getSpec).to.exist.and.to.be.a('function'); - }); - }); + expect(glimpseAdapter.callBids).to.exist.and.to.be.a('function') + expect(glimpseAdapter.getSpec).to.exist.and.to.be.a('function') + }) + }) describe('isBidRequestValid', () => { - it('Returns true if placement id is non-empty string', () => { - const bidRequest = getBidRequest(); + it('Returns true when a bid request has a valid placement id', () => { + const bidRequest = getBidRequest() + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.true + }) + + it('Returns false when params are empty', () => { + const bidRequest = getBidRequest() + bidRequest.params = {} + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) + + it('Returns false when params are null', () => { + const bidRequest = getBidRequest() + bidRequest.params = null + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) + + it('Returns false when params are undefined', () => { + const bidRequest = getBidRequest() + delete bidRequest.params + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) + + it('Returns false when params are invalid type', () => { + const bidRequest = getBidRequest() + bidRequest.params = 123 + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.true; - }); + it('Returns false when placement id is empty', () => { + const bidRequest = getBidRequest() + bidRequest.params.placementId = '' - it('Returns false if no pid is provided', () => { - const bidRequest = getBidRequest(); - delete bidRequest.params.pid; + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); + it('Returns false when placement id is null', () => { + const bidRequest = getBidRequest() + bidRequest.params.placementId = null - it('Returns false if pid is empty string', () => { - const bidRequest = getBidRequest(); - bidRequest.params.pid = ''; + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); + it('Returns false when placement id is undefined', () => { + const bidRequest = getBidRequest() + delete bidRequest.params.placementId - it('Returns false if pid is not string', () => { - const bidRequest = getBidRequest(); - const invalidPids = nonStringValues; + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) - invalidPids.forEach((invalidPid) => { - bidRequest.params.pid = invalidPid; - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); - }); - }); + it('Returns false when placement id has an invalid type', () => { + const bidRequest = getBidRequest() + bidRequest.params.placementId = 123 + + const isValidBidRequest = spec.isBidRequestValid(bidRequest) + expect(isValidBidRequest).to.be.false + }) + }) describe('buildRequests', () => { - const bidRequests = [getBidRequest()]; - const bidderRequest = getBidderRequest(); - - it('Adds additional info to api request query', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const url = new URL(request.url); - const queries = new URLSearchParams(url.search); - - expect(queries.get('ver')).to.exist; - expect(queries.get('tmax')).to.exist; - expect(queries.get('reg')).to.exist; - expect(queries.get('cs')).to.equal( - bidderRequest.gdprConsent.consentString - ); - }); - - it('Has correct payload shape', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.auth).to.be.a('string'); - expect(payload.data).to.be.an('object'); - expect(payload.data.referer).to.be.a('string'); - expect(payload.data.imp).to.be.an('array'); - expect(payload.data.fpd).to.be.an('object'); - }); - - it('Has referer information', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const expected = mock.bidderRequest.refererInfo.referer; - - expect(payload.data.referer).to.equal(expected); - }); - - it('Has correct bids (imp) shape', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const imp = payload.data.imp; - - imp.forEach((i) => { - expect(i.bid).to.be.a('string'); - expect(i.pid).to.be.a('string'); - expect(i.sizes).to.be.an('array').that.deep.include([300, 250]); - }); - }); - }); + const bidRequests = [getBidRequest()] + const bidderRequest = getBidderRequest() + + it('Adds GDPR consent', () => { + const request = spec.buildRequests(bidRequests, bidderRequest) + const payload = JSON.parse(request.data) + const expected = bidderRequest.gdprConsent.consentString + + expect(payload.data.gdprConsent).to.exist + expect(payload.data.gdprConsent.gdprApplies).to.be.true + expect(payload.data.gdprConsent.consentString).to.equal(expected) + }) + + it('Adds referer information', () => { + const request = spec.buildRequests(bidRequests, bidderRequest) + const payload = JSON.parse(request.data) + const expected = mock.bidderRequest.refererInfo.referer + + expect(payload.data.referer).to.equal(expected) + }) + + it('Sends a POST request to the Glimpse server', () => { + const request = spec.buildRequests(bidRequests) + + expect(request.url).to.equal(ENDPOINT) + expect(request.method).to.equal('POST') + }) + }) describe('interpretResponse', () => { - it('Returns valid bids', () => { - const bidResponse = getBidResponse(); - const bids = spec.interpretResponse(bidResponse); - - expect(bids).to.have.lengthOf(1); - expect(bids[0].adUnitCode).to.equal(mock.bidRequest.adUnitCode); - }); - - it('Returns no bids if auth is not string', () => { - const bidResponse = getBidResponse(); - const invalidAuths = nonStringValues; - - invalidAuths.forEach((invalidAuth) => { - bidResponse.body.auth = invalidAuth; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - }); - - it('Returns no bids if bids is empty', () => { - const bidResponse = getBidResponse(); - bidResponse.body.data.bids = []; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - - it('Returns no bids if bids is not array', () => { - const bidResponse = getBidResponse(); - const invalidBids = nonArrayValues; - - invalidBids.forEach((invalidBid) => { - bidResponse.body.data.bids = invalidBid; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - }); - - it('Contains advertiserDomains', () => { - const bidResponse = getBidResponse(); - - const bids = spec.interpretResponse(bidResponse); - bids.forEach((bid) => { - expect(bid.meta.advertiserDomains).to.be.an('array'); - }); - }); - }); - - describe('optimize request fpd data', () => { - const bidRequests = [getBidRequest()]; - const bidderRequest = getBidderRequest(); - - const fpdMockBase = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - }; - - afterEach(() => { - config.getConfig.restore(); - }); - - it('should keep all non-empty fields', () => { - const fpdMock = fpdMockBase; - sinon.stub(config, 'getConfig').withArgs('ortb2').returns(fpdMock); - const expected = fpdMockBase; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty objects', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.ext.data.fpdProvider.dataObject = {}; - fpdMock.user.ext.data.fpdProvider = {}; - sinon.stub(config, 'getConfig').withArgs('ortb2').returns(fpdMock); - - const expected = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - }, - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty arrays', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.ext.data.fpdProvider.dataArray = []; - fpdMock.user.ext.data.fpdProvider.dataArray = []; - sinon.stub(config, 'getConfig').withArgs('ortb2').returns(fpdMock); - - const expected = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - ext: { - data: { - fpdProvider: { - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty strings', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.keywords = ''; - fpdMock.site.ext.data.fpdProvider.dataString = ''; - fpdMock.user.keywords = ''; - fpdMock.user.ext.data.fpdProvider.dataString = ''; - sinon.stub(config, 'getConfig').withArgs('ortb2').returns(fpdMock); - - const expected = { - site: { - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - }, - }, - }, - }, - user: { - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - }, - }, - }, - }, - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty fields', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.keywords = ''; - fpdMock.site.ext.data.fpdProvider.dataArray = []; - fpdMock.site.ext.data.fpdProvider.dataObject = {}; - fpdMock.site.ext.data.fpdProvider.dataString = ''; - fpdMock.user.keywords = ''; - fpdMock.user.ext.data.fpdProvider.dataArray = []; - fpdMock.user.ext.data.fpdProvider.dataObject = {}; - fpdMock.user.ext.data.fpdProvider.dataString = ''; - sinon.stub(config, 'getConfig').withArgs('ortb2').returns(fpdMock); - - const expected = {}; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - }); -}); + it('Handles valid bid responses', () => { + const bidResponse = getBidResponse() + const bids = spec.interpretResponse(bidResponse) + + expect(bids).to.have.lengthOf(1) + expect(bids[0].adUnitCode).to.equal(mock.bidRequest.adUnitCode) + }) + + it('Handles no bid responses', () => { + const bidResponse = getBidResponse() + bidResponse.body.data.bids = [] + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if body is empty', () => { + const bidResponse = getBidResponse() + bidResponse.body = {} + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if body is null', () => { + const bidResponse = getBidResponse() + bidResponse.body = null + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if body is undefined', () => { + const bidResponse = getBidResponse() + delete bidResponse.body + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if body is invalid type', () => { + const bidResponse = getBidResponse() + bidResponse.body = 123 + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if auth is empty', () => { + const bidResponse = getBidResponse() + bidResponse.body.auth = '' + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if auth is null', () => { + const bidResponse = getBidResponse() + bidResponse.body.auth = null + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if auth is undefined', () => { + const bidResponse = getBidResponse() + delete bidResponse.body.auth + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bids if auth is invalid type', () => { + const bidResponse = getBidResponse() + bidResponse.body.auth = 123 + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bid if data is empty', () => { + const bidResponse = getBidResponse() + bidResponse.body.data = {} + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bid if data is null', () => { + const bidResponse = getBidResponse() + bidResponse.body.data = null + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bid if data is undefined', () => { + const bidResponse = getBidResponse() + delete bidResponse.body.data + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + + it('Returns no bid if data is invalid type', () => { + const bidResponse = getBidResponse() + bidResponse.body.data = "This shouldn't be a string" + + const bids = spec.interpretResponse(bidResponse) + expect(bids).to.have.lengthOf(0) + }) + }) +})