Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: fix native render when adUnits defines mediaTypes.native.ortb but adapter replies with "legacy" native bid #9638

Merged
merged 2 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/native.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
isNumber,
isPlainObject,
logError,
triggerPixel,
pick
pick,
triggerPixel
} from './utils.js';
import {includes} from './polyfill.js';
import {auctionManager} from './auctionManager.js';
Expand Down Expand Up @@ -385,16 +385,19 @@ export function getNativeTargeting(bid, {index = auctionManager.index} = {}) {
return keyValues;
}

function assetsMessage(data, adObject, keys) {
function assetsMessage(data, adObject, keys, {index = auctionManager.index} = {}) {
const message = {
message: 'assetResponse',
adId: data.adId,
};

const adUnit = index.getAdUnit(adObject);
let nativeResp = adObject.native;

if (adObject.native.ortb) {
message.ortb = adObject.native.ortb;
} else if (adUnit.mediaTypes?.native?.ortb) {
message.ortb = toOrtbNativeResponse(adObject.native, adUnit.nativeOrtbRequest);
}
message.assets = [];

Expand Down Expand Up @@ -698,7 +701,7 @@ export function toOrtbNativeResponse(legacyResponse, ortbRequest) {
}

Object.keys(legacyResponse).filter(key => !!legacyResponse[key]).forEach(key => {
const value = legacyResponse[key];
const value = getAssetValue(legacyResponse[key]);
switch (key) {
// process titles
case 'title':
Expand Down
316 changes: 179 additions & 137 deletions test/spec/native_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import CONSTANTS from 'src/constants.json';
import { stubAuctionIndex } from '../helpers/indexStub.js';
import { convertOrtbRequestToProprietaryNative, fromOrtbNativeRequest } from '../../src/native.js';
import {auctionManager} from '../../src/auctionManager.js';
const utils = require('src/utils');

const bid = {
Expand Down Expand Up @@ -430,158 +431,180 @@ describe('native.js', function () {
sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]);
});

it('creates native asset message', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'assetRequest',
adId: '123',
assets: ['hb_native_body', 'hb_native_image', 'hb_native_linkurl'],
};
describe('native postMessages', () => {
let adUnit;
beforeEach(() => {
adUnit = {};
sinon.stub(auctionManager, 'index').get(() => ({
getAdUnit: () => adUnit
}))
});

it('creates native asset message', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'assetRequest',
adId: '123',
assets: ['hb_native_body', 'hb_native_image', 'hb_native_linkurl'],
};

const message = getAssetMessage(messageRequest, bid);
const message = getAssetMessage(messageRequest, bid);

expect(message.assets.length).to.equal(3);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
expect(message.assets.length).to.equal(3);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
});
});

it('creates native all asset message', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
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);

expect(message.assets.length).to.equal(10);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'icon',
value: bid.native.icon.url,
});
expect(message.assets).to.deep.include({
key: 'cta',
value: bid.native.cta,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
});
expect(message.assets).to.deep.include({
key: 'baz',
value: bid.native.ext.baz,
expect(message.assets.length).to.equal(10);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'icon',
value: bid.native.icon.url,
});
expect(message.assets).to.deep.include({
key: 'cta',
value: bid.native.cta,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
});
expect(message.assets).to.deep.include({
key: 'baz',
value: bid.native.ext.baz,
});
});
});

it('creates native all asset message with only defined fields', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
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);

expect(message.assets.length).to.equal(4);
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
expect(message.assets.length).to.equal(4);
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
});
});
});

it('creates native all asset message with complete format', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
it('creates native all asset message with complete format', function () {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};

const message = getAllAssetsMessage(messageRequest, completeNativeBid);
const message = getAllAssetsMessage(messageRequest, completeNativeBid);

expect(message.assets.length).to.equal(10);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'icon',
value: bid.native.icon.url,
});
expect(message.assets).to.deep.include({
key: 'cta',
value: bid.native.cta,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'privacyLink',
value: ortbBid.native.ortb.privacy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
});
expect(message.assets).to.deep.include({
key: 'baz',
value: bid.native.ext.baz,
expect(message.assets.length).to.equal(10);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body,
});
expect(message.assets).to.deep.include({
key: 'image',
value: bid.native.image.url,
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl,
});
expect(message.assets).to.deep.include({
key: 'title',
value: bid.native.title,
});
expect(message.assets).to.deep.include({
key: 'icon',
value: bid.native.icon.url,
});
expect(message.assets).to.deep.include({
key: 'cta',
value: bid.native.cta,
});
expect(message.assets).to.deep.include({
key: 'sponsoredBy',
value: bid.native.sponsoredBy,
});
expect(message.assets).to.deep.include({
key: 'privacyLink',
value: ortbBid.native.ortb.privacy,
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo,
});
expect(message.assets).to.deep.include({
key: 'baz',
value: bid.native.ext.baz,
});
});
});

it('if necessary, adds ortb response when the request was in ortb', () => {
const messageRequest = {
message: 'Prebid Native',
action: 'allAssetRequest',
adId: '123',
};
adUnit = {mediaTypes: {native: {ortb: ortbRequest}}, nativeOrtbRequest: ortbRequest}
const message = getAllAssetsMessage(messageRequest, bid);
const expected = toOrtbNativeResponse(bid.native, ortbRequest)
expect(message.ortb).to.eql(expected);
})
})

const SAMPLE_ORTB_REQUEST = toOrtbNativeRequest({
title: 'vtitle',
Expand Down Expand Up @@ -1303,5 +1326,24 @@ describe('toOrtbNativeResponse', () => {
text: 'vtitle'
}
})
});

it('should accept objects as legacy assets', () => {
const legacyResponse = {
icon: {
url: 'image-url'
}
}
const request = toOrtbNativeRequest({
icon: {
required: true
}
});
const response = toOrtbNativeResponse(legacyResponse, request);
sinon.assert.match(response.assets[0], {
img: {
url: 'image-url'
}
})
})
})