<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1345361
-->
<head>
  <meta charset="utf-8">
  <title>Test for Bug 1345361</title>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript">

  "use strict";
  SimpleTest.waitForExplicitFinish();

  var gUrl = SimpleTest.getTestFileURL('ConstructorChromeScript.js');
  var gScript = SpecialPowers.loadChromeScript(gUrl);

  function testFailHandler(message) {
    ok(false, message);
  }
  gScript.addMessageListener("test-fail", testFailHandler);

  const simplestMethods = [{
    supportedMethods: "basic-card",
  }];
  const simplestDetails = {
    total: {
      label: "Total",
      amount: {
        currency: "USD",
        value: "1.00"
      }
    }
  };

  const complexMethods = [{
    supportedMethods: "basic-card",
    data: {
      supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                          'diners', 'jcb', 'mir',
      ],
    },
  }];

  const nonBasicCardMethods = [{
    supportedMethods: "testing-payment-method",
    data: {
      paymentId: "P3892940",
      paymentType: "prepaid",
    },
  }];

  const complexDetails = {
    id: "payment details",
    total: {
      label: "Total",
      amount: {
        currency: "USD",
        value: "100.00"
      }
    },
    displayItems: [
      {
        label: "First item",
        amount: {
          currency: "USD",
          value: "60.00"
        }
      },
      {
        label: "Second item",
        amount: {
          currency: "USD",
          value: "40.00"
        }
      }
    ],
    modifiers: [
      {
        supportedMethods: "basic-card",
        total: {
          label: "Discounted Total",
          amount: {
            currency: "USD",
            value: "90.00"
          }
        },
        additionalDisplayItems: [
          {
            label: "basic-card discount",
            amount: {
              currency: "USD",
              value: "-10.00"
            }
          }
        ],
        data: { discountProgramParticipantId: "86328764873265", }
      },
    ],
    shippingOptions: [
      {
        id: "NormalShipping",
        label: "NormalShipping",
        amount: {
          currency: "USD",
          value: "10.00"
        },
        selected: true,
      },
      {
        id: "FastShipping",
        label: "FastShipping",
        amount: {
          currency: "USD",
          value: "30.00"
        },
        selected: false,
      },
    ],
  };

  const complexOptions = {
    requestPayerName: true,
    requestPayerEmail: true,
    requestPayerPhone: true,
    requestShipping: true,
    shippingType: "shipping"
  };

  const duplicateShippingOptionsDetails = {
    id: "duplicate shipping options details",
    total: {
      label: "Total",
      amount: {
        currency: "USD",
        value: "1.00"
      }
    },
    shippingOptions: [
      {
        id: "dupShipping",
        label: "NormalShipping",
        amount: {
          currency: "USD",
          value: "10.00"
        },
        selected: true,
      },
      {
        id: "dupShipping",
        label: "FastShipping",
        amount: {
          currency: "USD",
          value: "30.00"
        },
        selected: false,
      },
    ],
  };


  function testWithSimplestParameters() {
    return new Promise((resolve, reject) => {
      const payRequest = new PaymentRequest(simplestMethods, simplestDetails);
      ok(payRequest, "PaymentRequest should be created");
      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
        gScript.removeMessageListener("check-complete", checkCompleteHandler);
        resolve();
      });
      gScript.sendAsyncMessage("check-simplest-request");
    });
  }

  function testWithComplexParameters() {
    return new Promise((resolve, reject) => {
      const payRequest = new PaymentRequest(complexMethods, complexDetails, complexOptions);
      ok(payRequest, "PaymentRequest should be created");
      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
        gScript.removeMessageListener("check-complete", checkCompleteHandler);
        resolve();
      });
      gScript.sendAsyncMessage("check-complex-request");
    });
  }

  function testWithNonBasicCardMethods() {
    return new Promise((resolve, reject) => {
      const payRequest = new PaymentRequest(nonBasicCardMethods, simplestDetails);
      ok(payRequest, "PaymentRequest should be created");
      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
        gScript.removeMessageListener("check-complete", checkCompleteHandler);
        resolve();
      });
      gScript.sendAsyncMessage("check-nonbasiccard-request");
    });
  }

  function testWithDuplicateShippingOptionsParameters() {
    return new Promise((resolve, reject) => {
      try {
        const payRequest = new PaymentRequest(simplestMethods,
                                              duplicateShippingOptionsDetails,
                                              {requestShipping: true});
        ok(false, "Construction should fail with duplicate shippingOption Ids.");
        resolve();
      } catch (e) {
        is(e.name, "TypeError", "Expected 'TypeError' with duplicate shippingOption Ids.");
        resolve();
      }
    });
  }

  function testShippingOptionAttribute() {
    return new Promise((resolve, reject) => {
      const details = {
        total: {
          label: "Total",
          amount: {
            currency: "USD",
            value: "1.00",
          },
        },
        shippingOptions: [
          {
            id: "option1",
            label: "option1",
            amount: {
              currency: "USD",
              value: "1.00",
            },
            selected: false,
          },
          {
            id: "option2",
            label: "option2",
            amount: {
              currency: "USD",
              value: "1.00",
            },
            selected: false,
          },
        ],
      };
      const payRequest1 = new PaymentRequest(simplestMethods,
                                             details,
                                             {requestShipping: false});
      ok(payRequest1, "PaymentRequest should be created");
      is(payRequest1.shippingOption, null,
         "request.shippingOption should be null in default, when options.requestShipping is false");
      details.shippingOptions[0].selected = true;
      const payRequest2 = new PaymentRequest(simplestMethods,
                                             details,
                                             {requestShipping: false});
      ok(payRequest2, "PaymentRequest should be created");
      is(payRequest2.shippingOption, null,
         "request.shippingOption should be null in default, when options.requestShipping is false");
      const payRequest3 = new PaymentRequest(simplestMethods,
                                             details,
                                             {requestShipping: true});
      ok(payRequest3, "PaymentRequest should be created");
      ok(payRequest3.shippingOption,
         "request.shippingOption should not be null when both shoppingOtpion.selected and options.requestOptions are true");
      is(payRequest3.shippingOption, "option1",
         "request.shippingOption should be 'option1'");
      details.shippingOptions[1].selected = true;
      const payRequest4 = new PaymentRequest(simplestMethods,
                                             details,
                                             {requestShipping: true});
      ok(payRequest4, "PaymentRequest should be created");
      ok(payRequest4.shippingOption,
         "request.shippingOption should not be null when both shoppingOtpion.selected and options.requestOptions are true");
      is(payRequest4.shippingOption, "option2",
         "request.shippingOption should be 'option2' which is the last one selected.");
      resolve();
    });
  }

  function testMultipleRequests() {
    return new Promise((resolve, reject) => {
      const payRequest1 = new PaymentRequest(complexMethods, complexDetails, complexOptions);
      const payRequest2 = new PaymentRequest(simplestMethods, simplestDetails);
      ok(payRequest1, "PaymentRequest with complex parameters should be created");
      ok(payRequest2, "PaymentRequest with simplest parameters should be created");
      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
        gScript.removeMessageListener("check-complete", checkCompleteHandler);
        resolve();
      });
      gScript.sendAsyncMessage("check-multiple-requests");
    });
  }

  function testCrossOriginTopLevelPrincipal() {
    return new Promise((resolve, reject) => {
      var ifrr = document.createElement('iframe');

      window.addEventListener("message", function(event) {
        is(event.data, "successful",
          "Expected 'successful', but got '" + event.data + "'");
        gScript.addMessageListener("check-complete", function checkCompleteHandler() {
          gScript.removeMessageListener("check-complete", checkCompleteHandler);
          resolve();
        });
        gScript.sendAsyncMessage("check-cross-origin-top-level-principal");
      });

      ifrr.setAttribute('allow', 'payment');
      ifrr.src = "https://test1.example.com:443/tests/dom/payments/test/simple_payment_request.html";
      document.body.appendChild(ifrr);
    });
  }

  function teardown() {
    gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
      gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
      gScript.removeMessageListener("test-fail", testFailHandler)
      gScript.destroy();
      SimpleTest.finish();
    });
    gScript.sendAsyncMessage("teardown");
  }

  function runTests() {
    testWithSimplestParameters()
    .then(testWithComplexParameters)
    .then(testWithNonBasicCardMethods)
    .then(testWithDuplicateShippingOptionsParameters)
    .then(testMultipleRequests)
    .then(testCrossOriginTopLevelPrincipal)
    .then(testShippingOptionAttribute)
    .then(teardown)
    .catch( e => {
      ok(false, "Unexpected error: " + e.name);
      SimpleTest.finish();
    });
  }

  window.addEventListener('load', function() {
    SpecialPowers.pushPrefEnv({
      'set': [
        ['dom.payments.request.enabled', true],
      ]
    }, runTests);
  });

  </script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1345361">Mozilla Bug 1345361</a>
</body>
</html>
