<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="timeout" content="long">
<meta name="variant" content="?target=ContentEditable">
<meta name="variant" content="?target=ContentEditable&parent=b">
<meta name="variant" content="?target=ContentEditable&child=b">
<meta name="variant" content="?target=ContentEditable&parent=b&child=i">
<meta name="variant" content="?target=DesignMode">
<meta name="variant" content="?target=DesignMode&parent=b">
<meta name="variant" content="?target=DesignMode&child=b">
<meta name="variant" content="?target=DesignMode&parent=b&child=i">
<title>Testing inserting content around link element</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="../include/editor-test-utils.js"></script>
<style>
.bold {
  font-weight: bold;
}
</style>
</head>
<body>
<div contenteditable></div>
<iframe srcdoc="
  <!doctype html>
  <html>
    <script>document.designMode='on';</script>
    <script src='/resources/testdriver.js'></script>
    <script src='/resources/testdriver-vendor.js'></script>
    <script src='/resources/testdriver-actions.js'></script>
    <body></body>
  </html>"></iframe>
<script>
"use strict";

const params = new URLSearchParams(location.search.substring(1));
const kTarget = params.get("target");
const kParentTag = params.get("parent") === null
  ? ["", ""]
  : [`<${params.get("parent")}>`, `</${params.get("parent")}>`];
const kChildTag = params.get("child") === null
  ? ["", ""]
  : [`<${params.get("child")}>`, `</${params.get("child")}>`];
const kLinkDesc = (() => {
  let result = ""
  if (kParentTag[0] !== "") {
    result += `in ${kParentTag[0]} `;
    if (kChildTag[0] !== "") {
      result += "and ";
    }
  }
  if (kChildTag[0] !== "") {
    result += `containing ${kChildTag[0]} `;
  }
  return result;
})();
const kNewContainerOfLink = (() => {
  if (kParentTag !== "" && kChildTag !== "") {
    return [`${kParentTag[0]}${kChildTag[0]}`, `${kChildTag[1]}${kParentTag[1]}`];
  }
  if (kParentTag !== "") {
    return kParentTag;
  }
  if (kChildTag !== "") {
    return kChildTag;
  }
  return ["", ""];
})();
const kSelectorForTextNodeContainer = kChildTag[0] === ""
  ? "a"
  : `a > ${kChildTag[0].substr(1, kChildTag[0].length - 2)}`;

function getEditingHost() {
  return kTarget === "ContentEditable"
    ? document.querySelector("div[contenteditable]")
    : document.querySelector("iframe").contentDocument.body;
}

function addPromiseTest(test) {
  promise_test(async () => {
    let editingHost = getEditingHost();
    let utils = new EditorTestUtils(editingHost);
    utils.setupEditingHost(test.innerHTML);
    utils.window.focus();
    utils.document.body.focus();
    editingHost.focus();
    await test.run(utils);
    if (Array.isArray(test.expectedResult)) {
      assert_in_array(editingHost.innerHTML, test.expectedResult);
    } else {
      assert_equals(editingHost.innerHTML, test.expectedResult);
    }
  }, `${test.description.trim()} in ${test.innerHTML}`);
}

promise_test(async () => {
  await new Promise(resolve => {
    addEventListener("load", resolve, { once: true });
  });
}, "");

if (kChildTag[0] === "") {
  // Immediately after creating a link with Document.execCommand.

  addPromiseTest({
    description: `Replacing text in a link ${kLinkDesc}with "XY"`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}<a href="about:blank">XY${kParentTag[1]}</a></p>`,
      `<p>${kParentTag[0]}<a href="about:blank">XY${kParentTag[1]}</a><br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following Selection.collapseToEnd)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      utils.selection.collapseToEnd();
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}<br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following ArrowRight key press)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      await utils.sendArrowRightKey();
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}<br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following End key press)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      if (!navigator.platform.includes("Mac")) {
        await utils.sendEndKey();
      } else {
        await utils.sendArrowRightKey(utils.kMetaKey);
      }
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}<a href="about:blank">abc</a>XY${kParentTag[1]}<br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following Selection.collapseToStart)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      utils.selection.collapseToStart();
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}<br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following ArrowLeft key press)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      await utils.sendArrowLeftKey();
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}<br></p>`,
    ],
  });

  addPromiseTest({
    description: `Inserting "XY" after making a link ${kLinkDesc}(following Home key press)`,
    innerHTML: `<p>${kParentTag[0]}[abc]${kParentTag[1]}</p>`,
    run: async (utils) => {
      utils.document.execCommand("createLink", false, "about:blank");
      if (!navigator.platform.includes("Mac")) {
        await utils.sendHomeKey();
      } else {
        await utils.sendArrowLeftKey(utils.kMetaKey);
      }
      await utils.sendKey("X", utils.kShiftKey);
      await utils.sendKey("Y", utils.kShiftKey);
    },
    expectedResult: [
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}</p>`,
      `<p>${kParentTag[0]}XY<a href="about:blank">abc</a>${kParentTag[1]}<br></p>`,
    ],
  });
}

addPromiseTest({
  description: `Inserting "XY" after setting caret position to middle of a link ${kLinkDesc}(Selection.collapse)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    utils.selection.collapse(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 2);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after setting caret position to middle of a link ${kLinkDesc}(Selection.addRange)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    utils.selection.removeAllRanges();
    let range = utils.document.createRange();
    range.setStart(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 2);
    utils.selection.addRange(range);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after setting caret position to start of a link ${kLinkDesc}(Selection.collapse)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    utils.selection.collapse(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 0);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[2]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after setting caret position to start of a link ${kLinkDesc}(Selection.addRange)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
  utils.selection.removeAllRanges();
  let range = utils.document.createRange();
  range.setStart(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 0);
  utils.selection.addRange(range);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[2]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after setting caret position to end of a link ${kLinkDesc}(Selection.collapse)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    utils.selection.collapse(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, "abc".length);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[2]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after setting caret position to end of a link ${kLinkDesc}(Selection.addRange)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    utils.selection.collapse(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, "abc".length);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[2]}<br></p>`,
  ],
});

