154 lines
5.7 KiB
HTML
154 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<meta charset="utf-8">
|
|
<title>InputEvent.getTargetRanges() behavior</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/testdriver.js"></script>
|
|
<script src="/resources/testdriver-actions.js"></script>
|
|
<script src="/resources/testdriver-vendor.js"></script>
|
|
<p>To manually run this test, please follow the steps below:<br/>
|
|
1. Place caret at the end of 'hel<i>lo wo</i><b>rld</b>'.<br/>
|
|
2. Press Ctrl-Backspace (Alt-Backspace on macOS) to delete word backwards.<br/>
|
|
3. Place caret at the end of 'test2' => Press 'a' key.<br/>
|
|
4. Select 'test2a' => Press 'b' key.<br/>
|
|
5. Select 'b' => Bold text through context menu or Command-b on macOS.<br/>
|
|
6. Place caret at the end of 'test3' => Press 'a' key => Press Backspace key.<br/>
|
|
<br/>
|
|
If a "PASS" result appears the test passes, otherwise it fails</p>
|
|
<p id="test1_editable" contenteditable>hel<i>lo wo</i><b>rld</b></p>
|
|
<p id="test2_editable" contenteditable>test2</p>
|
|
<textarea id="test3_plain">test3</textarea>
|
|
<script>
|
|
function resolveWhen(condition) {
|
|
return new Promise((resolve, reject) => {
|
|
function tick() {
|
|
if (condition())
|
|
resolve();
|
|
else
|
|
requestAnimationFrame(tick.bind(this));
|
|
}
|
|
tick();
|
|
});
|
|
}
|
|
|
|
let modifier_key = "\uE009";
|
|
if(navigator.platform.includes('Mac'))
|
|
modifier_key = "\uE03D";
|
|
const commands = {
|
|
COPY: 'copy',
|
|
CUT: 'cut',
|
|
PASTE: 'paste',
|
|
SELECTALL: 'select all',
|
|
DELETEALL: 'delete all',
|
|
BOLD: 'bold',
|
|
}
|
|
const backspace = "\uE003";
|
|
|
|
function clickOnTarget(target) {
|
|
return new test_driver.Actions()
|
|
.pointerMove(0, 0, {origin: target})
|
|
.pointerDown()
|
|
.pointerUp()
|
|
.send();
|
|
}
|
|
|
|
function sendTextCommand(command) {
|
|
let command_key = "";
|
|
if(command == "copy")
|
|
command_key = "c";
|
|
else if (command == "cut")
|
|
command_key = "x";
|
|
else if (command == "paste")
|
|
command_key = "v";
|
|
else if (command == "select all")
|
|
command_key = "a";
|
|
else if (command == "delete all")
|
|
command_key = backspace;
|
|
else if (command == "bold")
|
|
command_key = "b";
|
|
return new test_driver.Actions()
|
|
.keyDown(modifier_key)
|
|
.keyDown(command_key)
|
|
.keyUp(command_key)
|
|
.keyUp(modifier_key)
|
|
.send();
|
|
}
|
|
|
|
function sendTextCommandAtTarget(target, command) {
|
|
return clickOnTarget(target).then(() => {
|
|
return sendTextCommand(command);
|
|
});
|
|
}
|
|
|
|
function addTextAtTarget(target, char) {
|
|
return test_driver.send_keys(target, char);
|
|
}
|
|
|
|
promise_test(async test => {
|
|
const test1_editable = document.getElementById('test1_editable');
|
|
let lastBeforeInput;
|
|
test1_editable.addEventListener('beforeinput', test.step_func(function() {
|
|
assert_equals(event.inputType, 'deleteWordBackward');
|
|
const ranges = event.getTargetRanges();
|
|
assert_equals(ranges.length, 1);
|
|
const range = ranges[0];
|
|
assert_true(range instanceof StaticRange);
|
|
assert_equals(range.startOffset, 3);
|
|
assert_equals(range.startContainer.textContent, 'lo wo');
|
|
assert_equals(range.endOffset, 3);
|
|
assert_equals(range.endContainer.textContent, 'rld');
|
|
assert_equals(test1_editable.innerHTML, 'hel<i>lo wo</i><b>rld</b>');
|
|
lastBeforeInput = event;
|
|
}));
|
|
|
|
test1_editable.addEventListener('input', test.step_func(function() {
|
|
assert_equals(event.inputType, 'deleteWordBackward');
|
|
assert_equals(test1_editable.innerHTML, 'hel<i>lo </i>');
|
|
assert_equals(lastBeforeInput.inputType, 'deleteWordBackward');
|
|
assert_equals(lastBeforeInput.getTargetRanges().length, 0,
|
|
'getTargetRanges() should be empty after the event has finished dispatching.');
|
|
}));
|
|
|
|
await sendTextCommandAtTarget(test1_editable, commands.DELETEALL);
|
|
await resolveWhen(() => { return test1_editable.innerHTML == 'hel<i>lo </i>' });
|
|
}, 'getTargetRanges() returns correct range and cleared after dispatch.');
|
|
|
|
promise_test(async test => {
|
|
const expectedEventLog = ['test2-5-test2-5', 'test2a-0-test2a-6', 'b-0-b-1'];
|
|
const actualEventLog = [];
|
|
|
|
const test2_editable = document.getElementById('test2_editable');
|
|
test2_editable.addEventListener('beforeinput', test.step_func(function() {
|
|
const ranges = event.getTargetRanges();
|
|
assert_equals(ranges.length, 1);
|
|
const range = ranges[0];
|
|
actualEventLog.push(
|
|
`${range.startContainer.textContent}-${range.startOffset}-${range.endContainer.textContent}-${range.endOffset}`);
|
|
}));
|
|
|
|
await addTextAtTarget(test2_editable, "a");
|
|
await sendTextCommandAtTarget(test2_editable, commands.SELECTALL);
|
|
await addTextAtTarget(test2_editable, "b");
|
|
await sendTextCommandAtTarget(test2_editable, commands.SELECTALL);
|
|
await sendTextCommand(commands.BOLD);
|
|
await resolveWhen(() => { return actualEventLog.length == expectedEventLog.length });
|
|
assert_array_equals(actualEventLog, expectedEventLog,
|
|
`Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`);
|
|
}, 'Actions other than deletion should have current selection as target ranges.');
|
|
|
|
promise_test(async test => {
|
|
const test3_plain = document.getElementById('test3_plain');
|
|
let event_type;
|
|
test3_plain.addEventListener('beforeinput', test.step_func(function() {
|
|
assert_equals(event.getTargetRanges().length, 0,
|
|
'getTargetRanges() should return empty array on textarea.');
|
|
|
|
if (event.inputType === 'deleteContentBackward')
|
|
event_type = event.inputType;
|
|
}));
|
|
|
|
await addTextAtTarget(test3_plain, "a");
|
|
await addTextAtTarget(test3_plain, backspace);
|
|
await resolveWhen(() => { return event_type == 'deleteContentBackward' });
|
|
}, 'Textarea should have empty target range.');
|
|
</script>
|