Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<html>
<head>
<title>EditContext: The HTMLElement.editContext property</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src='../../html/resources/common.js'></script>
</head>
<body>
<div id="test"></div>
<div id="contenteditableDiv" contenteditable></div>
<script>
test(function() {
const editContextDict = {
text: "Hello world",
selectionStart: 11,
selectionEnd: 11
};
const editContext = new EditContext(editContextDict);
assert_not_equals(editContext, null);
// Verify all the members of the EditContext
assert_equals(editContext.text, "Hello world");
assert_equals(editContext.selectionStart, 11);
assert_equals(editContext.selectionEnd, 11);
}, 'Testing EditContext Dictionary Init');
test(function() {
contenteditableDiv.editContext = new EditContext();
contenteditableDiv.editContext = null;
contenteditableDiv.focus();
assert_equals(document.activeElement, contenteditableDiv);
}, 'A contenteditable element should remain editable after attaching and detaching EditContext.');
test(function() {
const editContext = new EditContext();
assert_not_equals(editContext, null);
const disconnected_div = document.createElement("DIV");
assert_equals(disconnected_div.editContext, null);
disconnected_div.editContext = editContext;
assert_equals(disconnected_div.editContext, editContext);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], disconnected_div);
}, 'EditContext can be associated with an element that is not in the tree.');
test(function() {
const editContext = new EditContext();
assert_not_equals(editContext, null);
const div = document.createElement("DIV");
assert_equals(div.editContext, null);
document.body.appendChild(div);
div.editContext = editContext;
assert_equals(div.editContext, editContext);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], div);
document.body.removeChild(div);
assert_equals(div.editContext, editContext);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], div);
}, 'If an element is removed from the tree, the associated EditContext remains connected to the element.');
test(function() {
const editContext = new EditContext();
const div_parent = document.createElement("DIV");
const div_child = document.createElement("DIV");
document.body.appendChild(div_parent);
div_parent.appendChild(div_child);
div_child.editContext = editContext;
assert_equals(div_child.editContext, editContext);
assert_equals(div_parent.editContext, null);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], div_child);
document.body.removeChild(div_parent);
assert_equals(div_child.editContext, editContext);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], div_child);
}, 'If an element\'s ancestor is removed from tree, the associated EditContext remains connected to the element.');
test(function() {
const editContext = new EditContext();
const test = document.getElementById("test");
test.editContext = editContext;
assert_equals(test.editContext, editContext);
assert_equals(editContext.attachedElements().length, 1);
assert_equals(editContext.attachedElements()[0], test);
test.editContext = null;
assert_equals(editContext.attachedElements().length, 0);
}, '.attachedElements() should return associated element');
test(function() {
const editContext = new EditContext();
assert_not_equals(editContext, null);
editContext.updateText(0, 3, "foo");
assert_equals(editContext.text, "foo");
const test = document.getElementById('test');
// Update the layout of the |EditContext|
var viewRect = test.getBoundingClientRect();
viewRect.x = viewRect.left;
viewRect.y = viewRect.top;
var caretRect = test.getBoundingClientRect();
caretRect.x = caretRect.left;
caretRect.y = 2.2 * caretRect.top;
caretRect.width = 1;
editContext.updateSelection(0, 0);
assert_equals(editContext.selectionStart, 0);
assert_equals(editContext.selectionEnd, 0);
editContext.updateSelection(1, 0);
assert_equals(editContext.selectionStart, 1);
assert_equals(editContext.selectionEnd, 0);
editContext.updateSelection(0, 1);
assert_equals(editContext.selectionStart, 0);
assert_equals(editContext.selectionEnd, 1);
editContext.updateSelection(1, 1);
assert_equals(editContext.selectionStart, 1);
assert_equals(editContext.selectionEnd, 1);
editContext.updateControlBounds(viewRect);
editContext.updateSelectionBounds(caretRect);
editContext.updateCharacterBounds(0, [caretRect]);
assert_throws_js(TypeError, function() { editContext.updateControlBounds(42); });
assert_throws_js(TypeError, function() { editContext.updateSelectionBounds(42); });
assert_throws_js(TypeError, function() { editContext.updateControlBounds(undefined); });
assert_throws_js(TypeError, function() { editContext.updateSelectionBounds(undefined); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds(0); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds([caretRect]); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds(0, caretRect); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds(0, 42); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds(0, undefined); });
assert_throws_js(TypeError, function() { editContext.updateCharacterBounds(0, [undefined]); });
viewRect.x = viewRect.y = viewRect.width = viewRect.height = undefined;
editContext.updateControlBounds(viewRect);
editContext.updateSelectionBounds(viewRect);
editContext.updateCharacterBounds(0, [viewRect]);
}, 'Testing EditContext update text, selection and layout');
test(function() {
const editContext = new EditContext();
const test = document.getElementById('test');
var rect1 = DOMRect.fromRect({x:0, y:1, width:100, height:200});
var rect2 = DOMRect.fromRect({x:2, y:3, width:300, height:400});
var rectArray = [rect1, rect2];
var rangeStart = 2;
editContext.updateCharacterBounds(rangeStart, rectArray);
assert_equals(editContext.characterBoundsRangeStart, 2);
var actualRectArray = editContext.characterBounds();
assert_equals(actualRectArray.length, 2);
assert_equals(actualRectArray[0].x, 0);
assert_equals(actualRectArray[0].y, 1);
assert_equals(actualRectArray[0].width, 100);
assert_equals(actualRectArray[0].height, 200);
rect2.x=100;
assert_equals(actualRectArray[1].x, 2); // the cached value shouldn't change.
assert_equals(actualRectArray[1].y, 3);
assert_equals(actualRectArray[1].width, 300);
assert_equals(actualRectArray[1].height, 400);
}, 'updateCharacterBounds(), characterBounds(), and characterBoundsRangeStart should work properly');
// The behavior in this test case is not well-defined in the spec.
// test(function() {
// const editContext = new EditContext();
// assert_not_equals(editContext, null);
// editContext.updateText(0, 3, "foo");
// assert_equals(editContext.text, "foo");
// assert_throws_dom("IndexSizeError", function() { editContext.updateSelection(10, 0); });
// assert_equals(editContext.selectionStart, 0);
// assert_equals(editContext.selectionEnd, 0);
// assert_throws_dom("IndexSizeError", function() { editContext.updateText(10, 1, "h"); });
// assert_equals(editContext.text, "foo");
// }, 'Testing EditContext update text and selection with invalid values');
test(function() {
const editContext = new EditContext();
assert_not_equals(editContext, null);
editContext.updateText(0, 3, "foo");
assert_equals(editContext.text, "foo");
editContext.updateSelection(3, 0);
assert_equals(editContext.selectionStart, 3);
assert_equals(editContext.selectionEnd, 0);
}, 'EditContext should allow a backwards selection');
test(function() {
const editContext = new EditContext();
assert_not_equals(editContext, null);
editContext.updateText(6, 0, "abcdef");
assert_equals(editContext.text, "abcdef");
editContext.updateText(2, 5, "ghi");
assert_equals(editContext.text, "abghif");
editContext.updateText(5, 2, "jkl");
assert_equals(editContext.text, "abjklf");
}, 'updateText can replace substrings including with backwards parameters');
</script>
</body>
</html>