chromium/third_party/blink/web_tests/editing/spelling/spelling-changed-text.html

<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../assert_selection.js"></script>
<script src="spellcheck_test.js"></script>
<script>
spellcheck_test(
    '<div contenteditable>|</div>',
    // Insert a space after the misspelled word so it is spellchecked properly.
    // This is done to trigger spellchecking as the punctuation after the misspelled word
    // doesn't trigger spellchecking until the user has pressed space bar or changed the selection.
    // This is how it should be done in real sites anyways so inserting the space after spellcheck
    // makes sense.
    'insertText Spell wellcome. ',
    '<div contenteditable>Spell #wellcome#.\u00A0</div>',
    {
      title: '1 Setup a content editable div with spelling marker',
      callback: sample => spellcheck_test(
          sample,
          document => {
            assert_not_equals(window.eventSender, undefined, 'This test requires eventSender. ');

            const destination = document.querySelector('div');
            const textNode = destination.firstChild;
            const deleteRange = document.createRange();
            deleteRange.setStart(textNode, 16);
            deleteRange.setEnd(textNode, 16);
            document.getSelection().removeAllRanges();
            document.getSelection().addRange(deleteRange);
            document.execCommand('insertText', false, 'Is it broken?');
            const textNode1 = destination.firstChild;
            // Select the text "Is it broken?".
            deleteRange.setStart(textNode1, 16);
            deleteRange.setEnd(textNode1, 29);
            document.getSelection().removeAllRanges();
            document.getSelection().addRange(deleteRange);

            // Delete the text "Is it broken?".
            textNode1.deleteData(16, 29);

            // Context click to show the context menu.
            var x = destination.offsetParent.offsetLeft + destination.offsetLeft + 50;
            var y = destination.offsetParent.offsetTop + destination.offsetTop + destination.offsetHeight / 2;
            eventSender.mouseMoveTo(x, y);
            contextMenuElements = eventSender.contextClick();

            // Esc key to hide the context menu.
            eventSender.keyDown("Escape", null);
          },
          '<div contenteditable>Spell #wellcome#. </div>',
          '1 Spellcheck should not crash after the text has changed.')
    });

spellcheck_test(
    '<div contenteditable>zz.|</div>',
    '',
    '<div contenteditable>#zz#.</div>',
    {
      title: '2 Setup a content editable div with spelling marker',
      callback: sample => spellcheck_test(
          sample,
          document => {
            // Send out a new request that rechecks the entire div.
            document.execCommand('insertText', false, ' zz.');
            if (window.internals)
              internals.runIdleTimeSpellChecker(document);

            // Mutate the text node to cancel the previous request.
            const text = document.querySelector('div').firstChild;
            text.deleteData(text.length - 2, 2);
          },
          '<div contenteditable>#zz#. z</div>',
          '2 Canceled spellcheck request should not remove existing marker')
    });

// Must be at least 1024 characters to force spellchecker to compute checking
// range with TextIterator.
const longText = 'bla. '.repeat(255) + 'bla.';
spellcheck_test(
  `<div contenteditable>${longText}|</div>`,
  document => {
    document.execCommand('insertText', false, 'zz..');

    // Invalidate the ending selection of InsertText command in the undo stack.
    const textNode = document.getSelection().anchorNode;
    textNode.deleteData(textNode.length - 1, 1);

    // Clear selection, so that if spellchecker can only use the ending
    // selection of InsertText command to compute checking range.
    document.getSelection().removeAllRanges();
  },
  `<div contenteditable>${longText}zz.</div>`,
  '3 No spellcheck due to invalid ending selection in the undo stack');
</script>
</body>
</html>