spiegel-keyman/web/unit_tests/cases/element_interfaces.js
2019-11-27 09:53:42 +07:00

1462 lines
No EOL
60 KiB
JavaScript

var assert = chai.assert;
var InterfaceTests;
// Define common interface testing functions that can be run upon the OutputTarget interface.
if(typeof InterfaceTests == 'undefined') {
InterfaceTests = {};
(function(){
// Makes a nice Unicode shortcut.
var u = toSupplementaryPairString;
InterfaceTests.Strings = {};
InterfaceTests.Strings.Apple = {};
InterfaceTests.Strings.Apple.normal = 'apple';
// Built in-line via function. Looks functionally equivalent to "apple", but with SMP characters.
InterfaceTests.Strings.Apple.smp = u(0x1d5ba)+u(0x1d5c9)+u(0x1d5c9)+u(0x1d5c5)+u(0x1d5be);
InterfaceTests.Strings.Apple.mixed = 'a'+u(0x1d5c9)+'p'+'l'+u(0x1d5be);
//#region Defines helpers related to HTMLInputElement / Input test setup.
InterfaceTests.Input = {};
InterfaceTests.Input.setupElement = function() {
var id = DynamicElements.addInput();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.Input(elem);
return {elem: elem, wrapper: wrapper};
}
InterfaceTests.Input.resetWithText = function(pair, string) {
pair.elem.value = string;
pair.wrapper.invalidateSelection();
pair.elem.setSelectionRange(0, 0);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.Input.setCaret = function(pair, index) {
pair.elem.setSelectionRange(index, index);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.Input.getCaret = function(pair) {
return pair.elem.selectionStart;
}
InterfaceTests.Input.setSelectionRange = function(pair, start, end) {
// For HTMLInputElements, `start` must be before `end` to create a proper range.
var dir = 'forward';
if(end < start) {
dir = 'backward';
var temp = end;
end = start;
start = temp;
}
pair.elem.setSelectionRange(start, end, dir);
}
InterfaceTests.Input.setText = function(pair, text) {
pair.elem.value = text;
}
//#endregion
//#region Defines helpers related to HTMLTextAreaElement / TextArea test setup.
InterfaceTests.TextArea = {};
InterfaceTests.TextArea.setupElement = function() {
var id = DynamicElements.addText();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.TextArea(elem);
return {elem: elem, wrapper: wrapper};
}
InterfaceTests.TextArea.resetWithText = function(pair, string) {
pair.elem.value = string;
pair.wrapper.invalidateSelection();
pair.elem.setSelectionRange(0, 0);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.TextArea.setCaret = function(pair, index) {
pair.elem.setSelectionRange(index, index);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.TextArea.getCaret = function(pair) {
return pair.elem.selectionStart;
}
InterfaceTests.TextArea.setSelectionRange = function(pair, start, end) {
// For HTMLInputElements, `start` must be before `end` to create a proper range.
var dir = 'forward';
if(end < start) {
dir = 'backward';
var temp = end;
end = start;
start = temp;
}
pair.elem.setSelectionRange(start, end, dir);
}
InterfaceTests.TextArea.setText = function(pair, text) {
pair.elem.value = text;
}
//#endregion
//#region Defines helpers related to ContentEditable element test setup.
// These functions simply make the basic (within a single text node) tests
// compatible with the more advanced element types; more complex tests may
// be in order. They can probably be shared with design-mode IFrames.
InterfaceTests.ContentEditable = {};
InterfaceTests.ContentEditable.setupElement = function() {
var id = DynamicElements.addEditable();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.ContentEditable(elem);
return {elem: elem, wrapper: wrapper, node: null};
}
InterfaceTests.ContentEditable.setupDummyElement = function() {
var id = DynamicElements.addEditable();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.ContentEditable(elem);
return {elem: elem, wrapper: wrapper, node: null};
}
InterfaceTests.ContentEditable.resetWithText = function(pair, string) {
this.setText(pair, string);
this.setSelectionRange(pair, 0, 0);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.ContentEditable.setCaret = function(pair, index) {
this.setSelectionRange(pair, index, index);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.ContentEditable.getCaret = function(pair) {
var sel = document.getSelection();
if(sel.focusNode.compareDocumentPosition(pair.elem) == 16) { // Contained by
return sel.focusOffset;
} else {
console.warn("Selection during test is in unexpected configuration!");
}
}
InterfaceTests.ContentEditable.setSelectionRange = function(pair, start, end) {
var device = new com.keyman.Device();
device.detect();
var node = pair.elem.childNodes[0];
var sel = document.getSelection();
var setIESelection = function(node, sel, start, end) {
if(start > end) {
// The Range API doesn't allow 'backward' configurations.
var temp = end;
end = start;
start = temp;
}
var range = document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
sel.removeAllRanges();
sel.addRange(range);
}
if(node.nodeType == 3) {
if(device.browser == 'ie') {
setIESelection(node, sel, start, end);
} else {
sel.removeAllRanges();
// Does not work on IE!
try {
sel.setPosition(node, start);
sel.extend(node, end);
} catch (e) {
// Sometimes fails in Firefox during CI. Not sure why.
console.warn("Error occurred while setting Selection via setPosition/extend: " + e.toString());
setIESelection(node, sel, start, end);
}
}
} else {
console.warn("Problem detected when setting up a selection range for content-editables!");
var range = document.createRange();
range.setStart(node, start);
range.setEnd(node, start);
sel.removeAllRanges();
sel.addRange(range);
}
}
InterfaceTests.ContentEditable.setText = function(pair, text) {
pair.elem.innerText = text;
}
//#endregion
//#region Defines helpers related to design-mode IFrame test setup.
// These functions simply make the basic (within a single text node) tests
// compatible with the more advanced element types; more complex tests may
// be in order. They can probably be shared with ContentEditables.
InterfaceTests.DesignIFrame = {};
InterfaceTests.DesignIFrame.InitAsyncElements = function(done) {
// DynamicElements.addDesignIFrame takes an async callback
// triggered upon the IFrame's load.
var obj = this;
var id1 = DynamicElements.addDesignIFrame(function() {
var id2 = DynamicElements.addDesignIFrame(function() {
elem1 = document.getElementById(id1);
elem2 = document.getElementById(id2);
obj.mainPair = {elem: elem1, wrapper: new com.keyman.dom.DesignIFrame(elem1), document: elem1.contentWindow.document};
obj.dummyPair = {elem: elem2, wrapper: new com.keyman.dom.DesignIFrame(elem2), document: elem1.contentWindow.document};
done();
});
});
}
InterfaceTests.DesignIFrame.setupElement = function() {
return this.mainPair;
}
InterfaceTests.DesignIFrame.setupDummyElement = function() {
return this.dummyPair;
}
InterfaceTests.DesignIFrame.resetWithText = function(pair, string) {
this.setText(pair, string);
this.setSelectionRange(pair, 0, 0);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.DesignIFrame.setCaret = function(pair, index) {
this.setSelectionRange(pair, index, index);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.DesignIFrame.getCaret = function(pair) {
var sel = pair.document.getSelection();
if(sel.focusNode.compareDocumentPosition(pair.elem) == 16) { // Contained by
return sel.focusOffset;
} else {
console.warn("Selection during test is in unexpected configuration!");
}
}
InterfaceTests.DesignIFrame.setSelectionRange = function(pair, start, end) {
var device = new com.keyman.Device();
device.detect();
var node = pair.document.documentElement.childNodes[0];
var sel = pair.document.getSelection();
var range;
var setIESelection = function(node, sel, start, end) {
if(start > end) {
// The Range API doesn't allow 'backward' configurations.
var temp = end;
end = start;
start = temp;
}
range = pair.document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
sel.removeAllRanges();
sel.addRange(range);
}
if(node.nodeType == 3) {
if(device.browser == 'ie') {
setIESelection(node, sel, start, end);
} else {
sel.removeAllRanges();
// Does not work on IE!
try {
sel.setPosition(node, start);
sel.extend(node, end);
} catch (e) {
// Sometimes fails in Firefox during CI. Not sure why.
console.warn("Error occurred while setting Selection via setPosition/extend: " + e.toString());
setIESelection(node, sel, start, end);
}
}
} else {
console.warn("Problem detected when setting up a selection range!");
range = pair.document.createRange();
range.setStart(node, start);
range.setEnd(node, start);
sel.removeAllRanges();
sel.addRange(range);
}
}
InterfaceTests.DesignIFrame.setText = function(pair, text) {
pair.document.documentElement.innerText = text;
}
//#endregion
//#region Defines helpers related to TouchAliasElement test setup.
InterfaceTests.TouchAlias = {};
InterfaceTests.TouchAlias.setupElement = function() {
var id = DynamicElements.addTouchAlias();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.TouchAlias(elem);
return {elem: elem, wrapper: wrapper};
}
InterfaceTests.TouchAlias.resetWithText = function(pair, string) {
// This method is tested separately in the touch_aliases.js test case file.
pair.elem.setText(string, 0);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.TouchAlias.setCaret = function(pair, index) {
var text = pair.elem.getText();
// White-box style caret setting.
var pre = text.substr(0, index);
var post = text.substr(index);
pair.elem.__preCaret.textContent = pre;
pair.elem.__postCaret.textContent = post;
// Alternative, black-box-ish way to do this:
// // setTextCaret performs the needed string index translations already, so we need to convert back.
// pair.elem.setTextCaret(text._kmwCodePointToCodeUnit(index));
}
// Implemented for completeness and generality with other tests.
InterfaceTests.TouchAlias.getCaret = function(pair) {
return pair.elem.getCaret();
}
InterfaceTests.TouchAlias.setText = function(pair, text) {
pair.elem.setText(text);
}
//#endregion
//#region Defines helpers related to HTMLInputElement / Input test setup.
InterfaceTests.Mock = {};
InterfaceTests.Mock.setupElement = function() {
return {wrapper: new com.keyman.text.Mock()};
}
InterfaceTests.Mock.resetWithText = function(pair, string) {
pair.wrapper.text = string;
pair.wrapper.caretIndex = 0;
}
// Implemented for completeness and generality with other tests.
InterfaceTests.Mock.setCaret = function(pair, index) {
var text = pair.wrapper.getText();
pair.wrapper.caretIndex = text._kmwCodeUnitToCodePoint(index);
}
// Implemented for completeness and generality with other tests.
InterfaceTests.Mock.getCaret = function(pair) {
return pair.wrapper.getDeadkeyCaret();
}
InterfaceTests.Mock.setText = function(pair, text) {
pair.wrapper.text = text;
}
//#endregion
//#region Defines common test patterns across element tests
InterfaceTests.Tests = {};
// Corresponds to a helper method for certain classes.
InterfaceTests.Tests.getCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
assert.equal(pair.wrapper.getCaret(), 4, "Failed to correctly read the caret's position within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
assert.equal(pair.wrapper.getCaret(), 4, "Failed to correctly read the caret's position within an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 5);
assert.equal(pair.wrapper.getCaret(), 4, "Failed to correctly read the caret's position within a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
// Corresponds to a helper method for certain classes.
InterfaceTests.Tests.getCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 3, 5);
assert.equal(pair.wrapper.getCaret(), 3, "Failed to choose the caret's initial position for forward-selections within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 5, 3);
assert.equal(pair.wrapper.getCaret(), 3, "Failed to choose the caret's initial position for backward-selections within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 6, 10);
assert.equal(pair.wrapper.getCaret(), 3, "Failed to caret's initial position for forward-selections within an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 10, 6);
assert.equal(pair.wrapper.getCaret(), 3, "Failed to caret's initial position for backward-selections within an SMP string");
String.kmwEnableSupplementaryPlane(false);
}
// Corresponds to a helper method for certain classes.
InterfaceTests.Tests.setCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 4, "Failed to correctly set the caret within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
testObj.resetWithText(pair, Apple.smp);
String.kmwEnableSupplementaryPlane(true);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 8, "Failed to correctly set the caret within an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
testObj.resetWithText(pair, Apple.mixed);
String.kmwEnableSupplementaryPlane(true);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 5, "Failed to correctly set the caret within a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
// Corresponds to a helper method for certain classes.
InterfaceTests.Tests.setCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 3, 5);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 4, "Failed to correctly set the caret within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 5, 3);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 4, "Failed to correctly set the caret within a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 6, 10);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 8, "Failed to correctly set the caret within an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 10, 6);
pair.wrapper.setCaret(4);
assert.equal(testObj.getCaret(pair), 8, "Failed to correctly set the caret within an SMP string");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
assert.equal(pair.wrapper.getText(), Apple.normal, "Failed to properly return its stored value: a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
assert.equal(pair.wrapper.getText(), Apple.smp, "Failed to properly return its stored value: a string of SMP characters");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.mixed);
assert.equal(pair.wrapper.getText(), Apple.mixed, "Failed to properly return its stored value: a string with some SMP characters");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 3, 5);
assert.equal(pair.wrapper.getText(), Apple.normal, "Failed to properly return its stored value: a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 6, 10);
assert.equal(pair.wrapper.getText(), Apple.smp, "Failed to properly return its stored value: a string of SMP characters");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 4, 7);
assert.equal(pair.wrapper.getText(), Apple.mixed, "Failed to properly return its stored value: a string with some SMP characters");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextBeforeCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.normal.substr(0, 4), "Failed to properly return correct substring for a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.smp.substr(0, 8), "Failed to properly return correct substring for an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 5);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.mixed.substr(0, 5), "Failed to properly return correct substring for a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextBeforeCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 3, 5);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.normal.substr(0, 3), "Failed simple string, normal-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 5, 3);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.normal.substr(0, 3), "Failed simple string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 6, 10);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.smp.substr(0, 6), "Failed SMP string, normal-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 10, 6);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.smp.substr(0, 6), "Failed SMP string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 4, 7);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.mixed.substr(0, 4), "Failed mixed SMP string, forward-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 7, 4);
assert.equal(pair.wrapper.getTextBeforeCaret(), Apple.mixed.substr(0, 4), "Failed mixed SMP string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextAfterCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.normal.substr(4), "Failed to properly return correct substring for a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.smp.substr(8), "Failed to properly return correct substring for an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 5);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.mixed.substr(5), "Failed to properly return correct substring for a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getTextAfterCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 2, 4);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.normal.substr(4), "Failed simple string, normal-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 4, 2);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.normal.substr(4), "Failed simple string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 4, 8);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.smp.substr(8), "Failed SMP string, normal-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setSelectionRange(pair, 8, 4);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.smp.substr(8), "Failed SMP string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.mixed.substr(5), "Failed mixed SMP string, forward-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 5, 3);
assert.equal(pair.wrapper.getTextAfterCaret(), Apple.mixed.substr(5), "Failed mixed SMP string, reverse-order selection");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.clearSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
assert.equal(pair.wrapper.getText(), Apple.mixed, "String should not be modified on selection: forward-order selection");
pair.wrapper.clearSelection();
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 3) + Apple.mixed.substr(5), "Selected text improperly removed: forward-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 5, 3);
assert.equal(pair.wrapper.getText(), Apple.mixed, "String should not be modified on selection: reverse-order selection");
pair.wrapper.clearSelection();
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 3) + Apple.mixed.substr(5), "Selected text improperly removed: backward-order selection");
String.kmwEnableSupplementaryPlane(false);
}
// Corresponds to a helper method for certain subclasses.
InterfaceTests.Tests.setTextBeforeCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
pair.wrapper.setTextBeforeCaret(Apple.normal.substr(0, 2))
assert.equal(pair.wrapper.getText(), Apple.normal.substr(0, 2) + Apple.normal.substr(4), "Error replacing text in a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
pair.wrapper.setTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 4) + Apple.smp.substr(8), "Error replacing text in an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 5);
pair.wrapper.setTextBeforeCaret(Apple.smp.substr(0, 4))
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 4) + Apple.mixed.substr(5), "Error replacing text in a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.setTextBeforeCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
pair.wrapper.setTextBeforeCaret(Apple.mixed.substr(0, 3));
assert.equal(pair.wrapper.getText(), Apple.mixed, "Actively-selected text was erroneously removed");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
pair.wrapper.setTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 4) + Apple.mixed.substr(3), "Error with text replacement: forward-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 5, 3);
pair.wrapper.setTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 4) + Apple.mixed.substr(3), "Error with text replacement: backward-order selection");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
pair.wrapper.deleteCharsBeforeCaret(1);
assert.equal(pair.wrapper.getText(), Apple.normal.substr(0, 3) + Apple.normal.substr(4), "Error deleting context chars from a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
pair.wrapper.deleteCharsBeforeCaret(1);
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 6) + Apple.smp.substr(8), "Error deleting context chars from an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 4);
pair.wrapper.deleteCharsBeforeCaret(2);
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 1) + Apple.mixed.substr(4), "Error deleting context chars from a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
pair.wrapper.deleteCharsBeforeCaret(7);
assert.equal(pair.wrapper.getText(), "e", "Bounds-check on deletion range failed; context improperly deleted.");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
}
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setSelectionRange(pair, 2, 4);
pair.wrapper.deleteCharsBeforeCaret(1);
assert.equal(pair.wrapper.getText(), Apple.normal.substr(0, 1) + Apple.normal.substr(2), "Selected text erroneously deleted from selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
}
InterfaceTests.Tests.insertTextBeforeCaretNoSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
pair.wrapper.insertTextBeforeCaret(Apple.normal.substr(0, 2))
assert.equal(pair.wrapper.getText(), Apple.normal.substr(0, 4) + Apple.normal.substr(0, 2) + Apple.normal.substr(4), "Error inserting text in a simple string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.smp);
testObj.setCaret(pair, 8);
pair.wrapper.insertTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.smp.substr(0, 8) + Apple.smp.substr(0, 4) + Apple.smp.substr(8), "Error inserting text in an SMP string");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 5);
pair.wrapper.insertTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 5) + Apple.smp.substr(0, 4) + Apple.mixed.substr(5), "Error inserting text in a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.insertTextBeforeCaretWithSelection = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
pair.wrapper.insertTextBeforeCaret("");
assert.equal(pair.wrapper.getText(), Apple.mixed, "Actively-selected text was erroneously removed");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 3, 5);
pair.wrapper.insertTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 3) + Apple.smp.substr(0, 4) + Apple.mixed.substr(3), "Error with text replacement: forward-order selection");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 5, 3);
pair.wrapper.insertTextBeforeCaret(Apple.smp.substr(0, 4));
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 3) + Apple.smp.substr(0, 4) + Apple.mixed.substr(3), "Error with text replacement: backward-order selection");
String.kmwEnableSupplementaryPlane(false);
}
InterfaceTests.Tests.getSelectionOwned = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
// All we need is some basic sample text to get started.
testObj.resetWithText(pair, Apple.mixed);
testObj.setSelectionRange(pair, 0, 7);
assert.isTrue(pair.wrapper.hasSelection(), "Failed to recognize ownership of full, forward-order selection.");
testObj.setSelectionRange(pair, 7, 0);
assert.isTrue(pair.wrapper.hasSelection(), "Failed to recognize ownership of full, backward-order selection.")
testObj.setSelectionRange(pair, 1, 3);
assert.isTrue(pair.wrapper.hasSelection(), "Failed to recognize ownership of partial, forward-order selection.");
testObj.setSelectionRange(pair, 3, 1);
assert.isTrue(pair.wrapper.hasSelection(), "Failed to recognize ownership of partial, backward-order selection.")
}
InterfaceTests.Tests.getSelectionUnowned = function(testObj) {
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
var dummy = testObj.setupDummyElement();
// All we need is some basic sample text to get started.
testObj.resetWithText(pair, Apple.mixed);
testObj.resetWithText(dummy, Apple.mixed);
testObj.setSelectionRange(dummy, 0, 7);
assert.isFalse(pair.wrapper.hasSelection(), "Falsely claimed ownership of full, forward-order selection.");
testObj.setSelectionRange(dummy, 7, 0);
assert.isFalse(pair.wrapper.hasSelection(), "Falsely claimed ownership of full, backward-order selection.")
testObj.setSelectionRange(dummy, 1, 3);
assert.isFalse(pair.wrapper.hasSelection(), "Falsely claimed ownership of partial, forward-order selection.");
testObj.setSelectionRange(dummy, 3, 1);
assert.isFalse(pair.wrapper.hasSelection(), "Falsely claimed ownership of partial, backward-order selection.")
}
InterfaceTests.Tests.deadkeyMaintenance = function(testObj) {
// Rather than messing with keystroke rules, we can directly test the deadkey maintenance logic.
var Apple = InterfaceTests.Strings.Apple;
var pair = testObj.setupElement();
String.kmwEnableSupplementaryPlane(true);
testObj.resetWithText(pair, Apple.mixed);
testObj.setCaret(pair, 1);
pair.wrapper.insertDeadkeyBeforeCaret(1); // unmatched
pair.wrapper.insertDeadkeyBeforeCaret(2); // matched (by next line)
pair.wrapper.deadkeys().isMatch(1, 0, 2);
testObj.setCaret(pair, 5); // True caret point: 4 (one SMP character before this)
pair.wrapper.insertDeadkeyBeforeCaret(3); // unmatched
testObj.setCaret(pair, 3); // After SMP character 1.
pair.wrapper.deadkeys().deleteMatched();
assert.equal(pair.wrapper.deadkeys().count(), 2, "Failed to delete 'matched' deadkey");
// Failure here likely reflects incorrect logic in .getDeadkeyCaret()!
assert.isTrue(pair.wrapper.deadkeys().isMatch(4, 0, 3), "Failed to correctly note position of deadkey after an SMP character!");
pair.wrapper.deadkeys().resetMatched();
pair.wrapper.deleteCharsBeforeCaret(1);
assert.equal(pair.wrapper.deadkeys().count(), 2, "Erroneously deleted deadkey after pre-caret deletions");
assert.isTrue(pair.wrapper.deadkeys().isMatch(1, 0, 1), "Failed to leave deadkey before caret unmoved after pre-caret deletions");
assert.isTrue(pair.wrapper.deadkeys().isMatch(3, 0, 3), "Failed to properly adjust position of post-caret deadkey after pre-caret deletions");
pair.wrapper.deadkeys().resetMatched();
pair.wrapper.insertTextBeforeCaret(Apple.mixed);
assert.isTrue(pair.wrapper.deadkeys().isMatch(1, 0, 1), "Failed to leave deadkey before caret unmoved after text insertion");
assert.isTrue(pair.wrapper.deadkeys().isMatch(8, 0, 3), "Failed to properly adjust position of post-caret deadkey after text insertion");
String.kmwEnableSupplementaryPlane(false);
}
//#endregion
})();
}
describe('Element Input/Output Interfacing', function() {
this.timeout(kmwconfig.timeouts.standard);
before(function() {
fixture.setBase('unit_tests/fixtures');
// Make sure the basic SMP extension hooks exist to prevent errors later.
String.kmwEnableSupplementaryPlane(false);
});
beforeEach(function() {
fixture.load("robustAttachment.html");
})
afterEach(function() {
fixture.cleanup();
});
describe('Wrapper: HTMLInputElement', function() {
/**
* The design of these tests is to ensure that all caret handling works correctly,
* independently of other methods. Other tests will then rely upon these methods
* to simplify their code.
*/
describe('Caret Handling', function() {
describe('setCaret', function() {
it('correctly places the caret (no prior selection)', function() {
InterfaceTests.Tests.setCaretNoSelection(InterfaceTests.Input);
});
it('correctly places the caret (prior selection)', function() {
InterfaceTests.Tests.setCaretWithSelection(InterfaceTests.Input);
});
});
describe('getCaret', function() {
it('correctly reports the position of the caret (no selection)', function() {
InterfaceTests.Tests.getCaretNoSelection(InterfaceTests.Input);
});
it('correctly reports the position of the caret (active selection)', function() {
InterfaceTests.Tests.getCaretWithSelection(InterfaceTests.Input);
});
});
});
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.Input);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextWithSelection(InterfaceTests.Input);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.Input);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretWithSelection(InterfaceTests.Input);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.Input);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretWithSelection(InterfaceTests.Input);
});
});
});
describe('Text Mutation', function() {
describe('clearSelection', function() {
it('properly deletes selected text', function() {
InterfaceTests.Tests.clearSelection(InterfaceTests.Input);
});
});
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.Input);
});
it("correctly deletes characters from 'context' (with active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.Input);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.Input);
});
it("correctly replaces the element's 'context' (with active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.Input);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.Input);
});
});
});
// TODO: (if possible) Implement support for scroll-restoration checks.
describe('Wrapper: HTMLTextAreaElement', function() {
/**
* The design of these tests is to ensure that all caret handling works correctly,
* independently of other methods. Other tests will then rely upon these methods
* to simplify their code.
*/
describe('Caret Handling', function() {
describe('setCaret', function() {
it('correctly places the caret (no prior selection)', function() {
InterfaceTests.Tests.setCaretNoSelection(InterfaceTests.TextArea);
});
it('correctly places the caret (prior selection)', function() {
InterfaceTests.Tests.setCaretWithSelection(InterfaceTests.TextArea);
});
});
describe('getCaret', function() {
it('correctly reports the position of the caret (no selection)', function() {
InterfaceTests.Tests.getCaretNoSelection(InterfaceTests.TextArea);
});
it('correctly reports the position of the caret (active selection)', function() {
InterfaceTests.Tests.getCaretWithSelection(InterfaceTests.TextArea);
});
});
});
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.TextArea);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextWithSelection(InterfaceTests.TextArea);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.TextArea);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretWithSelection(InterfaceTests.TextArea);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.TextArea);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretWithSelection(InterfaceTests.TextArea);
});
});
});
describe('Text Mutation', function() {
describe('clearSelection', function() {
it('properly deletes selected text', function() {
InterfaceTests.Tests.clearSelection(InterfaceTests.TextArea);
});
});
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.TextArea);
});
it("correctly deletes characters from 'context' (with active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.TextArea);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.TextArea);
});
it("correctly replaces the element's 'context' (with active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.TextArea);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.TextArea);
});
});
});
/**
* TODO: Design and implement some 'complex', cross-Node selection tests.
*/
describe('Wrapper: Content-Editable Elements (using DIVs)', function() {
before(function() {
// These tests require use of KMW's device-detection functionality.
assert.isFalse(com.keyman.karma.DEVICE_DETECT_FAILURE, "Cannot run due to device detection failure.");
})
describe('Caret Handling', function() {
describe('hasSelection', function() {
it('correctly recognizes Selection ownership', function () {
InterfaceTests.Tests.getSelectionOwned(InterfaceTests.ContentEditable);
});
it('correctly rejects lack of Selection ownership', function () {
InterfaceTests.Tests.getSelectionUnowned(InterfaceTests.ContentEditable);
});
// Need to design a test (and necessary helpers!) for a 'partial ownership rejection' test.
});
});
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.ContentEditable);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextWithSelection(InterfaceTests.ContentEditable);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.ContentEditable);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretWithSelection(InterfaceTests.ContentEditable);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.ContentEditable);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretWithSelection(InterfaceTests.ContentEditable);
});
});
});
describe('Text Mutation', function() {
describe('clearSelection', function() {
it('properly deletes selected text', function() {
InterfaceTests.Tests.clearSelection(InterfaceTests.ContentEditable);
});
});
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.ContentEditable);
});
it("correctly deletes characters from 'context' (with active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.ContentEditable);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.ContentEditable);
});
it("correctly replaces the element's 'context' (with active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.ContentEditable);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.ContentEditable);
});
});
});
/**
* TODO: Design and implement some 'complex', cross-doc selection tests if possible.
*/
describe('Wrapper: Design-Mode IFrames', function() {
// We're asynchronously loading IFrames, and sequentially at that.
// We'll need a larger timeout.
this.timeout(kmwconfig.timeouts.scriptLoad);
before(function() {
// These tests require use of KMW's device-detection functionality.
assert.isFalse(com.keyman.karma.DEVICE_DETECT_FAILURE, "Cannot run due to device detection failure.");
})
beforeEach(function(done) {
// Per-test creation of reg. pair and dummy elements, since IFrames are async.
// Relies on the main-level's renewal of the overall fixture to be processed first.
InterfaceTests.DesignIFrame.InitAsyncElements(done);
});
/**
* Sadly, JavaScript appears to disallow programmatically setting an outer document's selection
* to Nodes inside an iframe's document, which would be needed to properly emulate actual use-case
* selections we'd want to test with these methods. :(
*/
// describe.skip('Caret Handling', function() {
// describe('hasSelection', function() {
// it('correctly recognizes Selection ownership', function () {
// InterfaceTests.Tests.getSelectionOwned(InterfaceTests.DesignIFrame);
// });
// it('correctly rejects lack of Selection ownership', function () {
// InterfaceTests.Tests.getSelectionUnowned(InterfaceTests.DesignIFrame);
// });
// // Need to design a test (and necessary helpers!) for a 'partial ownership rejection' test.
// });
// });
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.DesignIFrame);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextWithSelection(InterfaceTests.DesignIFrame);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.DesignIFrame);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretWithSelection(InterfaceTests.DesignIFrame);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.DesignIFrame);
});
it('correctly returns text (with active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretWithSelection(InterfaceTests.DesignIFrame);
});
});
});
describe('Text Mutation', function() {
describe('clearSelection', function() {
it('properly deletes selected text', function() {
InterfaceTests.Tests.clearSelection(InterfaceTests.DesignIFrame);
});
});
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.DesignIFrame);
});
it("correctly deletes characters from 'context' (with active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection(InterfaceTests.DesignIFrame);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.DesignIFrame);
});
it("correctly replaces the element's 'context' (with active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretWithSelection(InterfaceTests.DesignIFrame);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.DesignIFrame);
});
});
});
/**
* TODO: Design and implement some 'complex', cross-Node selection tests.
*/
describe('Wrapper: Touch-Alias Elements', function() {
// Always has an active caret pos, so there's never a rejection.
// However, never has an actual SELECTION, since touch aliases don't support those yet.
// describe('Caret Handling', function() {
// describe('hasSelection', function() {
// it('correctly reports an active selection', function () {
// InterfaceTests.Tests.getSelectionOwned(InterfaceTests.TouchAlias);
// });
// });
// });
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.TouchAlias);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.TouchAlias);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.TouchAlias);
});
});
});
describe('Text Mutation', function() {
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.TouchAlias);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.TouchAlias);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.TouchAlias);
});
});
});
describe('The "Mock" output target', function() {
// Unique to the Mock type - element interface cloning tests. Is element state properly copied?
// As those require a very different setup, they're in the target_mocks.js test case file instead.
describe('Text Retrieval', function(){
describe('getText', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextNoSelection(InterfaceTests.Mock);
});
});
describe('getTextBeforeCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextBeforeCaretNoSelection(InterfaceTests.Mock);
});
});
describe('getTextAfterCaret', function() {
it('correctly returns text (no active selection)', function() {
InterfaceTests.Tests.getTextAfterCaretNoSelection(InterfaceTests.Mock);
});
});
});
describe('Text Mutation', function() {
describe('deleteCharsBeforeCaret', function() {
it("correctly deletes characters from 'context' (no active selection)", function() {
InterfaceTests.Tests.deleteCharsBeforeCaretNoSelection(InterfaceTests.Mock);
});
});
describe('insertTextBeforeCaret', function() {
it("correctly replaces the element's 'context' (no active selection)", function() {
InterfaceTests.Tests.insertTextBeforeCaretNoSelection(InterfaceTests.Mock);
});
});
it('correctly maintains deadkeys', function() {
InterfaceTests.Tests.deadkeyMaintenance(InterfaceTests.TouchAlias);
});
});
});
});