mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-11-20 10:33:36 +00:00
1800 lines
47 KiB
HTML
1800 lines
47 KiB
HTML
|
<!DOCTYPE HTML>
|
||
|
<html>
|
||
|
<!--
|
||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1137557
|
||
|
-->
|
||
|
<head>
|
||
|
<title>Test for new API arguments accepting D3E properties</title>
|
||
|
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||
|
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||
|
</head>
|
||
|
<body>
|
||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1137557">Mozilla Bug 1137557</a>
|
||
|
<p id="display"></p>
|
||
|
<pre id="test">
|
||
|
<script class="testbody" type="application/javascript;version=1.7">
|
||
|
|
||
|
inputmethod_setup(function() {
|
||
|
runTest();
|
||
|
});
|
||
|
|
||
|
let gEventDetails = [];
|
||
|
let gCurrentValue = '';
|
||
|
let gTestDescription = '';
|
||
|
|
||
|
let appFrameScript = function appFrameScript() {
|
||
|
let input = content.document.body.firstElementChild;
|
||
|
|
||
|
input.focus();
|
||
|
|
||
|
function sendEventDetail(evt) {
|
||
|
var eventDetail;
|
||
|
|
||
|
switch (evt.type) {
|
||
|
case 'compositionstart':
|
||
|
case 'compositionupdate':
|
||
|
case 'compositionend':
|
||
|
eventDetail = {
|
||
|
type: evt.type,
|
||
|
value: input.value,
|
||
|
data: evt.data
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
case 'input':
|
||
|
eventDetail = {
|
||
|
type: evt.type,
|
||
|
value: input.value
|
||
|
};
|
||
|
break;
|
||
|
|
||
|
default: // keyboard events
|
||
|
eventDetail = {
|
||
|
type: evt.type,
|
||
|
charCode: evt.charCode,
|
||
|
keyCode: evt.keyCode,
|
||
|
key: evt.key,
|
||
|
code: evt.code,
|
||
|
location: evt.location,
|
||
|
repeat: evt.repeat,
|
||
|
value: input.value,
|
||
|
shift: evt.getModifierState('Shift'),
|
||
|
capsLock: evt.getModifierState('CapsLock'),
|
||
|
control: evt.getModifierState('Control'),
|
||
|
alt: evt.getModifierState('Alt')
|
||
|
};
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
sendAsyncMessage('test:eventDetail', eventDetail);
|
||
|
}
|
||
|
|
||
|
input.addEventListener('compositionstart', sendEventDetail);
|
||
|
input.addEventListener('compositionupdate', sendEventDetail);
|
||
|
input.addEventListener('compositionend', sendEventDetail);
|
||
|
input.addEventListener('input', sendEventDetail);
|
||
|
input.addEventListener('keydown', sendEventDetail);
|
||
|
input.addEventListener('keypress', sendEventDetail);
|
||
|
input.addEventListener('keyup', sendEventDetail);
|
||
|
};
|
||
|
|
||
|
function waitForInputContextChange() {
|
||
|
return new Promise((resolve) => {
|
||
|
navigator.mozInputMethod.oninputcontextchange = resolve;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function assertEventDetail(expectedDetails, testName) {
|
||
|
is(gEventDetails.length, expectedDetails.length,
|
||
|
testName + ' expects ' + expectedDetails.map(d => d.type).join(', ') + ' events, got ' + gEventDetails.map(d => d.type).join(', '));
|
||
|
|
||
|
expectedDetails.forEach((expectedDetail, j) => {
|
||
|
for (let key in expectedDetail) {
|
||
|
is(gEventDetails[j][key], expectedDetail[key],
|
||
|
testName + ' expects ' + key + ' of ' + gEventDetails[j].type + ' to be equal to ' + expectedDetail[key]);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function sendKeyAndAssertResult(testdata) {
|
||
|
var dict = testdata.dict;
|
||
|
var testName = gTestDescription + 'sendKey(' + JSON.stringify(dict) + ')';
|
||
|
var promise = navigator.mozInputMethod.inputcontext.sendKey(dict);
|
||
|
|
||
|
if (testdata.expectedReject) {
|
||
|
promise = promise
|
||
|
.then(() => {
|
||
|
ok(false, testName + ' should not resolve.');
|
||
|
}, (e) => {
|
||
|
ok(true, testName + ' rejects.');
|
||
|
ok(e instanceof testdata.expectedReject, 'Reject with type.');
|
||
|
})
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
promise = promise
|
||
|
.then((res) => {
|
||
|
is(res, true,
|
||
|
testName + ' should resolve to true.');
|
||
|
|
||
|
var expectedEventDetail = [];
|
||
|
|
||
|
var expectedValues = testdata.expectedValues;
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keydown',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: expectedValues.location ? expectedValues.location : 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
|
||
|
if (testdata.expectedKeypress) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keypress',
|
||
|
key: expectedValues.key,
|
||
|
charCode: expectedValues.charCode,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
|
||
|
location: expectedValues.location ? expectedValues.location : 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (testdata.expectedInput) {
|
||
|
switch (testdata.expectedInput) {
|
||
|
case 'Enter':
|
||
|
gCurrentValue += '\n';
|
||
|
break;
|
||
|
case 'Backspace':
|
||
|
gCurrentValue =
|
||
|
gCurrentValue.substr(0, gCurrentValue.length - 1);
|
||
|
break;
|
||
|
default:
|
||
|
gCurrentValue += testdata.expectedInput;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'input',
|
||
|
value: gCurrentValue
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (!testdata.expectedRepeat) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keyup',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: expectedValues.location ? expectedValues.location : 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
assertEventDetail(expectedEventDetail, testName);
|
||
|
gEventDetails = [];
|
||
|
}, (e) => {
|
||
|
ok(false, testName + ' should not reject. ' + e);
|
||
|
});
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
function runSendKeyAlphabetTests() {
|
||
|
gTestDescription = 'runSendKeyAlphabetTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test the plain alphabets
|
||
|
var codeA = 'A'.charCodeAt(0);
|
||
|
for (var i = 0; i < 26; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = codeA + i;
|
||
|
let code = 'Key' + String.fromCharCode(keyCode);
|
||
|
|
||
|
[String.fromCharCode(keyCode),
|
||
|
String.fromCharCode(keyCode).toLowerCase()]
|
||
|
.forEach((chr) => {
|
||
|
// Test plain alphabet
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with keyCode set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with keyCode set to keyCode + 1,
|
||
|
// expects keyCode to follow key value and ignore the incorrect value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode + 1
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set to Digit1,
|
||
|
// expects keyCode to follow key value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'Digit1'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'Digit1',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with keyCode set to DOM_VK_1,
|
||
|
// expects keyCode to follow key value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: KeyboardEvent.DOM_VK_1
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set to Digit1
|
||
|
// and keyCode set to DOM_VK_1,
|
||
|
// expects keyCode to follow key value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'Digit1',
|
||
|
keyCode: KeyboardEvent.DOM_VK_1
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'Digit1',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyNumberTests() {
|
||
|
gTestDescription = 'runSendKeyNumberTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test numbers
|
||
|
var code0 = '0'.charCodeAt(0);
|
||
|
for (var i = 0; i < 10; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = code0 + i;
|
||
|
let chr = String.fromCharCode(keyCode);
|
||
|
|
||
|
// Test plain number
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain number with keyCode set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain number with keyCode set to keyCode + 1,
|
||
|
// expects keyCode to follow key value and ignore the incorrect value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode + 1
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain number with code set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'Digit' + chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'Digit' + chr,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain upper caps alphabet with code set to KeyA,
|
||
|
// expects keyCode to follow key value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain upper caps alphabet with code set to KeyA,
|
||
|
// and keyCode set to DOM_VK_A.
|
||
|
// expects keyCode to follow key value.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyDvorakTests() {
|
||
|
gTestDescription = 'runSendKeyDvorakTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test Dvorak layout emulation
|
||
|
var qwertyCodeForDvorakKeys = [
|
||
|
'KeyR', 'KeyT', 'KeyY', 'KeyU', 'KeyI', 'KeyO', 'KeyP',
|
||
|
'KeyA', 'KeyS', 'KeyD', 'KeyF', 'KeyG',
|
||
|
'KeyH', 'KeyJ', 'KeyK', 'KeyL', 'Semicolon',
|
||
|
'KeyX', 'KeyC', 'KeyV', 'KeyB', 'KeyN',
|
||
|
'KeyM', 'Comma', 'Period', 'Slash'];
|
||
|
var dvorakKeys = 'PYFGCRL' +
|
||
|
'AOEUIDHTNS' +
|
||
|
'QJKXBMWVZ';
|
||
|
for (var i = 0; i < dvorakKeys.length; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = dvorakKeys.charCodeAt(i);
|
||
|
let code = qwertyCodeForDvorakKeys[i];
|
||
|
|
||
|
[dvorakKeys.charAt(i), dvorakKeys.charAt(i).toLowerCase()]
|
||
|
.forEach((chr) => {
|
||
|
// Test alphabet with code set to Qwerty code,
|
||
|
// expects keyCode to follow key value.
|
||
|
// (This is *NOT* the expected scenario for emulating a Dvorak keyboard,
|
||
|
// even though expected results are the same.)
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test alphabet with code set to Qwerty code and keyCode set,
|
||
|
// expects keyCode to follow key/keyCode value.
|
||
|
// (This is the expected scenario for emulating a Dvorak keyboard)
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var qwertyCodeForDvorakSymbols = [
|
||
|
'Minus', 'Equal',
|
||
|
'KeyQ', 'KeyW', 'KeyE', 'BracketLeft', 'BracketRight', 'Backslash',
|
||
|
'Quote', 'KeyZ'];
|
||
|
|
||
|
var shiftDvorakSymbols = '{}\"<>?+|_:';
|
||
|
var dvorakSymbols = '[]\',./=\\-;';
|
||
|
var dvorakSymbolsKeyCodes = [
|
||
|
KeyboardEvent.DOM_VK_OPEN_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_CLOSE_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_QUOTE,
|
||
|
KeyboardEvent.DOM_VK_COMMA,
|
||
|
KeyboardEvent.DOM_VK_PERIOD,
|
||
|
KeyboardEvent.DOM_VK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_EQUALS,
|
||
|
KeyboardEvent.DOM_VK_BACK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_HYPHEN_MINUS,
|
||
|
KeyboardEvent.DOM_VK_SEMICOLON
|
||
|
];
|
||
|
|
||
|
for (var i = 0; i < dvorakSymbols.length; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = dvorakSymbolsKeyCodes[i];
|
||
|
let code = qwertyCodeForDvorakSymbols[i];
|
||
|
|
||
|
[dvorakSymbols.charAt(i), shiftDvorakSymbols.charAt(i)]
|
||
|
.forEach((chr) => {
|
||
|
// Test symbols with code set to Qwerty code,
|
||
|
// expects keyCode to be 0.
|
||
|
// (This is *NOT* the expected scenario for emulating a Dvorak keyboard)
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test alphabet with code set to Qwerty code and keyCode set,
|
||
|
// expects keyCode to follow keyCode value.
|
||
|
// (This is the expected scenario for emulating a Dvorak keyboard)
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyDigitKeySymbolsTests() {
|
||
|
gTestDescription = 'runSendKeyDigitKeySymbolsTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
var digitKeySymbols = ')!@#$%^&*(';
|
||
|
for (var i = 0; i < digitKeySymbols.length; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = KeyboardEvent['DOM_VK_' + i];
|
||
|
let chr = digitKeySymbols.charAt(i);
|
||
|
let code = 'Digit' + i;
|
||
|
|
||
|
// Test plain symbol
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '', keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with keyCode set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set to KeyA,
|
||
|
// expects keyCode to be 0.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with keyCode set to DOM_VK_A,
|
||
|
// expects keyCode to follow the keyCode set.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set to KeyA
|
||
|
// expects keyCode to follow the keyCode set.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyUSKeyboardSymbolsTests() {
|
||
|
gTestDescription = 'runSendKeyUSKeyboardSymbolsTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test printable symbols on US Keyboard
|
||
|
var symbols = ' ;:=+,<-_.>/?`~[{\\|]}\'\"';
|
||
|
var symbolKeyCodes = [
|
||
|
KeyboardEvent.DOM_VK_SPACE,
|
||
|
KeyboardEvent.DOM_VK_SEMICOLON,
|
||
|
KeyboardEvent.DOM_VK_SEMICOLON,
|
||
|
KeyboardEvent.DOM_VK_EQUALS,
|
||
|
KeyboardEvent.DOM_VK_EQUALS,
|
||
|
KeyboardEvent.DOM_VK_COMMA,
|
||
|
KeyboardEvent.DOM_VK_COMMA,
|
||
|
KeyboardEvent.DOM_VK_HYPHEN_MINUS,
|
||
|
KeyboardEvent.DOM_VK_HYPHEN_MINUS,
|
||
|
KeyboardEvent.DOM_VK_PERIOD,
|
||
|
KeyboardEvent.DOM_VK_PERIOD,
|
||
|
KeyboardEvent.DOM_VK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_BACK_QUOTE,
|
||
|
KeyboardEvent.DOM_VK_BACK_QUOTE,
|
||
|
KeyboardEvent.DOM_VK_OPEN_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_OPEN_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_BACK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_BACK_SLASH,
|
||
|
KeyboardEvent.DOM_VK_CLOSE_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_CLOSE_BRACKET,
|
||
|
KeyboardEvent.DOM_VK_QUOTE,
|
||
|
KeyboardEvent.DOM_VK_QUOTE
|
||
|
];
|
||
|
var symbolCodes = [
|
||
|
'Space',
|
||
|
'Semicolon',
|
||
|
'Semicolon',
|
||
|
'Equal',
|
||
|
'Equal',
|
||
|
'Comma',
|
||
|
'Comma',
|
||
|
'Minus',
|
||
|
'Minus',
|
||
|
'Period',
|
||
|
'Period',
|
||
|
'Slash',
|
||
|
'Slash',
|
||
|
'Backquote',
|
||
|
'Backquote',
|
||
|
'BracketLeft',
|
||
|
'BracketLeft',
|
||
|
'Backslash',
|
||
|
'Backslash',
|
||
|
'BracketRight',
|
||
|
'BracketRight',
|
||
|
'Quote',
|
||
|
'Quote'
|
||
|
];
|
||
|
for (var i = 0; i < symbols.length; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = symbolKeyCodes[i];
|
||
|
let chr = symbols.charAt(i);
|
||
|
let code = symbolCodes[i];
|
||
|
|
||
|
// Test plain symbol
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with keyCode set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set
|
||
|
// expects keyCode to be 0.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set to KeyA,
|
||
|
// expects keyCode to be 0.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with keyCode set to DOM_VK_A,
|
||
|
// expects keyCode to follow the keyCode set.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain symbol with code set to KeyA
|
||
|
// expects keyCode to follow the keyCode set.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyGreekLettersTests() {
|
||
|
gTestDescription = 'runSendKeyGreekLettersTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test Greek letters
|
||
|
var greekLetters =
|
||
|
'\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c' +
|
||
|
'\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9' +
|
||
|
'\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc' +
|
||
|
'\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9' +
|
||
|
'\u03c2';
|
||
|
var greekLettersLayoutMap =
|
||
|
'ABGDEZHUIKLMNJOPRSTYFXCVABGDEZHUIKLMNJOPRSTYFXCVQ';
|
||
|
for (var i = 0; i < greekLetters.length; i++) {
|
||
|
// callbacks in then() are deferred; must only reference these block-scoped
|
||
|
// variable instead of i.
|
||
|
let keyCode = greekLettersLayoutMap.charCodeAt(i);
|
||
|
let chr = greekLetters.charAt(i);
|
||
|
let code = 'Key' + greekLettersLayoutMap.charAt(i);
|
||
|
|
||
|
// Test plain alphabet
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with keyCode set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: '',
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set,
|
||
|
// expects keyCode to be 0.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set to Digit1,
|
||
|
// expects keyCode to be 0.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'Digit1'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'Digit1',
|
||
|
keyCode: 0,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test plain alphabet with code set to Digit1,
|
||
|
// and keyCode set to DOM_VK_A.
|
||
|
// expects keyCode to follow the keyCode set.
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: 'Digit1',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: 'Digit1',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyEnterTests() {
|
||
|
gTestDescription = 'runSendKeyEnterTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test Enter with code unset
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: 'Enter'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: '\n',
|
||
|
expectedValues: {
|
||
|
key: 'Enter', code: '',
|
||
|
keyCode: KeyboardEvent.DOM_VK_RETURN,
|
||
|
charCode: 0
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test Enter with code set
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: 'Enter',
|
||
|
code: 'Enter'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: '\n',
|
||
|
expectedValues: {
|
||
|
key: 'Enter', code: 'Enter',
|
||
|
keyCode: KeyboardEvent.DOM_VK_RETURN,
|
||
|
charCode: 0
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Test Enter with keyCode explict set to zero
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: 'Enter',
|
||
|
keyCode: 0
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedValues: {
|
||
|
key: 'Enter', code: '',
|
||
|
keyCode: 0,
|
||
|
charCode: 0
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyNumpadTests() {
|
||
|
gTestDescription = 'runSendKeyNumpadTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
var tests = [];
|
||
|
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||
|
.forEach(function(key) {
|
||
|
let charCode = key.charCodeAt(0);
|
||
|
|
||
|
tests.push({
|
||
|
dict: {
|
||
|
key: key,
|
||
|
code: 'Numpad' + key
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: key,
|
||
|
expectedValues: {
|
||
|
key: key, code: 'Numpad' + key,
|
||
|
keyCode: charCode, charCode: charCode,
|
||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
[['+', 'NumpadAdd'],
|
||
|
[',', 'NumpadComma'],
|
||
|
['.', 'NumpadDecimal'],
|
||
|
['.', 'NumpadComma'], // Locale-specific NumpadComma
|
||
|
[',', 'NumpadDecimal'], // Locale-specific NumpadDecimal
|
||
|
['/', 'NumpadDivide'],
|
||
|
['=', 'NumpadEqual'],
|
||
|
// ['#', 'NumpadHash'], // Not supported yet.
|
||
|
['*', 'NumpadMultiply'],
|
||
|
['(', 'NumpadParenLeft'],
|
||
|
[')', 'NumpadParenRight'],
|
||
|
// ['*', 'NumpadStar'], // Not supported yet.
|
||
|
['-', 'NumpadSubtract']].forEach(function([key, code]) {
|
||
|
tests.push({
|
||
|
dict: {
|
||
|
key: key,
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: key,
|
||
|
expectedValues: {
|
||
|
key: key, code: code, keyCode: 0, charCode: key.charCodeAt(0),
|
||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
[
|
||
|
'NumpadComma', // Locale-specific NumpadComma -- outputs nothing
|
||
|
'NumpadClear',
|
||
|
'NumpadClearEntry',
|
||
|
'NumpadMemoryAdd',
|
||
|
'NumpadMemoryClear',
|
||
|
'NumpadMemoryRecall',
|
||
|
'NumpadMemoryStore',
|
||
|
'NumpadMemorySubtract'
|
||
|
].forEach(function(code) {
|
||
|
tests.push({
|
||
|
dict: {
|
||
|
key: 'Unidentified',
|
||
|
code: code
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedValues: {
|
||
|
key: 'Unidentified', code: code, keyCode: 0, charCode: 0,
|
||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
tests.push({
|
||
|
dict: {
|
||
|
key: 'Enter',
|
||
|
code: 'NumpadEnter'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: '\n',
|
||
|
expectedValues: {
|
||
|
key: 'Enter', code: 'NumpadEnter',
|
||
|
keyCode: KeyboardEvent.DOM_VK_RETURN, charCode: 0,
|
||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tests.push({
|
||
|
dict: {
|
||
|
key: 'Backspace',
|
||
|
code: 'NumpadBackspace'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: 'Backspace', // Special value
|
||
|
expectedValues: {
|
||
|
key: 'Backspace', code: 'NumpadBackspace',
|
||
|
keyCode: KeyboardEvent.DOM_VK_BACK_SPACE, charCode: 0,
|
||
|
location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tests.forEach((test) => {
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult(test);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runSendKeyRejectionTests() {
|
||
|
gTestDescription = 'runSendKeyRejectionTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: undefined,
|
||
|
expectedReject: TypeError
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function setCompositionAndAssertResult(testdata) {
|
||
|
var dict = testdata.dict;
|
||
|
var testName;
|
||
|
var promise;
|
||
|
|
||
|
if (dict) {
|
||
|
testName = gTestDescription +
|
||
|
'setComposition(' + testdata.text +
|
||
|
', undefined, undefined, '
|
||
|
+ JSON.stringify(dict) + ')';
|
||
|
promise = navigator.mozInputMethod.inputcontext
|
||
|
.setComposition(testdata.text, undefined, undefined, dict);
|
||
|
} else {
|
||
|
testName = gTestDescription +
|
||
|
'setComposition(' + testdata.text + ')';
|
||
|
promise = navigator.mozInputMethod.inputcontext
|
||
|
.setComposition(testdata.text);
|
||
|
}
|
||
|
|
||
|
if (testdata.expectedReject) {
|
||
|
promise = promise
|
||
|
.then(() => {
|
||
|
ok(false, testName + ' should not resolve.');
|
||
|
}, (e) => {
|
||
|
ok(true, testName + ' rejects.');
|
||
|
ok(e instanceof testdata.expectedReject, 'Reject with type.');
|
||
|
})
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
promise = promise
|
||
|
.then((res) => {
|
||
|
is(res, true,
|
||
|
testName + ' should resolve to true.');
|
||
|
|
||
|
var expectedEventDetail = [];
|
||
|
|
||
|
var expectedValues = testdata.expectedValues;
|
||
|
|
||
|
if (testdata.expectsKeyEvents &&
|
||
|
(testdata.startsComposition ||
|
||
|
testdata.dispatchKeyboardEventDuringComposition)) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keydown',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (testdata.startsComposition) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'compositionstart',
|
||
|
data: '',
|
||
|
value: gCurrentValue
|
||
|
});
|
||
|
}
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'compositionupdate',
|
||
|
data: testdata.text,
|
||
|
value: gCurrentValue
|
||
|
});
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'input',
|
||
|
value: gCurrentValue += testdata.expectedInput
|
||
|
});
|
||
|
|
||
|
if (testdata.expectsKeyEvents &&
|
||
|
testdata.dispatchKeyboardEventDuringComposition) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keyup',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
assertEventDetail(expectedEventDetail, testName);
|
||
|
gEventDetails = [];
|
||
|
}, (e) => {
|
||
|
ok(false, testName + ' should not reject. ' + e);
|
||
|
});
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
function endCompositionAndAssertResult(testdata) {
|
||
|
var dict = testdata.dict;
|
||
|
var testName;
|
||
|
var promise;
|
||
|
if (dict) {
|
||
|
testName = gTestDescription +
|
||
|
'endComposition(' + testdata.text + ', ' + JSON.stringify(dict) + ')';
|
||
|
promise = navigator.mozInputMethod.inputcontext
|
||
|
.endComposition(testdata.text, dict);
|
||
|
} else {
|
||
|
testName = gTestDescription +
|
||
|
'endComposition(' + testdata.text + ')';
|
||
|
promise = navigator.mozInputMethod.inputcontext
|
||
|
.endComposition(testdata.text);
|
||
|
}
|
||
|
|
||
|
if (testdata.expectedReject) {
|
||
|
promise = promise
|
||
|
.then(() => {
|
||
|
ok(false, testName + ' should not resolve.');
|
||
|
}, (e) => {
|
||
|
ok(true, testName + ' rejects.');
|
||
|
ok(e instanceof testdata.expectedReject, 'Reject with type.');
|
||
|
})
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
promise = promise
|
||
|
.then((res) => {
|
||
|
is(res, true,
|
||
|
testName + ' should resolve to true.');
|
||
|
|
||
|
var expectedEventDetail = [];
|
||
|
|
||
|
var expectedValues = testdata.expectedValues;
|
||
|
|
||
|
if (testdata.expectsKeyEvents &&
|
||
|
testdata.dispatchKeyboardEventDuringComposition) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keydown',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'compositionend',
|
||
|
data: testdata.text,
|
||
|
value: gCurrentValue
|
||
|
});
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'input',
|
||
|
value: gCurrentValue
|
||
|
});
|
||
|
|
||
|
if (testdata.expectsKeyEvents) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keyup',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
assertEventDetail(expectedEventDetail, testName);
|
||
|
gEventDetails = [];
|
||
|
}, (e) => {
|
||
|
ok(false, testName + ' should not reject. ' + e);
|
||
|
});
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
function runCompositionWithKeyEventTests() {
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
[true, false].forEach((dispatchKeyboardEventDuringComposition) => {
|
||
|
gTestDescription = 'runCompositionWithKeyEventTests() (dispatchKeyboardEvent =' + dispatchKeyboardEventDuringComposition + '): ';
|
||
|
|
||
|
promiseQueue = promiseQueue
|
||
|
.then(() => {
|
||
|
SpecialPowers.setBoolPref(
|
||
|
'dom.keyboardevent.dispatch_during_composition',
|
||
|
dispatchKeyboardEventDuringComposition);
|
||
|
})
|
||
|
.then(() => {
|
||
|
return setCompositionAndAssertResult({
|
||
|
text: 'foo',
|
||
|
expectsKeyEvents: true,
|
||
|
startsComposition: true,
|
||
|
dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
|
||
|
expectedInput: 'foo',
|
||
|
dict: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedValues: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return setCompositionAndAssertResult({
|
||
|
text: 'foobar',
|
||
|
expectsKeyEvents: true,
|
||
|
startsComposition: false,
|
||
|
dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
|
||
|
expectedInput: 'bar',
|
||
|
dict: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedValues: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return endCompositionAndAssertResult({
|
||
|
text: 'foobar',
|
||
|
expectsKeyEvents: true,
|
||
|
dispatchKeyboardEventDuringComposition: dispatchKeyboardEventDuringComposition,
|
||
|
expectedInput: '',
|
||
|
dict: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
},
|
||
|
expectedValues: {
|
||
|
key: 'a',
|
||
|
code: 'KeyA',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
SpecialPowers.clearUserPref(
|
||
|
'dom.keyboardevent.dispatch_during_composition');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runCompositionWithoutKeyEventTests() {
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
gTestDescription = 'runCompositionWithoutKeyEventTests(): ';
|
||
|
|
||
|
promiseQueue = promiseQueue
|
||
|
.then(() => {
|
||
|
return setCompositionAndAssertResult({
|
||
|
text: 'foo',
|
||
|
expectsKeyEvents: false,
|
||
|
startsComposition: true,
|
||
|
expectedInput: 'foo'
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return setCompositionAndAssertResult({
|
||
|
text: 'foobar',
|
||
|
expectsKeyEvents: false,
|
||
|
startsComposition: false,
|
||
|
expectedInput: 'bar'
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return endCompositionAndAssertResult({
|
||
|
text: 'foobar',
|
||
|
expectsKeyEvents: false,
|
||
|
expectedInput: ''
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function keydownAndAssertResult(testdata) {
|
||
|
var dict = testdata.dict;
|
||
|
var testName = gTestDescription + 'keydown(' + JSON.stringify(dict) + ')';
|
||
|
var promise = navigator.mozInputMethod.inputcontext.keydown(dict);
|
||
|
|
||
|
if (testdata.expectedReject) {
|
||
|
promise = promise
|
||
|
.then(() => {
|
||
|
ok(false, testName + ' should not resolve.');
|
||
|
}, (e) => {
|
||
|
ok(true, testName + ' rejects.');
|
||
|
ok(e instanceof testdata.expectedReject, 'Reject with type.');
|
||
|
})
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
promise = promise
|
||
|
.then((res) => {
|
||
|
is(res, true,
|
||
|
testName + ' should resolve to true.');
|
||
|
|
||
|
var expectedEventDetail = [];
|
||
|
|
||
|
var expectedValues = testdata.expectedValues;
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keydown',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
|
||
|
if (testdata.expectedKeypress) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keypress',
|
||
|
key: expectedValues.key,
|
||
|
charCode: expectedValues.charCode,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.charCode ? 0 : expectedValues.keyCode,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (testdata.expectedInput) {
|
||
|
expectedEventDetail.push({
|
||
|
type: 'input',
|
||
|
value: gCurrentValue += testdata.expectedInput
|
||
|
});
|
||
|
}
|
||
|
|
||
|
assertEventDetail(expectedEventDetail, testName);
|
||
|
gEventDetails = [];
|
||
|
}, (e) => {
|
||
|
ok(false, testName + ' should not reject. ' + e);
|
||
|
});
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
function keyupAndAssertResult(testdata) {
|
||
|
var dict = testdata.dict;
|
||
|
var testName = gTestDescription + 'keyup(' + JSON.stringify(dict) + ')';
|
||
|
var promise = navigator.mozInputMethod.inputcontext.keyup(dict);
|
||
|
|
||
|
if (testdata.expectedReject) {
|
||
|
promise = promise
|
||
|
.then(() => {
|
||
|
ok(false, testName + ' should not resolve.');
|
||
|
}, (e) => {
|
||
|
ok(true, testName + ' rejects.');
|
||
|
ok(e instanceof testdata.expectedReject, 'Reject with type.');
|
||
|
})
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
promise = promise
|
||
|
.then((res) => {
|
||
|
is(res, true,
|
||
|
testName + ' should resolve to true.');
|
||
|
|
||
|
var expectedEventDetail = [];
|
||
|
|
||
|
var expectedValues = testdata.expectedValues;
|
||
|
|
||
|
expectedEventDetail.push({
|
||
|
type: 'keyup',
|
||
|
key: expectedValues.key,
|
||
|
charCode: 0,
|
||
|
code: expectedValues.code || '',
|
||
|
keyCode: expectedValues.keyCode || 0,
|
||
|
location: 0,
|
||
|
repeat: expectedValues.repeat || false,
|
||
|
value: gCurrentValue,
|
||
|
shift: false,
|
||
|
capsLock: false,
|
||
|
control: false,
|
||
|
alt: false
|
||
|
});
|
||
|
|
||
|
assertEventDetail(expectedEventDetail, testName);
|
||
|
gEventDetails = [];
|
||
|
}, (e) => {
|
||
|
ok(false, testName + ' should not reject. ' + e);
|
||
|
});
|
||
|
|
||
|
return promise;
|
||
|
}
|
||
|
|
||
|
function runKeyDownUpTests() {
|
||
|
gTestDescription = 'runKeyDownUpTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
let chr = 'a';
|
||
|
let code = 'KeyA';
|
||
|
let keyCode = KeyboardEvent.DOM_VK_A;
|
||
|
|
||
|
promiseQueue = promiseQueue
|
||
|
.then(() => {
|
||
|
return keydownAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedInput: chr,
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return keyupAndAssertResult({
|
||
|
dict: {
|
||
|
key: chr,
|
||
|
code: code,
|
||
|
keyCode: keyCode
|
||
|
},
|
||
|
expectedValues: {
|
||
|
key: chr, code: code,
|
||
|
keyCode: keyCode,
|
||
|
charCode: chr.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runKeyDownUpRejectionTests() {
|
||
|
gTestDescription = 'runKeyDownUpRejectionTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return keydownAndAssertResult({
|
||
|
dict: undefined,
|
||
|
expectedReject: TypeError
|
||
|
});
|
||
|
});
|
||
|
|
||
|
promiseQueue = promiseQueue.then(() => {
|
||
|
return keyupAndAssertResult({
|
||
|
dict: undefined,
|
||
|
expectedReject: TypeError
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runRepeatTests() {
|
||
|
gTestDescription = 'runRepeatTests(): ';
|
||
|
var promiseQueue = Promise.resolve();
|
||
|
|
||
|
// Test repeat
|
||
|
promiseQueue = promiseQueue
|
||
|
.then(() => {
|
||
|
return sendKeyAndAssertResult({
|
||
|
dict: {
|
||
|
key: 'A',
|
||
|
repeat: true
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedRepeat: true,
|
||
|
expectedInput: 'A',
|
||
|
expectedValues: {
|
||
|
repeat: true,
|
||
|
key: 'A', code: '',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: 'A'.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
})
|
||
|
.then(() => {
|
||
|
return keyupAndAssertResult({
|
||
|
dict: {
|
||
|
key: 'A'
|
||
|
},
|
||
|
expectedKeypress: true,
|
||
|
expectedRepeat: true,
|
||
|
expectedInput: 'A',
|
||
|
expectedValues: {
|
||
|
key: 'A', code: '',
|
||
|
keyCode: KeyboardEvent.DOM_VK_A,
|
||
|
charCode: 'A'.charCodeAt(0)
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return promiseQueue;
|
||
|
}
|
||
|
|
||
|
function runTest() {
|
||
|
let im = navigator.mozInputMethod;
|
||
|
|
||
|
// Set current page as an input method.
|
||
|
SpecialPowers.wrap(im).setActive(true);
|
||
|
|
||
|
let iframe = document.createElement('iframe');
|
||
|
iframe.src = 'data:text/html,<html><body><textarea rows=30 cols=30></textarea></body></html>';
|
||
|
iframe.setAttribute('mozbrowser', true);
|
||
|
document.body.appendChild(iframe);
|
||
|
|
||
|
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||
|
|
||
|
iframe.addEventListener('mozbrowserloadend', function() {
|
||
|
mm.addMessageListener('test:eventDetail', function(msg) {
|
||
|
gEventDetails.push(msg.data);
|
||
|
});
|
||
|
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||
|
});
|
||
|
|
||
|
waitForInputContextChange()
|
||
|
.then(() => {
|
||
|
var inputcontext = navigator.mozInputMethod.inputcontext;
|
||
|
|
||
|
ok(!!inputcontext, 'Receving the first input context');
|
||
|
})
|
||
|
.then(() => runSendKeyAlphabetTests())
|
||
|
.then(() => runSendKeyNumberTests())
|
||
|
.then(() => runSendKeyDvorakTests())
|
||
|
.then(() => runSendKeyDigitKeySymbolsTests())
|
||
|
.then(() => runSendKeyUSKeyboardSymbolsTests())
|
||
|
.then(() => runSendKeyGreekLettersTests())
|
||
|
.then(() => runSendKeyEnterTests())
|
||
|
.then(() => runSendKeyNumpadTests())
|
||
|
.then(() => runSendKeyRejectionTests())
|
||
|
.then(() => runCompositionWithKeyEventTests())
|
||
|
.then(() => runCompositionWithoutKeyEventTests())
|
||
|
.then(() => runKeyDownUpTests())
|
||
|
.then(() => runKeyDownUpRejectionTests())
|
||
|
.then(() => runRepeatTests())
|
||
|
.catch((err) => {
|
||
|
console.error(err);
|
||
|
is(false, err.message);
|
||
|
})
|
||
|
.then(() => {
|
||
|
var p = waitForInputContextChange();
|
||
|
|
||
|
// Revoke our right from using the IM API.
|
||
|
SpecialPowers.wrap(im).setActive(false);
|
||
|
|
||
|
return p;
|
||
|
})
|
||
|
.then(() => {
|
||
|
var inputcontext = navigator.mozInputMethod.inputcontext;
|
||
|
|
||
|
is(inputcontext, null, 'Receving null input context');
|
||
|
|
||
|
inputmethod_cleanup();
|
||
|
})
|
||
|
.catch((err) => {
|
||
|
console.error(err);
|
||
|
is(false, err.message);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
</script>
|
||
|
</pre>
|
||
|
</body>
|
||
|
</html>
|
||
|
|