// META: script=/resources/testdriver.js
// META: script=/common/utils.js
// META: script=resources/fledge-util.js

"use strict;"

// The tests in this file focus on calls to runAdAuction with various
// auctionConfigs.

const makeTest = ({
  // Test name
  name,
  // Expectation function (EXPECT_NULL, etc.)
  expect,
  // Overrides to the auction config.
  auctionConfigOverrides = {},
}) => {
  promise_test(async test => {
    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);
  }, name);
};

// Expect an unsuccessful auction (yielding null).
const EXPECT_NO_WINNER = auctionResult => {
  assert_equals(auctionResult, null, 'Auction unexpected had a winner');
};

// 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; });
};

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: '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_EXCEPTION(TypeError),
  auctionConfigOverrides: { auctionSignals: { sig: BigInt(13) } },
});

makeTest({
  name: 'sellerSignals is invalid as JSON',
  expect: EXPECT_EXCEPTION(TypeError),
  auctionConfigOverrides: { sellerSignals: { sig: BigInt(13) } },
});

makeTest({
  name: 'directFromSellerSignals is invalid',
  expect: EXPECT_EXCEPTION(TypeError),
  auctionConfigOverrides: { directFromSellerSignals: "https://foo:99999999999" },
});

makeTest({
  name: 'directFromSellerSignals is cross-origin with seller',
  expect: EXPECT_EXCEPTION(TypeError),
  auctionConfigOverrides: { directFromSellerSignals: "https://example.com" },
});

makeTest({
  name: 'directFromSellerSignals has nonempty query',
  expect: EXPECT_EXCEPTION(TypeError),
  auctionConfigOverrides: { directFromSellerSignals: window.location.origin + "?foo=bar" },
});

makeTest({
  name: 'perBuyerSignals has invalid URL in a key',
  expect: EXPECT_EXCEPTION(TypeError),
  auctionConfigOverrides: { perBuyerSignals: { "https://foo:99999999999" : {} }},
});

makeTest({
  name: 'perBuyerSignals value is invalid as JSON',
  expect: 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: [],
      },
    ],
  },
});
