| // META: script=/resources/testdriver.js |
| // META: script=/common/utils.js |
| // META: script=resources/fledge-util.sub.js |
| // META: script=/common/subset-tests.js |
| // META: timeout=long |
| // META: variant=?1-5 |
| // META: variant=?6-10 |
| // META: variant=?11-15 |
| // META: variant=?16-20 |
| // META: variant=?21-25 |
| // META: variant=?26-30 |
| // META: variant=?31-35 |
| // META: variant=?36-40 |
| // META: variant=?40-45 |
| // META: variant=?46-50 |
| // META: variant=?51-55 |
| // META: variant=?56-60 |
| // META: variant=?61-last |
| |
| "use strict;" |
| |
| // The tests in this file focus on calls to runAdAuction with various |
| // auctionConfigs. |
| |
| // We handle promise rejections ourselves. |
| setup({ allow_uncaught_exception: true }); |
| |
| // Helper for when we expect it to happen. |
| const interceptUnhandledRejection = () => { |
| let invokePromiseResolved; |
| let eventHandler = event => { |
| event.preventDefault(); |
| invokePromiseResolved(event.reason); |
| } |
| window.addEventListener("unhandledrejection", eventHandler, {once: true}); |
| return new Promise((resolved) => { |
| invokePromiseResolved = resolved; |
| }); |
| } |
| |
| // Helper for when we expect it to not happen. This relies on the event |
| // dispatching being sync. |
| const unexpectedUnhandledRejection = () => { |
| let o = { sawError : false } |
| window.addEventListener("unhandledrejection", event => { |
| o.sawError = true; |
| }, {once: true}); |
| return o; |
| } |
| |
| const makeTest = ({ |
| // Test name |
| name, |
| // Expectation function (EXPECT_NULL, etc.) |
| expect, |
| // Overrides to the auction config. |
| auctionConfigOverrides = {}, |
| // Expectation for a promise error. |
| expectPromiseError, |
| }) => { |
| subsetTest(promise_test, async test => { |
| let waitPromiseError, dontExpectPromiseError; |
| if (expectPromiseError) { |
| waitPromiseError = interceptUnhandledRejection(); |
| } else { |
| dontExpectPromiseError = unexpectedUnhandledRejection(); |
| } |
| |
| const uuid = generateUuid(test); |
| // Join an interest group so the auction actually runs. |
| await joinInterestGroup(test, uuid); |
| let auctionResult; |
| try { |
| auctionResult = await runBasicFledgeAuction(test, uuid, auctionConfigOverrides); |
| } catch (e) { |
| auctionResult = e; |
| } |
| expect(auctionResult); |
| |
| if (expectPromiseError) { |
| expectPromiseError(await waitPromiseError); |
| } else { |
| assert_false(dontExpectPromiseError.sawError, |
| "Should not see a promise error"); |
| } |
| }, name); |
| }; |
| |
| // Expect an unsuccessful auction (yielding null). |
| const EXPECT_NO_WINNER = auctionResult => { |
| assert_equals(auctionResult, null, 'Auction unexpected had a winner'); |
| }; |
| |
| // Expect a winner (FencedFrameConfig). |
| const EXPECT_WINNER = |
| auctionResult => { |
| assert_true( |
| auctionResult instanceof FencedFrameConfig, |
| 'Auction did not return expected FencedFrameConfig'); |
| } |
| |
| // Expect an exception of the given type. |
| const EXPECT_EXCEPTION = exceptionType => auctionResult => { |
| assert_not_equals(auctionResult, null, "got null instead of expected error"); |
| assert_true(auctionResult instanceof Error, "did not get expected error: " + auctionResult); |
| assert_throws_js(exceptionType, () => { throw auctionResult; }); |
| }; |
| |
| const EXPECT_PROMISE_ERROR = auctionResult => { |
| assert_not_equals(auctionResult, null, "got null instead of expected error"); |
| assert_true(auctionResult instanceof TypeError, |
| "did not get expected error type: " + auctionResult); |
| } |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements without end bracket is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'${No_End_Bracket': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements without percents and brackets.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'No_Wrapper': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements without dollar sign.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'{No_Dollar_Sign}': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements without start bracket is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'$No_Start_Bracket}': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements mix and match is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'${Bracket_And_Percent%%': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements missing start percent is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%Missing_Start_Percents%%': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements single percents is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%Single_Percents%': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'deprecatedRenderURLReplacements without end percents is invalid.', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%%No_End_Percents': 'SSP'}} |
| }); |
| |
| makeTest({ |
| name: 'no buyers => no winners', |
| expect: EXPECT_NO_WINNER, |
| auctionConfigOverrides: {interestGroupBuyers: []}, |
| }); |
| |
| makeTest({ |
| name: 'seller is not an https URL', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {seller: "ftp://not-https"}, |
| }); |
| |
| makeTest({ |
| name: 'decisionLogicURL is invalid', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { decisionLogicURL: "https://foo:99999999999" }, |
| }); |
| |
| makeTest({ |
| name: 'decisionLogicURL is cross-origin with seller', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { decisionLogicURL: "https://example.com" }, |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL is invalid', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { trustedScoringSignalsURL: "https://foo:99999999999" }, |
| }); |
| |
| makeTest({ |
| name: 'valid trustedScoringSignalsURL', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: |
| {trustedScoringSignalsURL: window.location.origin + '/resource.json'} |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL should not have a fragment', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: |
| {trustedScoringSignalsURL: window.location.origin + '/resource.json#foo'} |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL with an empty fragment is not OK', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: |
| {trustedScoringSignalsURL: window.location.origin + '/resource.json#'} |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL should not have a query', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: |
| {trustedScoringSignalsURL: window.location.origin + '/resource.json?foo'} |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL with an empty query is not OK', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: |
| {trustedScoringSignalsURL: window.location.origin + '/resource.json?'} |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL should not have embedded credentials', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| trustedScoringSignalsURL: (window.location.origin + '/resource.json') |
| .replace('https://', 'https://user:pass@') |
| } |
| }); |
| |
| makeTest({ |
| name: 'trustedScoringSignalsURL is cross-origin with seller', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { trustedScoringSignalsURL: "https://example.com" }, |
| }); |
| |
| makeTest({ |
| name: 'interestGroupBuyer is invalid', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { interestGroupBuyers: ["https://foo:99999999999"] }, |
| }); |
| |
| makeTest({ |
| name: 'interestGroupBuyer is not https', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { interestGroupBuyers: ["http://example.com"] }, |
| }); |
| |
| makeTest({ |
| name: 'only one interestGroupBuyer is invalid', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| interestGroupBuyers: ["https://example.com", "https://foo:99999999999"], |
| }, |
| }); |
| |
| makeTest({ |
| name: 'only one interestGroupBuyer is not https', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| interestGroupBuyers: ["https://example.com", "http://example.com"], |
| }, |
| }); |
| |
| makeTest({ |
| name: 'auctionSignals is invalid as JSON', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { auctionSignals: { sig: BigInt(13) } }, |
| }); |
| |
| makeTest({ |
| name: 'sellerSignals is invalid as JSON', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { sellerSignals: { sig: BigInt(13) } }, |
| }); |
| |
| makeTest({ |
| name: 'directFromSellerSignals is invalid', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { directFromSellerSignals: "https://foo:99999999999" }, |
| }); |
| |
| makeTest({ |
| name: 'directFromSellerSignals is cross-origin with seller', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { directFromSellerSignals: "https://example.com" }, |
| }); |
| |
| makeTest({ |
| name: 'directFromSellerSignals has nonempty query', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { directFromSellerSignals: window.location.origin + "?foo=bar" }, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerSignals has invalid URL in a key', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { perBuyerSignals: { "https://foo:99999999999" : {} }}, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerSignals value is invalid as JSON', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| perBuyerSignals: { "https://example.com" : { sig: BigInt(1) }, |
| }}, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerGroupLimits has invalid URL in a key', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { perBuyerGroupLimits: { "https://foo:99999999999" : 5 }}, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerExperimentGroupIds has invalid URL in a key', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { perBuyerExperimentGroupIds: { "https://foo:99999999999" : 11 }}, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerPrioritySignals has invalid URL in a key', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| perBuyerPrioritySignals: { "https://foo:99999999999" : { sig: 2.5} }, |
| }, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerPrioritySignals has a value with a key with prefix "browserSignals"', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| perBuyerPrioritySignals: { "https://example.com" : { "browserSignals.foo" : true } }, |
| }, |
| }); |
| |
| makeTest({ |
| name: 'component auctions are not allowed within component auctions', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| interestGroupBuyers: undefined, |
| componentAuctions: [ |
| { |
| seller: window.location.origin, |
| decisionLogicURL: window.location.origin, |
| interestGroupBuyers: undefined, |
| componentAuctions: [ |
| { |
| seller: window.location.origin, |
| decisionLogicURL: window.location.origin, |
| } |
| ], |
| }, |
| ], |
| }, |
| }); |
| |
| makeTest({ |
| name: 'component auctions are not allowed with interestGroupBuyers', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: { |
| interestGroupBuyers: ["https://example.com"], |
| componentAuctions: [ |
| { |
| seller: window.location.origin, |
| decisionLogicURL: window.location.origin, |
| interestGroupBuyers: [], |
| }, |
| ], |
| }, |
| }); |
| |
| makeTest({ |
| name: 'perBuyerCurrencies with invalid currency', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerCurrencies: {'*': 'Dollars'}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerCurrencies with invalid currency map key', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerCurrencies: {'example': 'USD'}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerCurrencies with non-https currency map key', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerCurrencies: {'http://example.org/': 'USD'}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerCurrencies not convertible to dictionary', |
| expect: EXPECT_PROMISE_ERROR, |
| expectPromiseError: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerCurrencies: 123} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize has no width', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize has no height', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize width not a number', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '10 0', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize height not a number', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '100', height: '10 0'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize 0', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '0', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize space before units', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '100 px', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize leading 0', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '0100', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize invalid unit type', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '100furlongs', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'requestedSize hexideximal', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: {width: '0x100', height: '100'}} |
| }); |
| |
| makeTest({ |
| name: 'Empty allSlotsRequestedSizes', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {allSlotsRequestedSizes: []} |
| }); |
| |
| makeTest({ |
| name: 'allSlotsRequestedSizes without matching value in requestedSize', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {requestedSize: |
| {width: '100', height: '100'}, |
| allSlotsRequestedSizes: |
| [{width: '100', height: '101'}]} |
| }); |
| |
| makeTest({ |
| name: 'allSlotsRequestedSizes has duplicate values', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {allSlotsRequestedSizes: |
| [{width: '100', height: '100'}, |
| {width: '100', height: '100'}]} |
| }); |
| |
| makeTest({ |
| name: 'allSlotsRequestedSizes has invalid value', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {allSlotsRequestedSizes: |
| [{width: '100', height: '100'}, |
| {width: '200furlongs', height: '200'}]} |
| }); |
| |
| makeTest({ |
| name: 'sellerRealTimeReportingConfig has default local reporting type', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: {sellerRealTimeReportingConfig: |
| {type: 'default-local-reporting'}} |
| }); |
| |
| makeTest({ |
| name: 'sellerRealTimeReportingConfig has no type', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {sellerRealTimeReportingConfig: |
| {notType: 'default-local-reporting'}} |
| }); |
| |
| makeTest({ |
| name: 'sellerRealTimeReportingConfig has unknown type', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: {sellerRealTimeReportingConfig: {type: 'unknown type'}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerRealTimeReportingConfig', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: {perBuyerRealTimeReportingConfig: |
| {"https://example.com": {type: 'default-local-reporting'}}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerRealTimeReportingConfig has no entry', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: {perBuyerRealTimeReportingConfig: {}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerRealTimeReportingConfig has invalid buyer', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerRealTimeReportingConfig: |
| {"http://example.com": {type: 'default-local-reporting'}}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerRealTimeReportingConfig has no type', |
| expect: EXPECT_EXCEPTION(TypeError), |
| auctionConfigOverrides: {perBuyerRealTimeReportingConfig: |
| {"https://example.com": {notType: 'default-local-reporting'}}} |
| }); |
| |
| makeTest({ |
| name: 'perBuyerRealTimeReportingConfig has unknown type', |
| expect: EXPECT_WINNER, |
| auctionConfigOverrides: {perBuyerRealTimeReportingConfig: |
| {"https://example.com": {type: 'unknown type'}}} |
| }); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // The renderURL / report URLs for the first/second iterations of the auction. |
| let renderURL = createRenderURL(uuid); |
| let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/ 1); |
| let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/ 2); |
| let bidderDebugReportURL = |
| createBidderReportURL(uuid, /*id=*/ 'forDebuggingOnly'); |
| let sellerReportURL1 = createSellerReportURL(uuid, /*id=*/ 1); |
| let sellerReportURL2 = createSellerReportURL(uuid, /*id=*/ 2); |
| let sellerDebugReportURL = |
| createSellerReportURL(uuid, /*id=*/ 'forDebuggingOnly'); |
| |
| // reportWin() sends "bidderReportURL1" if |
| // browserSignals.forDebuggingOnlyInCooldownOrLockout is true, |
| // "bidderReportURL2" otherwise. |
| await joinInterestGroup(test, uuid, { |
| ads: [{renderURL: renderURL}], |
| biddingLogicURL: createBiddingScriptURL({ |
| generateBid: ` |
| forDebuggingOnly.reportAdAuctionWin('${bidderDebugReportURL}'); |
| if (!browserSignals.hasOwnProperty( |
| 'forDebuggingOnlyInCooldownOrLockout')) { |
| throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals"; |
| } |
| let bid = browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2; |
| return {bid: bid, render: '${renderURL}'};`, |
| reportWin: ` |
| if (browserSignals.bid === 1) |
| sendReportTo('${bidderReportURL1}'); |
| if (browserSignals.bid === 2) |
| sendReportTo('${bidderReportURL2}');` |
| |
| }) |
| }); |
| |
| // reportResult() sends "sellerReportURL1" if |
| // browserSignals.forDebuggingOnlyInCooldownOrLockout in scoreAd() is true, |
| // "sellerReportURL2" otherwise. |
| const auctionConfigOverrides = { |
| decisionLogicURL: createDecisionScriptURL(uuid, { |
| scoreAd: ` |
| forDebuggingOnly.reportAdAuctionWin('${sellerDebugReportURL}'); |
| if (!browserSignals.hasOwnProperty( |
| 'forDebuggingOnlyInCooldownOrLockout')) { |
| throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals"; |
| } |
| let desirability = |
| browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2; |
| return {desirability: desirability};`, |
| reportResult: ` |
| if (browserSignals.desirability === 1) |
| sendReportTo('${sellerReportURL1}'); |
| if (browserSignals.desirability === 2) |
| sendReportTo('${sellerReportURL2}');` |
| }) |
| }; |
| |
| // In the first auction, browserSignals.forDebuggingOnlyInCooldownOrLockout in |
| // generateBid() and scoreAd() should both be false. After the auction, |
| // lockout and cooldowns should be updated. |
| await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); |
| await waitForObservedRequestsIgnoreDebugOnlyReports( |
| uuid, [bidderReportURL2, sellerReportURL2]); |
| |
| // In the second auction, browserSignals.forDebuggingOnlyInCooldownOrLockout |
| // in generateBid() and scoreAd() should both be true, since both the buyer |
| // and seller called forDebuggingOnly API in the first auction, so they are in |
| // cooldowns at least (and also in lockout if a debug report is allowed to be |
| // sent). |
| await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); |
| await waitForObservedRequestsIgnoreDebugOnlyReports( |
| uuid, |
| [bidderReportURL2, sellerReportURL2, bidderReportURL1, sellerReportURL1]); |
| }, `forDebuggingOnly lockout and cooldowns updating in one auction, read in another's.`); |