',
+ },
};
const targeting = getNativeTargeting(bid, deps(adUnit));
@@ -270,10 +274,12 @@ describe('native.js', function () {
CONSTANTS.NATIVE_KEYS.image,
CONSTANTS.NATIVE_KEYS.icon,
CONSTANTS.NATIVE_KEYS.sponsoredBy,
- CONSTANTS.NATIVE_KEYS.clickUrl
+ CONSTANTS.NATIVE_KEYS.clickUrl,
]);
- expect(bid.native.adTemplate).to.deep.equal('
##hb_native_body##<\/p><\/div>');
+ expect(bid.native.adTemplate).to.deep.equal(
+ '
'
+ );
delete bid.native.adTemplate;
});
@@ -281,7 +287,10 @@ describe('native.js', function () {
fireNativeTrackers({}, bid);
sinon.assert.calledOnce(triggerPixelStub);
sinon.assert.calledWith(triggerPixelStub, bid.native.impressionTrackers[0]);
- sinon.assert.calledWith(insertHtmlIntoIframeStub, bid.native.javascriptTrackers);
+ sinon.assert.calledWith(
+ insertHtmlIntoIframeStub,
+ bid.native.javascriptTrackers
+ );
});
it('fires click trackers', function () {
@@ -291,7 +300,7 @@ describe('native.js', function () {
sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]);
});
- it('creates native asset message', function() {
+ it('creates native asset message', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'assetRequest',
@@ -304,95 +313,169 @@ describe('native.js', function () {
expect(message.assets.length).to.equal(3);
expect(message.assets).to.deep.include({
key: 'body',
- value: bid.native.body
+ value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
- value: bid.native.image.url
+ value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
- value: bid.native.clickUrl
+ value: bid.native.clickUrl,
});
});
- it('creates native all asset message', function() {
+ it('creates native all asset message', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
- const message = getAllAssetsMessage(messageRequest, bid);
+ const message = getAllAssetsMessage(messageRequest, bid, {getNativeReq: () => null});
expect(message.assets.length).to.equal(9);
expect(message.assets).to.deep.include({
key: 'body',
- value: bid.native.body
+ value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
- value: bid.native.image.url
+ value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
- value: bid.native.clickUrl
+ value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
- value: bid.native.title
+ value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'icon',
- value: bid.native.icon.url
+ value: bid.native.icon.url,
});
expect(message.assets).to.deep.include({
key: 'cta',
- value: bid.native.cta
+ value: bid.native.cta,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
- value: bid.native.sponsoredBy
+ value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
- value: bid.native.ext.foo
+ value: bid.native.ext.foo,
});
expect(message.assets).to.deep.include({
key: 'baz',
- value: bid.native.ext.baz
+ value: bid.native.ext.baz,
});
});
- it('creates native all asset message with only defined fields', function() {
+ it('creates native all asset message with only defined fields', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
- const message = getAllAssetsMessage(messageRequest, bidWithUndefinedFields);
+ const message = getAllAssetsMessage(messageRequest, bidWithUndefinedFields, {getNativeReq: () => null});
expect(message.assets.length).to.equal(4);
expect(message.assets).to.deep.include({
key: 'clickUrl',
- value: bid.native.clickUrl
+ value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
- value: bid.native.title
+ value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
- value: bid.native.sponsoredBy
+ value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
- value: bid.native.ext.foo
+ value: bid.native.ext.foo,
});
});
});
+describe('validate native openRTB', function () {
+ it('should validate openRTB request', function () {
+ let openRTBNativeRequest = { assets: [] };
+ // assets array can't be empty
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false);
+ openRTBNativeRequest.assets.push({
+ id: 1.5,
+ required: 1,
+ title: {},
+ });
+
+ // asset.id must be integer
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false);
+ openRTBNativeRequest.assets[0].id = 1;
+ // title must have 'len' property
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false);
+ openRTBNativeRequest.assets[0].title.len = 140;
+ // openRTB request is valid
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(true);
+
+ openRTBNativeRequest.assets.push({
+ id: 2,
+ required: 1,
+ video: {
+ mimes: [],
+ protocols: [],
+ minduration: 50,
+ },
+ });
+ // video asset should have all required properties
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false);
+ openRTBNativeRequest.assets[1].video.maxduration = 60;
+ expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(true);
+ });
+
+ it('should validate openRTB native bid', function () {
+ const openRTBRequest = {
+ assets: [
+ {
+ id: 1,
+ required: 1,
+ },
+ {
+ id: 2,
+ required: 0,
+ },
+ {
+ id: 3,
+ required: 1,
+ },
+ ],
+ };
+ let openRTBBid = {
+ assets: [
+ {
+ id: 1,
+ },
+ {
+ id: 2,
+ },
+ ],
+ };
+
+ // link is missing
+ expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(false);
+ openRTBBid.link = { url: 'www.foo.bar' };
+ // required id == 3 is missing
+ expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(false);
+
+ openRTBBid.assets[1].id = 3;
+ expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(true);
+ });
+});
+
describe('validate native', function () {
const adUnit = {
transactionId: 'test_adunit',
@@ -407,15 +490,15 @@ describe('validate native', function () {
image: {
required: true,
sizes: [150, 50],
- aspect_ratios: [150, 50]
+ aspect_ratios: [150, 50],
},
icon: {
required: true,
- sizes: [50, 50]
+ sizes: [50, 50],
},
- }
- }
- }
+ },
+ },
+ };
let validBid = {
adId: 'abc123',
@@ -424,23 +507,24 @@ describe('validate native', function () {
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
- body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
+ body:
+ 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: {
url: 'http://my.image.file/ad_image.jpg',
height: 75,
- width: 75
+ width: 75,
},
image: {
url: 'http://my.icon.file/ad_icon.jpg',
height: 2250,
- width: 3000
+ width: 3000,
},
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
- javascriptTrackers: '',
- title: 'This is an example Prebid Native creative'
- }
+ javascriptTrackers: '',
+ title: 'This is an example Prebid Native creative',
+ },
};
let noIconDimBid = {
@@ -450,19 +534,20 @@ describe('validate native', function () {
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
- body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
+ body:
+ 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: 'http://my.image.file/ad_image.jpg',
image: {
url: 'http://my.icon.file/ad_icon.jpg',
height: 2250,
- width: 3000
+ width: 3000,
},
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
- javascriptTrackers: '',
- title: 'This is an example Prebid Native creative'
- }
+ javascriptTrackers: '',
+ title: 'This is an example Prebid Native creative',
+ },
};
let noImgDimBid = {
@@ -472,19 +557,20 @@ describe('validate native', function () {
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
- body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
+ body:
+ 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: {
url: 'http://my.image.file/ad_image.jpg',
height: 75,
- width: 75
+ width: 75,
},
image: 'http://my.icon.file/ad_icon.jpg',
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
- javascriptTrackers: '',
- title: 'This is an example Prebid Native creative'
- }
+ javascriptTrackers: '',
+ title: 'This is an example Prebid Native creative',
+ },
};
beforeEach(function () {});
@@ -493,12 +579,446 @@ describe('validate native', function () {
it('should accept bid if no image sizes are defined', function () {
decorateAdUnitsWithNativeParams([adUnit]);
- const index = stubAuctionIndex({adUnits: [adUnit]})
- let result = nativeBidIsValid(validBid, {index});
+ const index = stubAuctionIndex({ adUnits: [adUnit] });
+ let result = nativeBidIsValid(validBid, { index });
expect(result).to.be.true;
- result = nativeBidIsValid(noIconDimBid, {index});
+ result = nativeBidIsValid(noIconDimBid, { index });
expect(result).to.be.true;
- result = nativeBidIsValid(noImgDimBid, {index});
+ result = nativeBidIsValid(noImgDimBid, { index });
expect(result).to.be.true;
});
+
+ it('should convert from old-style native to OpenRTB request', () => {
+ const adUnit = {
+ transactionId: 'test_adunit',
+ mediaTypes: {
+ native: {
+ title: {
+ required: true,
+ },
+ body: {
+ required: true,
+ len: 45
+ },
+ image: {
+ required: true,
+ sizes: [150, 50],
+ aspect_ratios: [{
+ min_width: 150,
+ min_height: 50
+ }]
+ },
+ icon: {
+ required: true,
+ aspect_ratios: [{
+ min_width: 150,
+ min_height: 50
+ }]
+ },
+ address: {},
+ },
+ },
+ };
+
+ const ortb = toOrtbNativeRequest(adUnit.mediaTypes.native);
+ expect(ortb).to.be.a('object');
+ expect(ortb.assets).to.be.a('array');
+
+ // title
+ expect(ortb.assets[0]).to.deep.include({
+ id: 0,
+ required: 1,
+ title: {
+ len: 140
+ }
+ });
+
+ // body => data
+ expect(ortb.assets[1]).to.deep.include({
+ id: 1,
+ required: 1,
+ data: {
+ type: 2,
+ len: 45
+ }
+ });
+
+ // image => image
+ expect(ortb.assets[2]).to.deep.include({
+ id: 2,
+ required: 1,
+ img: {
+ type: 3, // Main Image
+ w: 150,
+ h: 50,
+ }
+ });
+
+ expect(ortb.assets[3]).to.deep.include({
+ id: 3,
+ required: 1,
+ img: {
+ type: 1, // Icon Image
+ wmin: 150,
+ hmin: 50,
+ }
+ });
+
+ expect(ortb.assets[4]).to.deep.include({
+ id: 4,
+ required: 0,
+ data: {
+ type: 9,
+ }
+ });
+ });
+
+ it('should convert from ortb to old-style native request', () => {
+ const openRTBRequest = {
+ 'ver': '1.2',
+ 'context': 2,
+ 'contextsubtype': 20,
+ 'plcmttype': 11,
+ 'plcmtcnt': 1,
+ 'aurlsupport': 0,
+ 'privacy': 1,
+ 'eventrackers': [
+ {
+ 'event': 1,
+ 'methods': [1, 2]
+ },
+ {
+ 'event': 2,
+ 'methods': [1]
+ }
+ ],
+ 'assets': [
+ {
+ 'id': 123,
+ 'required': 1,
+ 'title': {
+ 'len': 140
+ }
+ },
+ {
+ 'id': 128,
+ 'required': 0,
+ 'img': {
+ 'wmin': 836,
+ 'hmin': 627,
+ 'type': 3
+ }
+ },
+ {
+ 'id': 124,
+ 'required': 1,
+ 'img': {
+ 'wmin': 50,
+ 'hmin': 50,
+ 'type': 1
+ }
+ },
+ {
+ 'id': 126,
+ 'required': 1,
+ 'data': {
+ 'type': 1,
+ 'len': 25
+ }
+ },
+ {
+ 'id': 127,
+ 'required': 1,
+ 'data': {
+ 'type': 2,
+ 'len': 140
+ }
+ }
+ ]
+ };
+
+ const oldNativeRequest = fromOrtbNativeRequest(openRTBRequest);
+
+ expect(oldNativeRequest).to.be.a('object');
+ expect(oldNativeRequest.title).to.include({
+ required: true,
+ len: 140
+ });
+
+ expect(oldNativeRequest.image).to.deep.include({
+ required: false,
+ aspect_ratios: {
+ min_width: 836,
+ min_height: 627,
+ ratio_width: 836,
+ ratio_height: 627
+ }
+ });
+
+ expect(oldNativeRequest.icon).to.deep.include({
+ required: true,
+ aspect_ratios: {
+ min_width: 50,
+ min_height: 50,
+ ratio_width: 50,
+ ratio_height: 50
+ }
+ });
+ expect(oldNativeRequest.sponsoredBy).to.include({
+ required: true,
+ len: 25
+ })
+ expect(oldNativeRequest.body).to.include({
+ required: true,
+ len: 140
+ })
+ });
+
+ if (FEATURES.NATIVE) {
+ it('should convert ortb bid requests to proprietary requests', () => {
+ const validBidRequests = [{
+ bidId: 'bidId3',
+ adUnitCode: 'adUnitCode3',
+ transactionId: 'transactionId3',
+ mediaTypes: {
+ banner: {}
+ },
+ params: {
+ publisher: 'publisher2',
+ placement: 'placement3'
+ }
+ }];
+ const resultRequests = convertOrtbRequestToProprietaryNative(validBidRequests);
+ expect(resultRequests).to.be.deep.equals(validBidRequests);
+
+ validBidRequests[0].mediaTypes.native = {
+ ortb: {
+ ver: '1.2',
+ context: 2,
+ contextsubtype: 20,
+ plcmttype: 11,
+ plcmtcnt: 1,
+ aurlsupport: 0,
+ privacy: 1,
+ eventrackers: [
+ {
+ event: 1,
+ methods: [1, 2]
+ },
+ {
+ event: 2,
+ methods: [1]
+ }
+ ],
+ assets: [
+ {
+ id: 123,
+ required: 1,
+ title: {
+ len: 140
+ }
+ },
+ {
+ id: 128,
+ required: 0,
+ img: {
+ wmin: 836,
+ hmin: 627,
+ type: 3
+ }
+ },
+ {
+ id: 124,
+ required: 1,
+ img: {
+ wmin: 50,
+ hmin: 50,
+ type: 1
+ }
+ },
+ {
+ id: 126,
+ required: 1,
+ data: {
+ type: 1,
+ len: 25
+ }
+ },
+ {
+ id: 127,
+ required: 1,
+ data: {
+ type: 2,
+ len: 140
+ }
+ }
+ ]
+ }
+ };
+
+ const resultRequests2 = convertOrtbRequestToProprietaryNative(validBidRequests);
+ expect(resultRequests2[0].mediaTypes.native).to.deep.include({
+ title: {
+ required: true,
+ len: 140
+ },
+ icon: {
+ required: true,
+ aspect_ratios: {
+ min_width: 50,
+ min_height: 50,
+ ratio_width: 50,
+ ratio_height: 50
+ }
+ },
+ sponsoredBy: {
+ required: true,
+ len: 25
+ },
+ body: {
+ required: true,
+ len: 140
+ }
+ });
+ });
+ }
});
+
+describe('legacyPropertiesToOrtbNative', () => {
+ describe('click trakckers', () => {
+ it('should convert clickUrl to link.url', () => {
+ const native = legacyPropertiesToOrtbNative({clickUrl: 'some-url'});
+ expect(native.link.url).to.eql('some-url');
+ });
+ it('should convert single clickTrackers to link.clicktrackers', () => {
+ const native = legacyPropertiesToOrtbNative({clickTrackers: 'some-url'});
+ expect(native.link.clicktrackers).to.eql([
+ 'some-url'
+ ])
+ });
+ it('should convert multiple clickTrackers into link.clicktrackers', () => {
+ const native = legacyPropertiesToOrtbNative({clickTrackers: ['url1', 'url2']});
+ expect(native.link.clicktrackers).to.eql([
+ 'url1',
+ 'url2'
+ ])
+ })
+ });
+ describe('impressionTrackers', () => {
+ it('should convert a single tracker into an eventtracker entry', () => {
+ const native = legacyPropertiesToOrtbNative({impressionTrackers: 'some-url'});
+ expect(native.eventtrackers).to.eql([
+ {
+ event: 1,
+ method: 1,
+ url: 'some-url'
+ }
+ ]);
+ });
+
+ it('should convert an array into corresponding eventtracker entries', () => {
+ const native = legacyPropertiesToOrtbNative({impressionTrackers: ['url1', 'url2']});
+ expect(native.eventtrackers).to.eql([
+ {
+ event: 1,
+ method: 1,
+ url: 'url1'
+ },
+ {
+ event: 1,
+ method: 1,
+ url: 'url2'
+ }
+ ])
+ })
+ });
+ describe('javascriptTrackers', () => {
+ it('should convert a single value into jstracker', () => {
+ const native = legacyPropertiesToOrtbNative({javascriptTrackers: 'some-markup'});
+ expect(native.jstracker).to.eql('some-markup');
+ })
+ it('should merge multiple values into a single jstracker', () => {
+ const native = legacyPropertiesToOrtbNative({javascriptTrackers: ['some-markup', 'some-other-markup']});
+ expect(native.jstracker).to.eql('some-markupsome-other-markup');
+ })
+ });
+});
+
+describe('fireImpressionTrackers', () => {
+ let runMarkup, fetchURL;
+ beforeEach(() => {
+ runMarkup = sinon.stub();
+ fetchURL = sinon.stub();
+ })
+
+ function runTrackers(resp) {
+ fireImpressionTrackers(resp, {runMarkup, fetchURL})
+ }
+
+ it('should run markup in jstracker', () => {
+ runTrackers({
+ jstracker: 'some-markup'
+ });
+ sinon.assert.calledWith(runMarkup, 'some-markup');
+ });
+
+ it('should fetch each url in imptrackers', () => {
+ const urls = ['url1', 'url2'];
+ runTrackers({
+ imptrackers: urls
+ });
+ urls.forEach(url => sinon.assert.calledWith(fetchURL, url));
+ });
+
+ it('should fetch each url in eventtrackers that use the image method', () => {
+ const urls = ['url1', 'url2'];
+ runTrackers({
+ eventtrackers: urls.map(url => ({event: 1, method: 1, url}))
+ });
+ urls.forEach(url => sinon.assert.calledWith(fetchURL, url))
+ });
+
+ it('should load as a script each url in eventtrackers that use the js method', () => {
+ const urls = ['url1', 'url2'];
+ runTrackers({
+ eventtrackers: urls.map(url => ({event: 1, method: 2, url}))
+ });
+ urls.forEach(url => sinon.assert.calledWith(runMarkup, sinon.match(`script async src="${url}"`)))
+ });
+
+ it('should not fire trackers that are not impression trakcers', () => {
+ runTrackers({
+ link: {
+ clicktrackers: ['click-url']
+ },
+ eventtrackers: [{
+ event: 2, // not imp
+ method: 1,
+ url: 'some-url'
+ }]
+ });
+ sinon.assert.notCalled(fetchURL);
+ sinon.assert.notCalled(runMarkup);
+ })
+})
+
+describe('fireClickTrackers', () => {
+ let fetchURL;
+ beforeEach(() => {
+ fetchURL = sinon.stub();
+ });
+
+ function runTrackers(resp) {
+ fireClickTrackers(resp, {fetchURL});
+ }
+
+ it('should load each URL in link.clicktrackers', () => {
+ const urls = ['url1', 'url2'];
+ runTrackers({
+ link: {
+ clicktrackers: urls
+ }
+ });
+ urls.forEach(url => sinon.assert.calledWith(fetchURL, url));
+ })
+})
diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js
index be68fc03765..c040bba4eec 100644
--- a/test/spec/unit/core/bidderFactory_spec.js
+++ b/test/spec/unit/core/bidderFactory_spec.js
@@ -12,6 +12,7 @@ import {hook} from '../../../../src/hook.js';
import {auctionManager} from '../../../../src/auctionManager.js';
import {stubAuctionIndex} from '../../../helpers/indexStub.js';
import { bidderSettings } from '../../../../src/bidderSettings.js';
+import {decorateAdUnitsWithNativeParams} from '../../../../src/native.js';
const CODE = 'sampleBidder';
const MOCK_BIDS_REQUEST = {
@@ -39,6 +40,10 @@ function onTimelyResponseStub() {
}
+before(() => {
+ hook.ready();
+});
+
let wrappedCallback = config.callbackWithBidder(CODE);
describe('bidders created by newBidder', function () {
@@ -47,10 +52,6 @@ describe('bidders created by newBidder', function () {
let addBidResponseStub;
let doneStub;
- before(() => {
- hook.ready();
- });
-
beforeEach(function () {
spec = {
code: CODE,
@@ -882,6 +883,7 @@ describe('validate bid response: ', function () {
title: {'required': true},
}
}]
+ decorateAdUnitsWithNativeParams(adUnits);
let bidRequest = {
bids: [{
bidId: '1',
@@ -923,6 +925,7 @@ describe('validate bid response: ', function () {
title: {'required': true},
},
}];
+ decorateAdUnitsWithNativeParams(adUnits);
let bidRequest = {
bids: [{
bidId: '1',
@@ -952,7 +955,7 @@ describe('validate bid response: ', function () {
bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
expect(addBidResponseStub.calledOnce).to.equal(false);
- expect(logErrorSpy.callCount).to.equal(1);
+ expect(logErrorSpy.calledWithMatch('Ignoring bid: Native bid missing some required properties.')).to.equal(true);
});
}
diff --git a/test/spec/unit/core/storageManager_spec.js b/test/spec/unit/core/storageManager_spec.js
index dacde5491b7..cb38aed9e47 100644
--- a/test/spec/unit/core/storageManager_spec.js
+++ b/test/spec/unit/core/storageManager_spec.js
@@ -3,7 +3,7 @@ import {
getCoreStorageManager,
storageCallbacks,
getStorageManager,
- newStorageManager
+ newStorageManager, validateStorageEnforcement
} from 'src/storageManager.js';
import { config } from 'src/config.js';
import * as utils from 'src/utils.js';
@@ -55,6 +55,33 @@ describe('storage manager', function() {
deviceAccessSpy.restore();
});
+ describe(`core storage`, () => {
+ let storage, validateHook;
+
+ beforeEach(() => {
+ storage = getCoreStorageManager();
+ validateHook = sinon.stub().callsFake(function (next, ...args) {
+ next.apply(this, args);
+ });
+ validateStorageEnforcement.before(validateHook, 99);
+ });
+
+ afterEach(() => {
+ validateStorageEnforcement.getHooks({hook: validateHook}).remove();
+ config.resetConfig();
+ })
+
+ it('should respect (vendorless) consent enforcement', () => {
+ storage.localStorageIsEnabled();
+ expect(validateHook.args[0][1]).to.eql(true); // isVendorless should be set to true
+ });
+
+ it('should respect the deviceAccess flag', () => {
+ config.setConfig({deviceAccess: false});
+ expect(storage.localStorageIsEnabled()).to.be.false
+ })
+ })
+
describe('localstorage forbidden access in 3rd-party context', function() {
let errorLogSpy;
let originalLocalStorage;
diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js
index ca646743147..3cee2b6b679 100644
--- a/test/spec/unit/pbjs_api_spec.js
+++ b/test/spec/unit/pbjs_api_spec.js
@@ -218,6 +218,51 @@ describe('Unit: Prebid Module', function () {
auctionManager.clearAllAuctions();
});
+ describe('and global adUnits', () => {
+ const startingAdUnits = [
+ {
+ code: 'one',
+ },
+ {
+ code: 'two',
+ }
+ ];
+ let actualAdUnits, hookRan, done;
+
+ function deferringHook(next, req) {
+ setTimeout(() => {
+ actualAdUnits = req.adUnits || $$PREBID_GLOBAL$$.adUnits;
+ done();
+ });
+ }
+
+ beforeEach(() => {
+ $$PREBID_GLOBAL$$.requestBids.before(deferringHook, 99);
+ $$PREBID_GLOBAL$$.adUnits.splice(0, $$PREBID_GLOBAL$$.adUnits.length, ...startingAdUnits);
+ hookRan = new Promise((resolve) => {
+ done = resolve;
+ });
+ });
+
+ afterEach(() => {
+ $$PREBID_GLOBAL$$.requestBids.getHooks({hook: deferringHook}).remove();
+ $$PREBID_GLOBAL$$.adUnits.splice(0, $$PREBID_GLOBAL$$.adUnits.length);
+ })
+
+ Object.entries({
+ 'addAdUnits': (g) => g.addAdUnits({code: 'three'}),
+ 'removeAdUnit': (g) => g.removeAdUnit('one')
+ }).forEach(([method, op]) => {
+ it(`once called, should not be affected by ${method}`, () => {
+ $$PREBID_GLOBAL$$.requestBids({});
+ op($$PREBID_GLOBAL$$);
+ return hookRan.then(() => {
+ expect(actualAdUnits).to.eql(startingAdUnits);
+ })
+ });
+ });
+ });
+
describe('getAdserverTargetingForAdUnitCodeStr', function () {
beforeEach(function () {
resetAuction();
@@ -2331,14 +2376,47 @@ describe('Unit: Prebid Module', function () {
$$PREBID_GLOBAL$$.requestBids({adUnits});
const spyArgs = adapterManager.callBids.getCall(0);
const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams;
- expect(nativeRequest).to.deep.equal({
- image: {required: true},
- title: {required: true},
- sponsoredBy: {required: true},
- clickUrl: {required: true},
- body: {required: false},
- icon: {required: false},
- });
+ expect(nativeRequest.ortb.assets).to.deep.equal([
+ {
+ required: 1,
+ id: 1,
+ img: {
+ type: 3,
+ wmin: 100,
+ hmin: 100,
+ }
+ },
+ {
+ required: 1,
+ id: 2,
+ title: {
+ len: 140,
+ }
+ },
+ {
+ required: 1,
+ id: 3,
+ data: {
+ type: 1,
+ }
+ },
+ {
+ required: 0,
+ id: 4,
+ data: {
+ type: 2,
+ }
+ },
+ {
+ required: 0,
+ id: 5,
+ img: {
+ type: 1,
+ wmin: 20,
+ hmin: 20,
+ }
+ },
+ ]);
resetAuction();
});
});
diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js
index 39fa9b9250f..7d5f9af35dd 100644
--- a/test/spec/unit/secureCreatives_spec.js
+++ b/test/spec/unit/secureCreatives_spec.js
@@ -1,7 +1,6 @@
import {
_sendAdToCreative, getReplier, receiveMessage
} from 'src/secureCreatives.js';
-import * as secureCreatives from 'src/secureCreatives.js';
import * as utils from 'src/utils.js';
import {getAdUnits, getBidRequests, getBidResponses} from 'test/fixtures/fixtures.js';
import {auctionManager} from 'src/auctionManager.js';
@@ -164,6 +163,7 @@ describe('secureCreatives', () => {
stubGetAllAssetsMessage.restore();
stubEmit.restore();
resetAuction();
+ adResponse.adId = bidId;
});
describe('Prebid Request', function() {
@@ -336,60 +336,17 @@ describe('secureCreatives', () => {
sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse);
sinon.assert.calledOnce(ev.source.postMessage);
sinon.assert.notCalled(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER);
- });
-
- it('Prebid native should allow stale rendering without config', function () {
- pushBidResponseToAuction({});
-
- const data = {
- adId: bidId,
- message: 'Prebid Native',
- action: 'allAssetRequest'
- };
-
- const ev = makeEvent({
- data: JSON.stringify(data),
- source: {
- postMessage: sinon.stub()
- },
- origin: 'any origin'
- });
-
- receiveMessage(ev);
-
- sinon.assert.neverCalledWith(spyLogWarn, warning);
- sinon.assert.calledOnce(stubGetAllAssetsMessage);
- sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse);
- sinon.assert.calledOnce(ev.source.postMessage);
- sinon.assert.notCalled(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER);
-
- resetHistories(ev.source.postMessage);
-
- receiveMessage(ev);
-
- sinon.assert.neverCalledWith(spyLogWarn, warning);
- sinon.assert.calledOnce(stubGetAllAssetsMessage);
- sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse);
- sinon.assert.calledOnce(ev.source.postMessage);
- sinon.assert.notCalled(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
+ sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse);
+ sinon.assert.calledOnce(spyAddWinningBid);
sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER);
});
- it('Prebid native should allow stale rendering with config', function () {
- configObj.setConfig({'auctionOptions': {'suppressStaleRender': true}});
-
- pushBidResponseToAuction({});
+ it('Prebid native should not fire BID_WON when receiveMessage is called more than once', () => {
+ let adId = 3;
+ pushBidResponseToAuction({ adId });
const data = {
- adId: bidId,
+ adId: adId,
message: 'Prebid Native',
action: 'allAssetRequest'
};
@@ -403,37 +360,18 @@ describe('secureCreatives', () => {
});
receiveMessage(ev);
-
- sinon.assert.neverCalledWith(spyLogWarn, warning);
- sinon.assert.calledOnce(stubGetAllAssetsMessage);
- sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse);
- sinon.assert.calledOnce(ev.source.postMessage);
- sinon.assert.notCalled(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER);
-
- resetHistories(ev.source.postMessage);
+ sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse);
receiveMessage(ev);
-
- sinon.assert.neverCalledWith(spyLogWarn, warning);
- sinon.assert.calledOnce(stubGetAllAssetsMessage);
- sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse);
- sinon.assert.calledOnce(ev.source.postMessage);
- sinon.assert.notCalled(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER);
-
- configObj.setConfig({'auctionOptions': {}});
+ stubEmit.withArgs(CONSTANTS.EVENTS.BID_WON, adResponse).calledOnce;
});
it('Prebid native should fire trackers', function () {
- pushBidResponseToAuction({});
+ let adId = 2;
+ pushBidResponseToAuction({adId});
const data = {
- adId: bidId,
+ adId: adId,
message: 'Prebid Native',
action: 'click',
};
@@ -450,8 +388,8 @@ describe('secureCreatives', () => {
sinon.assert.neverCalledWith(spyLogWarn, warning);
sinon.assert.calledOnce(stubFireNativeTrackers);
- sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
- sinon.assert.notCalled(spyAddWinningBid);
+ sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse);
+ sinon.assert.calledOnce(spyAddWinningBid);
resetHistories(ev.source.postMessage);
@@ -461,8 +399,8 @@ describe('secureCreatives', () => {
sinon.assert.neverCalledWith(spyLogWarn, warning);
sinon.assert.calledOnce(stubFireNativeTrackers);
- sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse);
- sinon.assert.calledOnce(spyAddWinningBid);
+ sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON);
+ sinon.assert.notCalled(spyAddWinningBid);
expect(adResponse).to.have.property('status', CONSTANTS.BID_STATUS.RENDERED);
});
diff --git a/test/test_deps.js b/test/test_deps.js
index 77fbad93e1c..35713106f8c 100644
--- a/test/test_deps.js
+++ b/test/test_deps.js
@@ -4,6 +4,7 @@ window.process = {
}
};
+require('test/helpers/consentData.js');
require('test/helpers/prebidGlobal.js');
require('test/mocks/adloaderStub.js');
require('test/mocks/xhr.js');