Skip to content

Commit

Permalink
Alexis' review
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-greenbids committed Nov 20, 2024
1 parent d9ee105 commit 422b9be
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 109 deletions.
21 changes: 16 additions & 5 deletions integrationExamples/gpt/hello_world.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
sizes: [[300, 250]],
}
},

// Replace this object to test a new Adapter!
bids: [{
bidder: 'appnexus',
bidder: 'greenbids',
params: {
placementId: 13144370
placementId: 4242
}
}]

}];

var pbjs = pbjs || {};
Expand All @@ -48,7 +46,20 @@

pbjs.que.push(function () {
pbjs.addAdUnits(adUnits);

pbjs.setConfig({
bidResponseFilter: {
cat: {
blockUnknown: false // setting only one of parameters will keep the other one as default
},
adv: {
enforce: false
},
attr: {
enforce: false,
blockUnknown: false
}
}
});
pbjs.requestBids({
bidsBackHandler: sendAdserverRequest,
timeout: PREBID_TIMEOUT
Expand Down
45 changes: 21 additions & 24 deletions modules/greenbidsBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getValue, logError, deepAccess, parseSizesInput, getBidIdParameter } from '../src/utils.js';
import { getValue, logError, deepAccess, parseSizesInput, getBidIdParameter, logInfo } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { getStorageManager } from '../src/storageManager.js';
import { getDM, getHC, getHLen } from '../libraries/navigatorData/navigatorData.js';
Expand All @@ -25,6 +25,7 @@ export const spec = {
*/
isBidRequestValid: function (bid) {
if (typeof bid.params !== 'undefined' && parseInt(getValue(bid.params, 'placementId')) > 0) {
logInfo('Greenbids bidder adapter valid bid request');
return true;
} else {
logError('Greenbids bidder adapter requires placementId to be defined and a positive number');
Expand Down Expand Up @@ -69,8 +70,8 @@ export const spec = {
payload.schain = firstBidRequest.schain;
}

hydratePayloadWithGPPData(payload, bidderRequest.gppConsent);
hydratePayloadWithGDPRData(payload, bidderRequest.gdprConsent);
hydratePayloadWithGppData(payload, bidderRequest.gppConsent);
hydratePayloadWithGdprData(payload, bidderRequest.gdprConsent);
hydratePayloadWithUspConsentData(payload, bidderRequest.uspConsent);

const userAgentClientHints = deepAccess(firstBidRequest, 'ortb2.device.sua');
Expand All @@ -87,29 +88,28 @@ export const spec = {
return {
method: 'POST',
url: ENDPOINT_URL,
data: payloadString
data: payloadString,
};
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {*} serverResponse A successful response from the server.
* @return {Bid[]} An array of bids which were nested inside the server.
* @return {Bid[]} An array of bids which were nested inside the server response.
*/
interpretResponse: function (serverResponse, bidderRequest) {
interpretResponse: function (serverResponse) {
serverResponse = serverResponse.body;

if (!serverResponse.responses) {
return [];
}

return serverResponse.responses.map((bid) => {
const bidResponse = {
cpm: bid.cpm,
width: bid.width,
height: bid.height,
currency: bid.currency,
netRevenue: true,
size: bid.size,
ttl: bid.ttl,
meta: {
advertiserDomains: bid && bid.adomain ? bid.adomain : [],
Expand All @@ -133,7 +133,6 @@ export const spec = {
registerBidder(spec);

// Page info retrival

function getReferrerInfo(bidderRequest) {
let ref = '';
if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.page) {
Expand Down Expand Up @@ -217,7 +216,7 @@ function getSizes(bid) {

// Privacy handling

export function hydratePayloadWithGPPData(payload, gppData) {
export function hydratePayloadWithGppData(payload, gppData) {
if (gppData) {
let isValidConsentString = typeof gppData.gppString === 'string';
let validateApplicableSections =
Expand All @@ -228,22 +227,20 @@ export function hydratePayloadWithGPPData(payload, gppData) {
applicableSectionIds: validateApplicableSections ? gppData.applicableSections : [],
};
}
return payload;
}

export function hydratePayloadWithGDPRData(payload, gdprData) {
if (gdprData) {
let isCmp = typeof gdprData.gdprApplies === 'boolean';
let isConsentString = typeof gdprData.consentString === 'string';
let status = isCmp
? findGdprStatus(gdprData.gdprApplies, gdprData.vendorData)
: gdprStatus.CMP_NOT_FOUND_OR_ERROR;
payload.gdpr_iab = {
consent: isConsentString ? gdprData.consentString : '',
status: status,
apiVersion: gdprData.apiVersion
};
}
export function hydratePayloadWithGdprData(payload, gdprData) {
if (!gdprData) { return; }
let isCmp = typeof gdprData.gdprApplies === 'boolean';
let isConsentString = typeof gdprData.consentString === 'string';
let status = isCmp
? findGdprStatus(gdprData.gdprApplies, gdprData.vendorData)
: gdprStatus.CMP_NOT_FOUND_OR_ERROR;
payload.gdpr_iab = {
consent: isConsentString ? gdprData.consentString : '',
status: status,
apiVersion: gdprData.apiVersion
};
}

export function hydratePayloadWithUspConsentData(payload, uspConsentData) {
Expand Down
162 changes: 82 additions & 80 deletions test/spec/modules/greenbidsBidAdapter_specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,21 @@ describe('greenbidsBidAdapter', () => {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

let bidNonGBCompatible = {
'bidder': 'greenbids',
};

it('should return false when required params are not found', function () {
expect(spec.isBidRequestValid(bidNonGBCompatible)).to.equal(false);
let bidNonGbCompatible = {
'bidder': 'greenbids',
};
expect(spec.isBidRequestValid(bidNonGbCompatible)).to.equal(false);
});

let bidNonGBCompatible2 = {
'bidder': 'greenbids',
'params': {
'placementId': 'toto'
},
};

it('should return false when required the placement is not a number', function () {
expect(spec.isBidRequestValid(bidNonGBCompatible2)).to.equal(false);
it('should return false when the placement is not a number', function () {
let bidNonGbCompatible = {
'bidder': 'greenbids',
'params': {
'placementId': 'toto'
},
};
expect(spec.isBidRequestValid(bidNonGbCompatible)).to.equal(false);
});
})
describe('buildRequests', function () {
Expand Down Expand Up @@ -420,38 +418,65 @@ describe('greenbidsBidAdapter', () => {
expect(payload.pageDescription).to.deep.equal(testText);
});

it('should add timeToFirstByte info to payload', function () {
it('should add timeToFirstByte info to payload for Navigation Timing V2', function () {
// Mock `performance` object with Navigation Timing V2 data
const mockPerformance = {
getEntriesByType: () => [
{ requestStart: 100, responseStart: 150 },
],
};

// Override the global performance object
const originalPerformance = window.performance;
window.performance = mockPerformance;

// Execute the code
const request = spec.buildRequests(bidRequests, bidderRequestDefault);
const payload = JSON.parse(request.data);
const performance = window.performance || window.webkitPerformance || window.msPerformance || window.mozPerformance;

const ttfbExpectedV2 = performance &&
typeof performance.getEntriesByType === 'function' &&
Object.prototype.toString.call(performance.getEntriesByType) === '[object Function]' &&
performance.getEntriesByType('navigation')[0] &&
performance.getEntriesByType('navigation')[0].responseStart &&
performance.getEntriesByType('navigation')[0].requestStart &&
performance.getEntriesByType('navigation')[0].responseStart > 0 &&
performance.getEntriesByType('navigation')[0].requestStart > 0 &&
Math.round(
performance.getEntriesByType('navigation')[0].responseStart - performance.getEntriesByType('navigation')[0].requestStart
);
// Calculate expected TTFB for V2
const ttfbExpected = Math.round(
mockPerformance.getEntriesByType('navigation')[0].responseStart -
mockPerformance.getEntriesByType('navigation')[0].requestStart
).toString();

// Assertions
expect(payload.timeToFirstByte).to.exist;
expect(payload.timeToFirstByte).to.deep.equal(ttfbExpected);

if (ttfbExpectedV2) {
expect(payload.timeToFirstByte).to.deep.equal(ttfbExpectedV2.toString());
} else {
const ttfbWithTimingV1 = performance &&
performance.timing.responseStart &&
performance.timing.requestStart &&
performance.timing.responseStart > 0 &&
performance.timing.requestStart > 0 &&
performance.timing.responseStart - performance.timing.requestStart;
const ttfbExpectedV1 = ttfbWithTimingV1 ? ttfbWithTimingV1.toString() : '';

expect(payload.timeToFirstByte).to.deep.equal(ttfbExpectedV1);
}
// Restore the original performance object
window.performance = originalPerformance;
});

it('should add timeToFirstByte info to payload for Navigation Timing V1', function () {
// Mock `performance` object with Navigation Timing V1 data
const mockPerformance = {
timing: {
requestStart: 100,
responseStart: 150,
},
getEntriesByType: () => [],
};

// Override the global performance object
const originalPerformance = window.performance;
window.performance = mockPerformance;

// Execute the code
const request = spec.buildRequests(bidRequests, bidderRequestDefault);
const payload = JSON.parse(request.data);

// Calculate expected TTFB for V1
const ttfbExpected = (
mockPerformance.timing.responseStart - mockPerformance.timing.requestStart
).toString();

// Assertions
expect(payload.timeToFirstByte).to.exist;
expect(payload.timeToFirstByte).to.deep.equal(ttfbExpected);

// Restore the original performance object
window.performance = originalPerformance;
});

it('should send GDPR to endpoint with 11 status', function () {
Expand Down Expand Up @@ -627,43 +652,7 @@ describe('greenbidsBidAdapter', () => {
});

it('should add userAgentClientHints info to payload if available', function () {
const bidRequest = Object.assign({}, bidRequests[0], {
ortb2: {
device: {
sua: {
source: 2,
platform: {
brand: 'macOS',
version: ['12', '4', '0']
},
browsers: [
{
brand: 'Chromium',
version: ['106', '0', '5249', '119']
},
{
brand: 'Google Chrome',
version: ['106', '0', '5249', '119']
},
{
brand: 'Not;A=Brand',
version: ['99', '0', '0', '0']
}
],
mobile: 0,
model: '',
bitness: '64',
architecture: 'x86'
}
}
}
});

const requestWithUserAgentClientHints = spec.buildRequests([bidRequest], bidderRequestDefault);
const payload = JSON.parse(requestWithUserAgentClientHints.data);

expect(payload.userAgentClientHints).to.exist;
expect(payload.userAgentClientHints).to.deep.equal({
const sua = {
source: 2,
platform: {
brand: 'macOS',
Expand All @@ -688,7 +677,20 @@ describe('greenbidsBidAdapter', () => {
bitness: '64',
architecture: 'x86'
}
);

const bidRequest = Object.assign({}, bidRequests[0], {
ortb2: {
device: {
sua: sua
}
}
});

const requestWithUserAgentClientHints = spec.buildRequests([bidRequest], bidderRequestDefault);
const payload = JSON.parse(requestWithUserAgentClientHints.data);

expect(payload.userAgentClientHints).to.exist;
expect(payload.userAgentClientHints).to.deep.equal(sua);

const defaultRequest = spec.buildRequests(bidRequests, bidderRequestDefault);
expect(JSON.parse(defaultRequest.data).userAgentClientHints).to.not.exist;
Expand Down Expand Up @@ -766,7 +768,7 @@ describe('greenbidsBidAdapter', () => {
const request = spec.buildRequests(updatedBidRequests, bidderRequestDefault);
const payload = JSON.parse(request.data);

return payload.data.forEach(bid => {
payload.data.forEach(bid => {
expect(bid).not.to.have.property('gpid');
});
});
Expand All @@ -783,7 +785,7 @@ describe('greenbidsBidAdapter', () => {
const request = spec.buildRequests(updatedBidRequests, bidderRequestDefault);
const payload = JSON.parse(request.data);

return payload.data.forEach(bid => {
payload.data.forEach(bid => {
expect(bid).not.to.have.property('gpid');
});
});
Expand Down

0 comments on commit 422b9be

Please sign in to comment.