<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Test for valid state with autocomplete</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="satchel_common.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
  <style>
    input:invalid {
      border: red 1px solid;
    }
  </style>
</head>
<body>
<p id="display"></p>

<div id="content">
  <form id="form1">
    <input  type="email" name="field1">
    <button type="submit">Submit</button>
  </form>
</div>

<script>

add_setup(async () => {
   await updateFormHistory([
    { op: "remove" },
    { op: "add", fieldname: "field1", value: "email@example.com" },
    { op: "add", fieldname: "field1", value: "email@example.com." },
  ]);
});

add_task(async function datalist_with_caching() {
   const kSetUserInputCancelable = SpecialPowers.getBoolPref("dom.input_event.allow_to_cancel_set_user_input");
   const { input } = await openPopupOn("input[name=field1]");
   synthesizeKey("KEY_Escape");

   let beforeInputFired = false;
   input.addEventListener("beforeinput", e => {
      beforeInputFired = true;
      ok(e.cancelable, "'beforeinput' event for 'insertText' is cancelable");
      is(e.inputType, "insertText", "inputType of 'beforeinput' event is 'insertText'");
      ok(input.validity.valid, "Valid immediately before inserting a character");
      ok(!input.matches(":invalid"),
         "Shouldn't match ':invalid' immediately before inserting a character");
   }, { once: true });

   let inputFired = false;
   input.addEventListener("input", e => {
      inputFired = true;
      is(e.inputType, "insertText", "inputType of 'input' event should be 'insertText'");
      ok(!input.validity.valid, "Invalid immediately after inserting a character");
      ok(input.matches(":invalid"),
         "Should match ':invalid' immediately after inserting a character");
   }, { once: true });
   synthesizeKey("e");
   ok(beforeInputFired, "'beforeinput' event fired at typing 'e'");
   ok(inputFired, "'input' event fired at typing 'e'");

   await notifyMenuChanged(2);
   inputFired = false;
   beforeInputFired = false;
   input.addEventListener("beforeinput", e => {
      beforeInputFired = true;
      is(e.cancelable, kSetUserInputCancelable,
         "'beforeinput' event for 'insertReplacementText' is cancelable unless it's suppressed by the pref");
      is(e.inputType, "insertReplacementText",
         "inputType of 'beforeinput' event is 'insertReplacementText'");
      ok(!input.validity.valid,
         "Invalid immediately before selecting valid item in autocomplete list");
      ok(input.matches(":invalid"),
         "Matches ':invalid' immediately before selecting valid item in autocomplete list");
   }, { once: true });
   input.addEventListener("input", e => {
      inputFired = true;
      is(e.inputType, "insertReplacementText",
         "inputType of 'input' event is 'insertReplacementText'");
      ok(input.validity.valid,
         "Valid immediately after selecting valid item in autocomplete list");
      ok(!input.matches(":invalid"),
         "Shouldn't match ':invalid' immediately after selecting valid item in autocomplete list");
   }, { once: true });
   synthesizeKey("KEY_ArrowDown");
   synthesizeKey("KEY_Enter"); // Select valid item
   ok(beforeInputFired, "'beforeinput' event should have been fired at selecting valid item");
   ok(inputFired, "'input' event should have been fired at selecting valid item");

   inputFired = false;
   beforeInputFired = false;
   synthesizeKey("KEY_Backspace");
   await notifyMenuChanged(2);
   synthesizeKey("KEY_ArrowDown");
   synthesizeKey("KEY_ArrowDown");
   input.addEventListener("beforeinput", e => {
      ok(!beforeInputFired, '"input" event should be fired only once at typing');
      beforeInputFired = true;
      is(e.cancelable, kSetUserInputCancelable,
         `"beforeinput" event for "insertReplacementText" is cancelable unless it's suppressed by the pref`);
      is(e.inputType, "insertReplacementText",
         "inputType of 'beforeinput' event is 'insertReplacementText'");
      ok(input.validity.valid,
         "Valid immediately before selecting invalid item in autocomplete list");
      ok(!input.matches(":invalid"),
         "Shouldn't match ':invalid' immediately after selecting invalid item in autocomplete list");
   }, { once: true });
   input.addEventListener("input", (event) => {
      ok(!inputFired, '"input" event is fired only once at typing');
      inputFired = true;
      is(event.inputType, "insertReplacementText",
         "inputType of 'input' event is 'insertReplacementText'");
      ok(!input.validity.valid,
         "Invalid immediately after selecting invalid item in autocomplete list");
      ok(input.matches(":invalid"),
         "Matches ':invalid' immediately after selecting invalid item in autocomplete list");
   }, { once: true });
   synthesizeKey("KEY_Enter"); // Select invalid item
   ok(beforeInputFired, "'beforeinput' event should have been fired at selecting invalid item");
   ok(inputFired, "'input' event should have been fired at selecting invalid item");
});

</script>
</body>
