Implements Mock-oriented unit-testing.

This commit is contained in:
Joshua A. Horton 2019-02-19 15:19:26 +07:00
parent d5973a1723
commit 099c23cdb1
4 changed files with 190 additions and 7 deletions

View file

@ -68,9 +68,16 @@ namespace com.keyman.dom {
}
setCaret(caret: number) {
let domCaret = this.root.value._kmwCodePointToCodeUnit(caret);
this.root.setSelectionRange(domCaret, domCaret);
this.processedSelectionEnd = caret;
this.setSelection(caret, caret);
}
setSelection(start: number, end: number) {
let domStart = this.root.value._kmwCodePointToCodeUnit(start);
let domEnd = this.root.value._kmwCodePointToCodeUnit(end);
this.root.setSelectionRange(domStart, domEnd);
this.processedSelectionStart = start;
this.processedSelectionEnd = end;
}
getTextBeforeCaret(): string {

View file

@ -75,9 +75,16 @@ namespace com.keyman.dom {
}
setCaret(caret: number) {
let domCaret = this.root.value._kmwCodePointToCodeUnit(caret);
this.root.setSelectionRange(domCaret, domCaret);
this.processedSelectionEnd = caret;
this.setSelection(caret, caret);
}
setSelection(start: number, end: number) {
let domStart = this.root.value._kmwCodePointToCodeUnit(start);
let domEnd = this.root.value._kmwCodePointToCodeUnit(end);
this.root.setSelectionRange(domStart, domEnd);
this.processedSelectionStart = start;
this.processedSelectionEnd = end;
}
getTextBeforeCaret(): string {

View file

@ -33,6 +33,13 @@ namespace com.keyman.text {
return this.o < other.o;
}
clone(): Deadkey {
let dk = new Deadkey(this.p, this.d);
dk.o = this.o;
return dk;
}
/**
* Sorts the deadkeys in reverse order.
*/
@ -57,7 +64,13 @@ namespace com.keyman.text {
clone(): DeadkeyTracker {
let dkt = new DeadkeyTracker();
dkt.dks = this.toSortedArray();
let dks = this.toSortedArray();
// Make sure to clone the deadkeys themselves - the Deadkey object is mutable.
dkt.dks = [];
dks.forEach(function(value: Deadkey) {
dkt.dks.push(value.clone());
});
return dkt;
}

View file

@ -0,0 +1,156 @@
var assert = chai.assert;
var MockTests;
// Define common interface testing functions that can be run upon the OutputTarget interface.
if(typeof MockTests == 'undefined') {
MockTests = {};
(function(){
// Makes a nice Unicode shortcut.
var u = toSupplementaryPairString;
MockTests.Apple = {};
MockTests.Apple.normal = 'apple';
// Built in-line via function. Looks functionally equivalent to "apple", but with SMP characters.
MockTests.Apple.smp = u(0x1d5ba)+u(0x1d5c9)+u(0x1d5c9)+u(0x1d5c5)+u(0x1d5be);
MockTests.Apple.mixed = 'a'+u(0x1d5c9)+'p'+'l'+u(0x1d5be);
MockTests.Deadkeys = {};
MockTests.Deadkeys.initial = [
{d: 1, p: 2}, // After the 'p'-ish SMP character of Apple.mixed.
{d: 0, p: 3} // After the normal 'p' character of Apple.mixed.
];
//#region Defines helpers related to HTMLInputElement / Input test setup.
MockTests.initBase = function() {
var id = DynamicElements.addInput();
var elem = document.getElementById(id);
var wrapper = new com.keyman.dom.Input(elem);
return wrapper;
}
MockTests.applyDeadkeys = function(base, dks) {
dks.forEach(function(val) {
base.setCaret(val.p);
base.insertDeadkeyBeforeCaret(val.d);
});
}
MockTests.setupBase = function(selStart, selEnd) {
// Defines initial selection range.
if(!selStart) {
selStart = 0;
}
if(!selEnd) {
selEnd = selStart;
}
let base = this.initBase();
base.root.value = MockTests.Apple.mixed;
this.applyDeadkeys(base, this.Deadkeys.initial);
// Set the requested selection range.
base.setSelection(selStart, selEnd);
return base;
}
//#endregion
})();
}
describe('OutputTarget Mocking', 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(true);
});
beforeEach(function() {
fixture.load("robustAttachment.html");
})
afterEach(function() {
fixture.cleanup();
});
after(function() {
String.kmwEnableSupplementaryPlane(false);
})
describe('The "Mock" output target', function() {
// Unique to the Mock type - element interface cloning tests. Is element state properly copied?
// TODO: This.
// Test with Input / TextArea source
// - with/without pre-existing deadkeys
// - with/without existing selected text in the source element
// - text operations on the Mock are not aliased / do not affect the source element.
describe('Initialization', function() {
it('copies an existing OutputTarget without a text selection', function() {
var base = MockTests.setupBase(4);
var mock = com.keyman.text.Mock.from(base);
assert.equal(mock.getText(), MockTests.Apple.mixed);
assert.deepEqual(mock.deadkeys(), base.deadkeys());
});
it('copies an existing OutputTarget with a text selection', function() {
var base = MockTests.setupBase(4, 5);
var mock = com.keyman.text.Mock.from(base);
// The selection should appear to be automatically deleted, as any text mutation
// by KMW would automatically erase the text anyway.
assert.equal(mock.getText(), MockTests.Apple.mixed.substr(0, 5));
assert.deepEqual(mock.deadkeys(), base.deadkeys());
});
});
describe('Aliasing', function() {
// is properly independent of the source element with no cross-effects
// with/without deadkeys
it('is not affected by mutation of the source element', function() {
// Already-verified code
var base = MockTests.setupBase(4);
var mock = com.keyman.text.Mock.from(base);
var baseInitDks = base.deadkeys().clone();
// Now for the actual test.
var dk = MockTests.Deadkeys.initial;
// Note - we selectively match and remove only ONE of the deadkeys. (Naturally, the one closer to the caret.)
base.hasDeadkeyMatch(4-dk[1].p, dk[1].d);
base.deadkeys().deleteMatched();
base.deleteCharsBeforeCaret(2);
assert.notDeepEqual(base.deadkeys(), baseInitDks, 'OutputTarget deadkey return is not a proper deep-copy');
assert.equal(mock.getText(), MockTests.Apple.mixed);
assert.deepEqual(mock.deadkeys(), baseInitDks);
});
it('does not affect the source element when mutated', function() {
// Already-verified code
var base = MockTests.setupBase(4);
var mock = com.keyman.text.Mock.from(base);
var baseInitDks = base.deadkeys().clone();
// Now for the actual test.
var dk = MockTests.Deadkeys.initial;
// Note - we selectively match and remove only ONE of the deadkeys. (Naturally, the one closer to the caret.)
mock.hasDeadkeyMatch(4-dk[1].p, dk[1].d);
mock.deadkeys().deleteMatched();
mock.deleteCharsBeforeCaret(2);
assert.notDeepEqual(mock.deadkeys(), baseInitDks);
assert.equal(base.getText(), MockTests.Apple.mixed);
assert.deepEqual(base.deadkeys(), baseInitDks);
});
});
});
});