<!DOCTYPE html>
<meta charset="utf-8">
<title>Tests for providing `additionalLineItems` as part of `ApplePayModifier`.</title>
<script src="/js-test-resources/ui-helper.js"></script>
<script src="/resources/payment-request.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
setup({ explicit_done: true, explicit_timeout: true });

const immediateLabel = "Immediate Label";
const immediateAmount = "20.00";
const recurringLabel = "Recurring Label";
const recurringAmount = "30.00";
const recurringPaymentStartDate = new Date(0);
const recurringPaymentIntervalUnit = "year";
const recurringPaymentIntervalCount = 10;
const recurringPaymentEndDate = new Date(1);
const deferredLabel = "Deferred Label";
const deferredPaymentDate = new Date(2);
const deferredAmount = "40.00";

function validPaymentDetailsWithModifierThatHasLineItems(additionalLineItems) {
    let details = validPaymentDetails();
    delete details.displayItems;
    if (additionalLineItems)
        details.modifiers = [ { supportedMethods: "https://apple.com/apple-pay", data: { additionalLineItems } } ];
    return details;
}

function testPaymentItemData(description, {additionalLineItems, expectedLineItems}) {
    user_activation_test(async (test) => {
        let request = new PaymentRequest([validPaymentMethod()], validPaymentDetailsWithModifierThatHasLineItems(additionalLineItems));
        request.addEventListener("merchantvalidation", (event) => {
            event.complete({ });
        });
        request.addEventListener("shippingaddresschange", (event) => {
            event.updateWith({ });
            internals.mockPaymentCoordinator.acceptPayment();
        });

        let response = await request.show();

        let actualLineItems = internals.mockPaymentCoordinator.lineItems;
        assert_equals(actualLineItems.length, expectedLineItems.length, `check that there are ${expectedLineItems.length} line items`);
        for (let i = 0; i < actualLineItems.length; ++i) {
            let actualLineItem = actualLineItems[i];
            let expectedLineItem = expectedLineItems[i];

            assert_equals(actualLineItem.label, expectedLineItem.label, `check that the \`label\` matches for line item ${i}`);
            assert_equals(actualLineItem.amount, expectedLineItem.amount, `check that the \`amount\` matches for line item ${i}`);
            assert_equals(actualLineItem.paymentTiming, expectedLineItem.paymentTiming, `check that the \`paymentTiming\` matches for line item ${i}`);
            assert_equals(actualLineItem.recurringPaymentStartDate?.getTime(), expectedLineItem.recurringPaymentStartDate?.getTime(), `check that the \`recurringPaymentStartDate\` matches for line item ${i}`);
            assert_equals(actualLineItem.recurringPaymentIntervalUnit, expectedLineItem.recurringPaymentIntervalUnit, `check that the \`recurringPaymentIntervalUnit\` matches for line item ${i}`);
            assert_equals(actualLineItem.recurringPaymentIntervalCount, expectedLineItem.recurringPaymentIntervalCount, `check that the \`recurringPaymentIntervalCount\` matches for line item ${i}`);
            assert_equals(actualLineItem.recurringPaymentEndDate?.getTime(), expectedLineItem.recurringPaymentEndDate?.getTime(), `check that the \`recurringPaymentEndDate\` matches for line item ${i}`);
            assert_equals(actualLineItem.deferredPaymentDate?.getTime(), expectedLineItem.deferredPaymentDate?.getTime(), `check that the \`deferredPaymentDate\` matches for line item ${i}`);
        }

        await response.complete("success");
    }, description);
}

testPaymentItemData("Should not have any line items if `additionalLineItems` is not provided.", {
    additionalLineItems: undefined,
    expectedLineItems: [ ],
});
testPaymentItemData("Should not have any line items if `additionalLineItems` is empty.", {
    additionalLineItems: [ ],
    expectedLineItems: [ ],
});

testPaymentItemData("The default value of `paymentTiming` should be `\"immediate\"`.", {
    additionalLineItems: [ { label: immediateLabel, amount: immediateAmount } ],
    expectedLineItems: [ { label: immediateLabel, amount: immediateAmount, paymentTiming: "immediate", recurringPaymentIntervalUnit: "month", recurringPaymentIntervalCount: 1 } ],
});

testPaymentItemData("Should not have a default value for `recurringPaymentIntervalStartDate` and `recurringPaymentIntervalEndDate` when `paymentTiming` is `\"recurring\"`.", {
    additionalLineItems: [ { label: recurringLabel, amount: recurringAmount, paymentTiming: "recurring" } ],
    expectedLineItems: [ { label: recurringLabel, amount: recurringAmount, paymentTiming: "recurring", recurringPaymentIntervalUnit: "month", recurringPaymentIntervalCount: 1 } ],
});
testPaymentItemData("Should also propagate `recurringPaymentIntervalStartDate` and `recurringPaymentIntervalEndDate` if provided when `paymentTiming` is `\"recurring\"`.", {
    additionalLineItems: [ { label: recurringLabel, amount: recurringAmount, paymentTiming: "recurring", recurringPaymentStartDate, recurringPaymentIntervalUnit, recurringPaymentIntervalCount, recurringPaymentEndDate } ],
    expectedLineItems: [ { label: recurringLabel, amount: recurringAmount, paymentTiming: "recurring", recurringPaymentStartDate, recurringPaymentIntervalUnit, recurringPaymentIntervalCount, recurringPaymentEndDate } ],
});

testPaymentItemData("Should not have a default value for `deferredPaymentDate` when `paymentTiming` is `\"deferred\"`.", {
    additionalLineItems: [ { label: deferredLabel, amount: deferredAmount, paymentTiming: "deferred" } ],
    expectedLineItems: [ { label: deferredLabel, amount: deferredAmount, paymentTiming: "deferred", recurringPaymentIntervalUnit: "month", recurringPaymentIntervalCount: 1 } ],
});
testPaymentItemData("Should also propagate `deferredPaymentDate` if provided when `paymentTiming` is `\"deferred\"`.", {
    additionalLineItems: [ { label: deferredLabel, amount: deferredAmount, paymentTiming: "deferred", deferredPaymentDate } ],
    expectedLineItems: [ { label: deferredLabel, amount: deferredAmount, paymentTiming: "deferred", recurringPaymentIntervalUnit: "month", recurringPaymentIntervalCount: 1, deferredPaymentDate } ],
});

done();
</script>