// Type text after moving caret with Range API.
addPromiseTest({
  description: `Inserting "XY" after modifying caret position to middle of a link ${kLinkDesc}`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    let range = utils.selection.getRangeAt(0);
    range.setStart(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 2);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
    `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abXYc${kChildTag[1]}</a>${kParentTag[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after modifying caret position to start of a link ${kLinkDesc}`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    let range = utils.selection.getRangeAt(0);
    range.setStart(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 0);
    range.setEnd(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, 0);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after modifying caret position to end of a link ${kLinkDesc}`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[]c${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    let range = utils.selection.getRangeAt(0);
    range.setStart(utils.editingHost.querySelector(kSelectorForTextNodeContainer).firstChild, "abc".length);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

// Type text after deleting character immediately before/after a link.
addPromiseTest({
  description: `Inserting "XY" after deleting following character of a link ${kLinkDesc}(Backspace)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abc${kChildTag[1]}</a>d[]${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendBackspaceKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting following character of a link ${kLinkDesc}(execCommand("delete"))`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abc${kChildTag[1]}</a>d[]${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("delete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting a previous character of a link ${kLinkDesc}(Delete)`,
  innerHTML: `<p>${kParentTag[0]}[]z<a href="about:blank">${kChildTag[0]}abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendDeleteKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting a previous character of a link ${kLinkDesc}(execCommand("forwarddelete"))`,
  innerHTML: `<p>${kParentTag[0]}[]z<a href="about:blank">${kChildTag[0]}abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("forwarddelete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

// Type text after deleting the last character in a link.
addPromiseTest({
  description: `Inserting "XY" after deleting last character of a link ${kLinkDesc}(Backspace)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abcd[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendBackspaceKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[1]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting last character of a link ${kLinkDesc}(execCommand("delete"))`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abcd[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("delete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[1]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting last character of a link ${kLinkDesc}(Delete)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abc[]d${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendDeleteKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting last character of a link ${kLinkDesc}(execCommand("forwarddelete"))`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abc[]d${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("forwarddelete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});

// Type text after deleting the first character in a link.
addPromiseTest({
  description: `Inserting "XY" after deleting first character of a link ${kLinkDesc}(Backspace)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}z[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendBackspaceKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting first character of a link ${kLinkDesc}(execCommand("delete"))`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}z[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("delete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting first character of a link ${kLinkDesc}(Delete)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[]zabc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendDeleteKey();
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

addPromiseTest({
  description: `Inserting "XY" after deleting first character of a link ${kLinkDesc}(execCommand("forwarddelete"))`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[]zabc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.document.execCommand("forwarddelete", false);
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});

// Don't create `<span>` element for preserving specified style of the link and
// don't clone `class` nor `style` attribute of the link.
addPromiseTest({
  description: `Inserting "XY" at start of a link which has a class for bold text`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" class="bold">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" class="bold">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" class="bold">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});
addPromiseTest({
  description: `Inserting "XY" at end of a link which has a class for bold text`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" class="bold">${kChildTag[0]}abc[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" class="bold">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" class="bold">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});
addPromiseTest({
  description: `Inserting "XY" at start of a link which has inline style for bold text`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" style="font-weight: bold">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" style="font-weight: bold">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" style="font-weight: bold">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});
addPromiseTest({
  description: `Inserting "XY" at end of a link which has inline style for bold text`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" style="font-weight: bold">${kChildTag[0]}abc[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" style="font-weight: bold">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" style="font-weight: bold">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});
document.execCommand("styleWithCSS", false, "true");
addPromiseTest({
  description: `Inserting "XY" at start of a link which has a class for bold text (in CSS mode)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" class="bold">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" class="bold">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" class="bold">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});
addPromiseTest({
  description: `Inserting "XY" at end of a link which has a class for bold text (in CSS mode)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" class="bold">${kChildTag[0]}abc[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" class="bold">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" class="bold">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});
addPromiseTest({
  description: `Inserting "XY" at start of a link which has inline style for bold text (in CSS mode)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" style="font-weight: bold">${kChildTag[0]}[]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" style="font-weight: bold">abc</a>${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}XY<a href="about:blank" style="font-weight: bold">abc</a>${kNewContainerOfLink[1]}<br></p>`,
  ],
});
document.execCommand("styleWithCSS", false, "false");
addPromiseTest({
  description: `Inserting "XY" at end of a link which has inline style for bold text (in CSS mode)`,
  innerHTML: `<p>${kParentTag[0]}<a href="about:blank" style="font-weight: bold">${kChildTag[0]}abc[]${kChildTag[1]}</a>${kParentTag[1]}</p>`,
  run: async (utils) => {
    await utils.sendKey("X", utils.kShiftKey);
    await utils.sendKey("Y", utils.kShiftKey);
  },
  expectedResult: [
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" style="font-weight: bold">abc</a>XY${kNewContainerOfLink[1]}</p>`,
    `<p>${kNewContainerOfLink[0]}<a href="about:blank" style="font-weight: bold">abc</a>XY${kNewContainerOfLink[1]}<br></p>`,
  ],
});
document.execCommand("styleWithCSS", false, "false");

</script>
</body>
</html>
