mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-07 22:47:29 +00:00
Implements Mock-oriented unit-testing.
This commit is contained in:
parent
d5973a1723
commit
099c23cdb1
4 changed files with 190 additions and 7 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
156
web/unit_tests/cases/target_mocks.js
Normal file
156
web/unit_tests/cases/target_mocks.js
Normal 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue