// META: script=/resources/testdriver.js
// META: script=/common/utils.js
// META: script=/common/subset-tests.js
// META: script=resources/fledge-util.sub.js
// META: timeout=long
// META: variant=?1-5
// META: variant=?6-10
// META: variant=?11-15
// META: variant=?16-last
"use strict";
// Creates an AuctionConfig with a single component auction.
function createComponentAuctionConfig(uuid, auctionConfigOverrides = {},
deprecatedRenderURLReplacements = {}) {
let componentAuctionConfig = {
seller: window.location.origin,
decisionLogicURL: createDecisionScriptURL(uuid),
interestGroupBuyers: [window.location.origin],
deprecatedRenderURLReplacements: deprecatedRenderURLReplacements
};
return {
seller: window.location.origin,
decisionLogicURL: createDecisionScriptURL(uuid),
interestGroupBuyers: [],
componentAuctions: [componentAuctionConfig],
...auctionConfigOverrides
};
}
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL()});
await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
}, 'Component auction allowed not specified by bidder.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: false })});
await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
}, 'Component auction not allowed by bidder.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true })});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
uuid,
{ scoreAd: "return 5;" });
await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
}, 'Component auction allowed not specified by component seller.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true })});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
uuid,
{ scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
}, 'Component auction not allowed by component seller.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true })});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.decisionLogicURL = createDecisionScriptURL(
uuid,
{ scoreAd: "return 5;" });
await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
}, 'Component auction allowed not specified by top-level seller.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true })});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.interestGroupBuyers = [window.location.origin];
try {
await runBasicFledgeAuction(test, uuid, auctionConfig);
} catch (exception) {
assert_true(exception instanceof TypeError, "did not get expected error: " + exception);
return;
}
throw 'Exception unexpectedly not thrown.'
}, 'Component auction top-level auction cannot have buyers.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true })});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.decisionLogicURL = createDecisionScriptURL(
uuid,
{ scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
}, 'Component auction not allowed by top-level seller.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
// Use distinct origins so can validate all origin parameters passed to worklets.
let bidder = OTHER_ORIGIN1;
let componentSeller = OTHER_ORIGIN2;
let topLevelSeller = OTHER_ORIGIN3;
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
// Note that generateBid() and reportWin() receive slightly different
// "browserSignals" fields - only reportWin() gets "interestGroupOwner", so
// need different sets of checks for them.
await joinCrossOriginInterestGroup(
test, uuid, bidder,
{ biddingLogicURL: createBiddingScriptURL(
{ origin: bidder,
allowComponentAuction: true,
generateBid:
`if (browserSignals.seller !== "${componentSeller}")
throw "Unexpected seller: " + browserSignals.seller;
if (browserSignals.componentSeller !== undefined)
throw "Unexpected componentSeller: " + browserSignals.componentSeller;
if (browserSignals.topLevelSeller !== "${topLevelSeller}")
throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
if (browserSignals.interestGroupOwner !== undefined)
throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
if (browserSignals.topWindowHostname !== "${window.location.hostname}")
throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`,
reportWin:
`if (browserSignals.seller !== "${componentSeller}")
throw "Unexpected seller: " + browserSignals.seller;
if (browserSignals.componentSeller !== undefined)
throw "Unexpected componentSeller: " + browserSignals.componentSeller;
if (browserSignals.topLevelSeller !== "${topLevelSeller}")
throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
if (browserSignals.interestGroupOwner !== "${bidder}")
throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
if (browserSignals.topWindowHostname !== "${window.location.hostname}")
throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;
sendReportTo("${bidderReportURL}");`})});
// Checks for scoreAd() and reportResult() for the component seller.
let componentSellerChecks =
`if (browserSignals.seller !== undefined)
throw "Unexpected seller: " + browserSignals.seller;
if (browserSignals.componentSeller !== undefined)
throw "Unexpected componentSeller: " + browserSignals.componentSeller;
if (browserSignals.topLevelSeller !== "${topLevelSeller}")
throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
if (browserSignals.interestGroupOwner !== "${bidder}")
throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
if (browserSignals.topWindowHostname !== "${window.location.hostname}")
throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
let componentAuctionConfig = {
seller: componentSeller,
decisionLogicURL: createDecisionScriptURL(
uuid,
{ origin: componentSeller,
scoreAd: componentSellerChecks,
reportResult: `${componentSellerChecks}
sendReportTo("${componentSellerReportURL}");` }),
interestGroupBuyers: [bidder]
};
// Checks for scoreAd() and reportResult() for the top-level seller.
let topLevelSellerChecks =
`if (browserSignals.seller !== undefined)
throw "Unexpected seller: " + browserSignals.seller;
if (browserSignals.componentSeller !== "${componentSeller}")
throw "Unexpected componentSeller: " + browserSignals.componentSeller;
if (browserSignals.topLevelSeller !== undefined)
throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
if (browserSignals.interestGroupOwner !== "${bidder}")
throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
if (browserSignals.topWindowHostname !== "${window.location.hostname}")
throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
let auctionConfigOverrides = {
seller: topLevelSeller,
decisionLogicURL: createDecisionScriptURL(
uuid,
{ origin: topLevelSeller,
scoreAd: topLevelSellerChecks,
reportResult: `${topLevelSellerChecks}
sendReportTo("${topLevelSellerReportURL}");` }),
interestGroupBuyers: [],
componentAuctions: [componentAuctionConfig]
};
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Component auction browserSignals origins.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
bid: 5,
reportWin:
`if (browserSignals.bid !== 5)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidderReportURL}");`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected component bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected component bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${componentSellerReportURL}");` });
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected top-level bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected top-level bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Component auction unmodified bid.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
bid: 5,
reportWin:
`if (browserSignals.bid !== 5)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidderReportURL}");`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected component bid: " + bid
return {desirability: 5, allowComponentAuction: true, bid: 4};`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected component bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== 4)
throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${componentSellerReportURL}");` });
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 4)
throw "Unexpected top-level bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 4)
throw "Unexpected top-level bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Component auction modified bid.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
bid: 5,
reportWin:
`if (browserSignals.bid !== 5)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidderReportURL}");`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected component bid: " + bid
return {desirability: 5, allowComponentAuction: true, bid: 5};`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected component bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== 5)
throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${componentSellerReportURL}");` });
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected top-level bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected top-level bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Component auction modified bid to same value.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
bid: 5,
reportWin:
`if (browserSignals.bid !== 5)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidderReportURL}");`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected component bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected component bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${componentSellerReportURL}");` });
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`if (bid !== 5)
throw "Unexpected top-level bid: " + bid
return {desirability: 5, allowComponentAuction: true, bid: 4};`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected top-level bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Top-level auction cannot modify bid.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
reportWin:
`if (browserSignals.desirability !== undefined)
throw "Unexpected desirability: " + browserSignals.desirability;
sendReportTo("${bidderReportURL}");`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 3, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 3)
throw "Unexpected component desirability: " + browserSignals.desirability;
sendReportTo("${componentSellerReportURL}");` });
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 4, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 4)
throw "Unexpected component desirability: " + browserSignals.desirability;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
}, 'Component auction desirability.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
// An auction with two components, each of which has a distinct bidder origin,
// so the bidder in the second component is OTHER_ORIGIN1). The bidder in the
// first component auction bids more and is given the highest of all
// desirability scores in the auction by its component seller, but the
// top-level seller prefers bidder 2.
let bidder1ReportURL = createBidderReportURL(uuid, /*id=*/1);
let bidder2ReportURL = createBidderReportURL(uuid, /*id=*/2);
let componentSeller1ReportURL = createSellerReportURL(uuid, /*id=*/"component1");
let componentSeller2ReportURL = createSellerReportURL(uuid, /*id=*/"component2");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await Promise.all([
joinInterestGroup(
test, uuid,
{ biddingLogicURL: createBiddingScriptURL(
{ bid: 10,
allowComponentAuction: true,
reportWin:
`sendReportTo("${bidder1ReportURL}");`})}),
joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1,
{ biddingLogicURL: createBiddingScriptURL(
{ origin: OTHER_ORIGIN1,
bid: 2,
allowComponentAuction: true,
reportWin:
`if (browserSignals.bid !== 2)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidder2ReportURL}");`})})
]);
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 10, allowComponentAuction: true};`,
reportResult:
`sendReportTo("${componentSeller1ReportURL}");` });
auctionConfig.componentAuctions[1] = {
...auctionConfig.componentAuctions[0],
interestGroupBuyers: [OTHER_ORIGIN1],
decisionLogicURL: createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 1, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 1)
throw "Unexpected component desirability: " + browserSignals.desirability;
sendReportTo("${componentSeller2ReportURL}");` })
}
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 11 - bid, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 9)
throw "Unexpected component desirability: " + browserSignals.desirability;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidder2ReportURL, componentSeller2ReportURL, topLevelSellerReportURL]);
}, 'Component auction desirability two sellers, two bidders.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let renderURL1 = createRenderURL(uuid);
let renderURL2 = createRenderURL(uuid, /*script=*/';');
// The same bidder uses different ads, bids, and reporting URLs for different
// component sellers.
let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/1);
let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/2);
let componentSeller1ReportURL = createSellerReportURL(uuid, /*id=*/"component1");
let componentSeller2ReportURL = createSellerReportURL(uuid, /*id=*/"component2");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
await joinInterestGroup(
test, uuid,
{ ads: [{ renderURL: renderURL1 }, { renderURL: renderURL2 }],
biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
generateBid:
// "auctionSignals" contains the bid and the report URL, to
// make the same bidder behave differently in the two
// auctions.
'return auctionSignals;',
reportWin:
`if (browserSignals.renderURL !== "${renderURL2}")
throw "Wrong winner: " + browserSignals.renderURL;
sendReportTo(auctionSignals.reportURL);`})});
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 10, allowComponentAuction: true};`,
reportResult:
`sendReportTo("${componentSeller1ReportURL}");` });
// "auctionSignals" contains the bid and the report URL, to
// make the same bidder behave differently in the two
// auctions.
auctionConfig.componentAuctions[0].auctionSignals = {
bid: 10,
allowComponentAuction: true,
render: renderURL1,
reportURL: bidderReportURL1
};
auctionConfig.componentAuctions[1] = {
...auctionConfig.componentAuctions[0],
auctionSignals: {
bid: 2,
allowComponentAuction: true,
render: renderURL2,
reportURL: bidderReportURL2
},
decisionLogicURL: createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 1, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 1)
throw "Unexpected component desirability: " + browserSignals.desirability;
if (browserSignals.renderURL !== "${renderURL2}")
throw "Wrong winner: " + browserSignals.renderURL;
sendReportTo("${componentSeller2ReportURL}");` })
}
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd:
`return {desirability: 11 - bid, allowComponentAuction: true};`,
reportResult:
`if (browserSignals.desirability !== 9)
throw "Unexpected component desirability: " + browserSignals.desirability;
if (browserSignals.renderURL !== "${renderURL2}")
throw "Wrong winner: " + browserSignals.renderURL;
sendReportTo("${topLevelSellerReportURL}");` });
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL2, componentSeller2ReportURL, topLevelSellerReportURL]);
}, 'Component auction desirability and renderURL two sellers, one bidder.');
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
// The renderURLs / report URLs for the first/second iterations of the auction.
let renderURL1 = createRenderURL(uuid);
let renderURL2 = createRenderURL(uuid, /*script=*/';');
let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/1);
let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/2);
let seller1ReportURL = createSellerReportURL(uuid, /*id=*/1);
let seller2ReportURL = createSellerReportURL(uuid, /*id=*/2);
await joinInterestGroup(
test, uuid,
{ ads: [{ renderURL: renderURL1 }, { renderURL: renderURL2 }],
biddingLogicURL: createBiddingScriptURL(
{ allowComponentAuction: true,
generateBid:
`// If this is the first recorded win, use "renderURL1"
if (browserSignals.bidCount === 0 &&
browserSignals.prevWinsMs.length === 0) {
return {bid: 2, allowComponentAuction: true, render: "${renderURL1}"};
}
// Otherwise, check that a single bid and win were reported, despite the
// bidder bidding twice in the first auction, once for each component
// auction.
if (browserSignals.bidCount === 1 &&
browserSignals.prevWinsMs.length === 1 &&
typeof browserSignals.prevWinsMs[0][0] === "number" &&
browserSignals.prevWinsMs[0][1].renderURL === "${renderURL1}") {
return {bid: 1, allowComponentAuction: true, render: "${renderURL2}"};
}
throw "Unexpected browserSignals: " + JSON.stringify(browserSignals);`,
reportWin:
`if (browserSignals.renderURL === "${renderURL1}")
sendReportTo("${bidderReportURL1}");
if (browserSignals.renderURL === "${renderURL2}")
sendReportTo("${bidderReportURL2}");`})});
// Auction has two component auctions with different sellers but the same
// single bidder. The first component auction only accepts bids with
// "renderURL1", the second only accepts bids with "renderURL2".
let auctionConfig = createComponentAuctionConfig(uuid);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{ scoreAd: `if (browserSignals.renderURL !== '${renderURL1}')
throw 'Wrong ad';`,
reportResult: `sendReportTo('${seller1ReportURL}');`}
);
auctionConfig.componentAuctions[1] = {
seller: OTHER_ORIGIN1,
interestGroupBuyers: [window.location.origin],
decisionLogicURL: createDecisionScriptURL(
uuid,
{ origin: OTHER_ORIGIN1,
scoreAd: `if (browserSignals.renderURL !== '${renderURL2}')
throw 'Wrong ad';`,
reportResult: `sendReportTo('${seller2ReportURL}');`}
)
};
// In the first auction, the bidder should use "renderURL1", which the first
// component auction allows. `prevWinsMs` and `numBids` should be updated.
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL1, seller1ReportURL]);
// In the second auction, the bidder should use "renderURL2", which the second
// component auction allows. `prevWinsMs` and `numBids` should reflect the updated
// value.
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL1, seller1ReportURL, bidderReportURL2, seller2ReportURL]);
}, `Component auction prevWinsMs and numBids updating in one component seller's auction, read in another's.`);
const makeDeprecatedRenderURLReplacementTest = ({
name,
deprecatedRenderURLReplacements,
}) => {
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let bidderReportURL = createBidderReportURL(uuid);
let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
// These are used within the URLs for deprecatedRenderURLReplacement tests.
const renderURLReplacementsStrings = createStringBeforeAndAfterReplacements(deprecatedRenderURLReplacements);
const beforeReplacementsString = renderURLReplacementsStrings.beforeReplacements;
const afterReplacementsString = renderURLReplacementsStrings.afterReplacements;
const renderURLBeforeReplacements = createTrackerURL(window.location.origin, uuid, 'track_get', beforeReplacementsString);
const renderURLAfterReplacements = createTrackerURL(window.location.origin, uuid, 'track_get', afterReplacementsString);
await joinInterestGroup(
test, uuid,
{
ads: [{ renderURL: renderURLBeforeReplacements }],
biddingLogicURL: createBiddingScriptURL(
{
allowComponentAuction: true,
bid: 5,
reportWin:
`if (browserSignals.bid !== 5)
throw "Unexpected bid: " + browserSignals.bid;
sendReportTo("${bidderReportURL}");`
})
});
let auctionConfig = createComponentAuctionConfig(uuid, {}, deprecatedRenderURLReplacements);
auctionConfig.componentAuctions[0].decisionLogicURL =
createDecisionScriptURL(
uuid,
{
scoreAd:
`if (bid !== 5)
throw "Unexpected component bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected component bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${componentSellerReportURL}");`
});
auctionConfig.decisionLogicURL =
createDecisionScriptURL(
uuid,
{
scoreAd:
`if (bid !== 5)
throw "Unexpected top-level bid: " + bid`,
reportResult:
`if (browserSignals.bid !== 5)
throw "Unexpected top-level bid: " + browserSignals.bid;
if (browserSignals.modifiedBid !== undefined)
throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
sendReportTo("${topLevelSellerReportURL}");`
});
await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
await waitForObservedRequests(
uuid,
[bidderReportURL, componentSellerReportURL, topLevelSellerReportURL, renderURLAfterReplacements]);
}, name);
};
makeDeprecatedRenderURLReplacementTest({
name: 'Replacements with brackets.',
deprecatedRenderURLReplacements: { '${EXAMPLE-MACRO}': 'SSP' }
});
makeDeprecatedRenderURLReplacementTest({
name: 'Replacements with percents.',
deprecatedRenderURLReplacements: { '%%EXAMPLE-MACRO%%': 'SSP' }
});
makeDeprecatedRenderURLReplacementTest({
name: 'Replacements with multiple replacements.',
deprecatedRenderURLReplacements: { '${EXAMPLE-MACRO1}': 'SSP1', '%%EXAMPLE-MACRO2%%': 'SSP2' }
});
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
let deprecatedRenderURLReplacements = { '${EXAMPLE-MACRO1}': 'SSP1', '%%EXAMPLE-MACRO2%%': 'SSP2' };
const renderURLReplacementsStrings = createStringBeforeAndAfterReplacements(deprecatedRenderURLReplacements);
let beforeReplacementsString = renderURLReplacementsStrings.beforeReplacements;
await joinInterestGroup(
test, uuid,
{
ads: [{ renderURL: createTrackerURL(window.location.origin, uuid, 'track_get', beforeReplacementsString) }],
biddingLogicURL: createBiddingScriptURL({allowComponentAuction: true})
});
let auctionConfigOverride = {deprecatedRenderURLReplacements: deprecatedRenderURLReplacements }
let auctionConfig = createComponentAuctionConfig(uuid,/*auctionConfigOverride=*/auctionConfigOverride,
/*deprecatedRenderURLReplacements=*/deprecatedRenderURLReplacements);
auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(uuid);
try {
await runBasicFledgeAuction(test, uuid, auctionConfig);
} catch (exception) {
assert_true(exception instanceof TypeError, "did not get expected error: " + exception);
return;
}
throw 'Exception unexpectedly not thrown.'
}, "deprecatedRenderURLReplacements cause error if passed in top level auction and component auction.");