chromium/third_party/blink/web_tests/accessibility/contenteditable-notifications.html

<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../resources/run-after-layout-and-paint.js"></script>

<div id="textbox" contenteditable="true">
  First<p>Second</p>
</div>

<script>
'use strict';

async_test((t) => {
  const textbox = document.getElementById('textbox');
  const axTextBox = accessibilityController.accessibleElementById('textbox');
  const axRoot = accessibilityController.rootElement;
  let valueChangedCount = 0;
  let selectedTextChangedCount = 0;
  const expectedValueChangedIntents = [];
  const expectedSelectedTextChangedIntents = [];

  function checkAllNotificationsReceived() {
    if (valueChangedCount >= 5 && selectedTextChangedCount >= 11)
      t.done();
  }

  axTextBox.setNotificationListener(t.step_func((notification, intents) => {
    if (notification == 'ValueChanged') {
      assert_array_equals(intents,
                          expectedValueChangedIntents[valueChangedCount],
                          'ValueChanged at ' + valueChangedCount);
      ++valueChangedCount;
    }

    checkAllNotificationsReceived();
  }));

  axRoot.setNotificationListener(t.step_func((notification, intents) => {
    if (notification == 'DocumentSelectionChanged') {
      // These are no longer fired for contenteditables.
      assert_array_equals(intents,
                          expectedSelectedTextChangedIntents[selectedTextChangedCount],
                          'DocumentSelectionChanged at ' + selectedTextChangedCount);
      ++selectedTextChangedCount;
    }

    checkAllNotificationsReceived();
  }));

  // SelectedTextChanged at 0.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(setSelection,none,character,forward)'
  ]);
  textbox.focus();

  // SelectedTextChanged at 1.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(moveSelection,none,lineStart,forward)'
  ]);
  eventSender.keyDown('ArrowDown', []);

  // ValueChanged at 0.
  expectedValueChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)'
  ]);
  // SelectedTextChanged at 2.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)',
    'AXEventIntent(setSelection,none,character,forward)'
  ]);
  eventSender.keyDown('w', []);

  // SelectedTextChanged at 3.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(moveSelection,none,lineStart,forward)'
  ]);
  eventSender.keyDown('ArrowDown', []);

  // ValueChanged at 1.
  expectedValueChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)'
  ]);
  // SelectedTextChanged at 4.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)',
    'AXEventIntent(setSelection,none,character,forward)'
  ]);
  eventSender.keyDown('x', []);

  // SelectedTextChanged at 5.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(moveSelection,none,character,backward)'
  ]);
  eventSender.keyDown('ArrowLeft', []);

  // ValueChanged at 2.
  expectedValueChangedIntents.push([
    'AXEventIntent(delete,deleteContentForward,none,none)'
  ]);
  eventSender.keyDown('Delete', []);

  // SelectedTextChanged at 6.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(moveSelection,none,character,backward)'
  ]);
  eventSender.keyDown('ArrowLeft', []);

  // ValueChanged at 3.
  expectedValueChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)'
  ]);
  // SelectedTextChanged at 7.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(insert,insertText,none,none)',
    'AXEventIntent(setSelection,none,character,forward)'
  ]);
  eventSender.keyDown('y', []);

  // SelectedTextChanged at 8.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(moveSelection,none,lineStart,backward)'
  ]);
  eventSender.keyDown('ArrowUp', []);

  // SelectedTextChanged at 9.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(insert,insertParagraph,none,none)',
    'AXEventIntent(setSelection,none,character,forward)'
  ]);
  eventSender.keyDown('Enter', []);

  // ValueChanged at 4.
  expectedValueChangedIntents.push([
    'AXEventIntent(delete,deleteContentBackward,none,none)',
  ]);
  // SelectedTextChanged at 10.
  expectedSelectedTextChangedIntents.push([
    'AXEventIntent(delete,deleteContentBackward,none,none)',
    'AXEventIntent(setSelection,none,character,forward)',
  ]);
  eventSender.keyDown('Backspace', []);
}, 'Ensures that moving the cursor in a contentEditable sends a selected text change notification, and typing in a contentEditable sends both a value changed and selected text changed notification.');

</script>