| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>Test selectionchange events from text controls</title> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <link rel="stylesheet" href="/fonts/ahem.css"> | |
| <style> | |
| input, | |
| textarea { | |
| font: 16px/1 Ahem; | |
| } | |
| </style> | |
| <input id="input" width="200"><br> | |
| <textarea id="textarea" width="200"></textarea> | |
| <script> | |
| class SelectionChangeCollector { | |
| /** | |
| * @param {HTMLElement} target | |
| */ | |
| constructor(target) { | |
| this.target = target; | |
| this.events = []; | |
| target.addEventListener("selectionchange", ev => { | |
| this.events.push(ev); | |
| }); | |
| } | |
| clear() { | |
| this.events.length = 0; | |
| } | |
| } | |
| const data = { | |
| collectors: [ | |
| new SelectionChangeCollector(input), | |
| new SelectionChangeCollector(input.cloneNode()), | |
| new SelectionChangeCollector(textarea), | |
| new SelectionChangeCollector(textarea.cloneNode(true)), | |
| ], | |
| async initialize() { | |
| for (const collector of this.collectors) { | |
| collector.target.value = "XXXXXXXXXXXXXXXXXXX"; | |
| collector.target.blur(); | |
| collector.target.setSelectionRange(0, 0); | |
| } | |
| await this.spin(); | |
| for (const collector of this.collectors) { | |
| collector.clear(); | |
| } | |
| }, | |
| spin() { | |
| return new Promise(setTimeout); | |
| }, | |
| async assert_empty_spin() { | |
| // firing selectionchange must be asynchronous | |
| for (const collector of this.collectors) { | |
| assert_equals(collector.events.length, 0); | |
| } | |
| await this.spin(); | |
| } | |
| }; | |
| for (const collector of data.collectors) { | |
| const target = collector.target; | |
| const name = `the ${!target.parentNode ? "disconnected " : ""}${target.localName} element`; | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionStart = 1; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Modifying selectionStart value of ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionEnd = 1; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Modifying selectionEnd value of ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.setSelectionRange(0, 4); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Calling setSelectionRange() on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.select(); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Calling select() on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.setRangeText("newmiddle", 2, 3, "select"); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Calling setRangeText() on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionStart = 0; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 0); | |
| }, `Setting initial zero selectionStart value on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionStart = 2; | |
| target.selectionStart = 2; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Setting the same selectionStart value twice on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionEnd = 0; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 0); | |
| }, `Setting initial zero selectionEnd value on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.selectionEnd = 2; | |
| target.selectionEnd = 2; | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Setting the same selectionEnd value twice on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.setSelectionRange(0, 0); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 0); | |
| }, `Setting initial zero selection range on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.setSelectionRange(3, 3); | |
| target.setSelectionRange(3, 3); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Setting the same selection range twice on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.select(); | |
| target.select(); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 1); | |
| }, `Calling select() twice on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.select(); | |
| target.setRangeText("foo", 2, 6); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 2); | |
| }, `Calling setRangeText() after select() on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.select(); | |
| target.setRangeText("", 10, 12); | |
| target.setRangeText("", 10, 12); | |
| target.setRangeText("", 10, 12); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 4); | |
| }, `Calling setRangeText() repeatedly on ${name}`); | |
| promise_test(async () => { | |
| await data.initialize(); | |
| target.value = ""; | |
| target.setRangeText("foo"); | |
| await data.assert_empty_spin(); | |
| assert_equals(collector.events.length, 0); | |
| }, `Calling setRangeText() on empty ${name}`); | |
| } | |
| </script> |