Skip to content

Commit

Permalink
ttd Bid Adapter: add regression test topmost domain (prebid#9300)
Browse files Browse the repository at this point in the history
* TTD Adapter use topmost location when available

* TTD add use top most location regression test

Co-authored-by: Andre Gielow <andre.gielow@thetradedesk.com>
  • Loading branch information
gielow and andre-gielow-ttd authored Nov 30, 2022
1 parent 1b4a5a3 commit 0c71ee2
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 97 deletions.
88 changes: 88 additions & 0 deletions test/helpers/refererDetectionHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Build a walkable linked list of window-like objects for testing.
*
* @param {Array} urls Array of URL strings starting from the top window.
* @param {string} [topReferrer]
* @param {string} [canonicalUrl]
* @param {boolean} [ancestorOrigins]
* @returns {Object}
*/
export function buildWindowTree(urls, topReferrer = null, canonicalUrl = null, ancestorOrigins = false) {
/**
* Find the origin from a given fully-qualified URL.
*
* @param {string} url The fully qualified URL
* @returns {string|null}
*/
function getOrigin(url) {
const originRegex = new RegExp('^(https?://[^/]+/?)');

const result = originRegex.exec(url);

if (result && result[0]) {
return result[0];
}

return null;
}

const inaccessibles = [];

let previousWindow, topWindow;
const topOrigin = getOrigin(urls[0]);

const windowList = urls.map((url, index) => {
const thisOrigin = getOrigin(url),
sameOriginAsPrevious = index === 0 ? true : (getOrigin(urls[index - 1]) === thisOrigin),
sameOriginAsTop = thisOrigin === topOrigin;

const win = {
location: {
href: url,
},
document: {
referrer: index === 0 ? topReferrer : urls[index - 1]
}
};

if (topWindow == null) {
topWindow = win;
win.document.querySelector = function (selector) {
if (selector === 'link[rel=\'canonical\']') {
return {
href: canonicalUrl
};
}
return null;
};
}

if (sameOriginAsPrevious) {
win.parent = previousWindow;
} else {
win.parent = inaccessibles[inaccessibles.length - 1];
}
if (ancestorOrigins) {
win.location.ancestorOrigins = urls.slice(0, index).reverse().map(getOrigin);
}
win.top = sameOriginAsTop ? topWindow : inaccessibles[0];

const inWin = {parent: inaccessibles[inaccessibles.length - 1], top: inaccessibles[0]};
if (index === 0) {
inWin.top = inWin;
}
['document', 'location'].forEach((prop) => {
Object.defineProperty(inWin, prop, {
get: function () {
throw new Error('cross-origin access');
}
});
});
inaccessibles.push(inWin);
previousWindow = win;

return win;
});

return windowList[windowList.length - 1];
}
45 changes: 36 additions & 9 deletions test/spec/modules/ttdBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { expect } from 'chai';
import { spec } from 'modules/ttdBidAdapter';
import { deepClone } from 'src/utils.js';
import { config } from 'src/config';
import { detectReferer } from 'src/refererDetection.js';

import { buildWindowTree } from '../../helpers/refererDetectionHelper';

describe('ttdBidAdapter', function () {
function testBuildRequests(bidRequests, bidderRequestBase) {
Expand Down Expand Up @@ -200,20 +203,15 @@ describe('ttdBidAdapter', function () {
'bidRequestsCount': 1
}];

const testWindow = buildWindowTree(['https://www.example.com/test', 'https://www.example.com/other/page', 'https://www.example.com/third/page'], 'https://othersite.com/', 'https://example.com/canonical/page');
const baseBidderRequestReferer = detectReferer(testWindow)();
const baseBidderRequest = {
'bidderCode': 'ttd',
'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c',
'bidderRequestId': '18084284054531',
'auctionStart': 1540945362095,
'timeout': 3000,
'refererInfo': {
'page': 'https://www.example.com/test',
'reachedTop': true,
'numIframes': 0,
'stack': [
'https://www.example.com/test'
]
},
'refererInfo': baseBidderRequestReferer,
'start': 1540945362099,
'doneCbCallCount': 0
};
Expand Down Expand Up @@ -291,6 +289,11 @@ describe('ttdBidAdapter', function () {
expect(requestBody.site.page).to.equal('https://www.example.com/test');
});

it('ensure top most location is used', function () {
const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data;
expect(requestBody.site.page).to.equal('https://www.example.com/test');
});

it('sets the banner pos correctly if sent', function () {
let clonedBannerRequests = deepClone(baseBannerBidRequests);
clonedBannerRequests[0].mediaTypes.banner.pos = 1;
Expand Down Expand Up @@ -318,11 +321,35 @@ describe('ttdBidAdapter', function () {
}
}
};
const requestBody = testBuildRequests(baseBannerBidRequests, {...baseBidderRequest, ortb2}).data;
const baseBidderRequestWithoutRefererDomain = {
...baseBidderRequest,
refererInfo: {
...baseBannerBidRequests.referer,
domain: null
}
}
const requestBody = testBuildRequests(
baseBannerBidRequests, {...baseBidderRequestWithoutRefererDomain, ortb2}
).data;
config.resetConfig();
expect(requestBody.site.publisher).to.deep.equal({domain: 'https://foo.bar', id: '13144370'});
});

it('referer domain overrides first party site data publisher domain', function () {
const ortb2 = {
site: {
publisher: {
domain: 'https://foo.bar',
}
}
};
const requestBody = testBuildRequests(
baseBannerBidRequests, {...baseBidderRequest, ortb2}
).data;
config.resetConfig();
expect(requestBody.site.publisher.domain).to.equal(baseBidderRequest.refererInfo.domain);
});

it('sets keywords properly if sent', function () {
const ortb2 = {
site: {
Expand Down
89 changes: 1 addition & 88 deletions test/spec/refererDetection_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,7 @@ import {detectReferer, ensureProtocol, parseDomain} from 'src/refererDetection.j
import {config} from 'src/config.js';
import {expect} from 'chai';

/**
* Build a walkable linked list of window-like objects for testing.
*
* @param {Array} urls Array of URL strings starting from the top window.
* @param {string} [topReferrer]
* @param {string} [canonicalUrl]
* @param {boolean} [ancestorOrigins]
* @returns {Object}
*/
function buildWindowTree(urls, topReferrer = null, canonicalUrl = null, ancestorOrigins = false) {
/**
* Find the origin from a given fully-qualified URL.
*
* @param {string} url The fully qualified URL
* @returns {string|null}
*/
function getOrigin(url) {
const originRegex = new RegExp('^(https?://[^/]+/?)');

const result = originRegex.exec(url);

if (result && result[0]) {
return result[0];
}

return null;
}

const inaccessibles = [];

let previousWindow, topWindow;
const topOrigin = getOrigin(urls[0]);

const windowList = urls.map((url, index) => {
const thisOrigin = getOrigin(url),
sameOriginAsPrevious = index === 0 ? true : (getOrigin(urls[index - 1]) === thisOrigin),
sameOriginAsTop = thisOrigin === topOrigin;

const win = {
location: {
href: url,
},
document: {
referrer: index === 0 ? topReferrer : urls[index - 1]
}
};

if (topWindow == null) {
topWindow = win;
win.document.querySelector = function (selector) {
if (selector === 'link[rel=\'canonical\']') {
return {
href: canonicalUrl
};
}
return null;
};
}

if (sameOriginAsPrevious) {
win.parent = previousWindow;
} else {
win.parent = inaccessibles[inaccessibles.length - 1];
}
if (ancestorOrigins) {
win.location.ancestorOrigins = urls.slice(0, index).reverse().map(getOrigin);
}
win.top = sameOriginAsTop ? topWindow : inaccessibles[0];

const inWin = {parent: inaccessibles[inaccessibles.length - 1], top: inaccessibles[0]};
if (index === 0) {
inWin.top = inWin;
}
['document', 'location'].forEach((prop) => {
Object.defineProperty(inWin, prop, {
get: function () {
throw new Error('cross-origin access');
}
});
});
inaccessibles.push(inWin);
previousWindow = win;

return win;
});

return windowList[windowList.length - 1];
}
import { buildWindowTree } from '../helpers/refererDetectionHelper';

describe('Referer detection', () => {
afterEach(function () {
Expand Down

0 comments on commit 0c71ee2

Please sign in to comment.