summaryrefslogtreecommitdiffstats
path: root/dom/inputmethod/mochitest/test_bug1137557.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/inputmethod/mochitest/test_bug1137557.html')
-rw-r--r--dom/inputmethod/mochitest/test_bug1137557.html1799
1 files changed, 1799 insertions, 0 deletions
diff --git a/dom/inputmethod/mochitest/test_bug1137557.html b/dom/inputmethod/mochitest/test_bug1137557.html
new file mode 100644
index 000000000..1f5053662
--- /dev/null
+++ b/dom/inputmethod/mochitest/test_bug1137557.html
@@ -0,0 +1,1799 @@
+<!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="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/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 = 'file_test_bug1137557.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>
+