blob: 6ec92f2fbc2f9bba6a407c75ad54cd117ea8b6cb [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// TODO(hsumita): Introduces Closure library into mozc code tree if we release
// this file as an open source.
goog.require('goog.array');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.mockmatchers.ArgumentMatcher');
goog.require('goog.testing.mockmatchers.IgnoreArgument');
/**
* Finds an item in an array, returns the index, or -1 if not found.
* @param {Array.<Object>} array Target array.
* @param {Object} target Taret you want to get a index.
* @return {number} -1 if array doesn't contain the item, or index of the item.
*/
function findInArray(array, target) {
return goog.array.findIndex(array, function(elem) {
return elem === target;
});
}
/**
* Overwrite the function by empty one.
* @param {!Object} obj Target object.
* @param {string} fullName The name of the function.
* @return {function} An original function.
*/
function overwriteByEmptyFunction(obj, fullName) {
var names = fullName.split('.');
var original = obj[names[0]];
for (var i = 0; i < names.length; ++i) {
obj = obj[names[i]] = function() {};
}
return original;
}
var ENGINE_ID = '12345';
var CONTEXT = {
contextID: 67890,
type: 'text'
};
var mockControl = null;
var callbackMatcher = null;
var _ = null;
function setUp() {
mockControl = new goog.testing.MockControl();
callbackMatcher =
new goog.testing.mockmatchers.ArgumentMatcher(function(obj) {
return typeof(obj) == 'function';
});
_ = new goog.testing.mockmatchers.IgnoreArgument();
}
function tearDown() {
mockControl.$tearDown();
mockControl = null;
}
function getIme() {
// Sets a dummy method, activates IME, and restores original one.
var api = chrome.input.ime;
if (!api.onActivate) {
fail('api.onActivate is not defined!');
}
if (!chrome.input.ime.onActivate) {
fail('chrome.input.ime.onActivate is not defined!');
}
if (!chrome.input.ime.onActivate.addListener) {
fail('chrome.input.ime.onActivate.addListener is not defined!');
}
var originalOnActivateListener =
overwriteByEmptyFunction(api, 'onActivate.addListener');
var originalOnDeactivatedListener =
overwriteByEmptyFunction(api, 'onDeactivated.addListener');
var originalOnFocusListener =
overwriteByEmptyFunction(api, 'onFocus.addListener');
var originalOnBlurListener =
overwriteByEmptyFunction(api, 'onBlur.addListener');
var originalOnInputContextUpdateListener =
overwriteByEmptyFunction(api, 'onInputContextUpdate.addListener');
var originalOnKeyEventListener =
overwriteByEmptyFunction(api, 'onKeyEvent.addListener');
var originalOnCandidateClickedListener =
overwriteByEmptyFunction(api, 'onCandidateClicked.addListener');
var originalOnMenuItemActivatedListener =
overwriteByEmptyFunction(api, 'onMenuItemActivated.addListener');
var originalSetMenuItems = overwriteByEmptyFunction(api, 'setMenuItems');
var ime = new sampleImeForImeExtensionApi.SampleIme;
ime.onActivate(ENGINE_ID);
api.onActivate = originalOnActivateListener;
api.onDeactivated = originalOnDeactivatedListener;
api.onBlur = originalOnBlurListener;
api.onInputContextUpdate = originalOnInputContextUpdateListener;
api.onKeyEvent = originalOnKeyEventListener;
api.onCandidateClicked = originalOnCandidateClickedListener;
api.onMenuItemActivated = originalOnMenuItemActivatedListener;
api.setMenuItems = originalSetMenuItems;
ime.onFocus(CONTEXT);
return ime;
}
function testInsertCharacters() {
var ime = getIme();
assertEquals('', ime.inputText_);
assertEquals(0, ime.segments_.length);
assertEquals(0, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
ime.insertCharacters_('a');
assertEquals('a', ime.inputText_);
assertEquals(1, ime.segments_.length);
assertEquals(1, ime.cursor_);
assertEquals(0, ime.focusedSegmentIndex_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.insertCharacters_('bc');
assertEquals('abc', ime.inputText_);
assertEquals(1, ime.segments_.length);
assertEquals(3, ime.cursor_);
assertEquals(0, ime.focusedSegmentIndex_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.moveCursor_(1);
ime.insertCharacters_('A');
assertEquals('aAbc', ime.inputText_);
assertEquals(1, ime.segments_.length);
assertEquals(2, ime.cursor_);
assertEquals(0, ime.focusedSegmentIndex_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
}
function testRemoveCharacter() {
var ime = getIme();
ime.insertCharacters_('abcde');
assertEquals('abcde', ime.inputText_);
assertEquals(5, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.moveCursor_(2);
ime.removeCharacter_(0);
assertEquals('bcde', ime.inputText_);
assertEquals(1, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.removeCharacter_(3);
assertEquals('bcd', ime.inputText_);
assertEquals(1, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.removeCharacter_(-1);
assertEquals('bcd', ime.inputText_);
assertEquals(1, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.removeCharacter_(4);
assertEquals('bcd', ime.inputText_);
assertEquals(1, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.removeCharacter_(1);
assertEquals('bd', ime.inputText_);
assertEquals(1, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
ime.removeCharacter_(0);
ime.removeCharacter_(0);
assertEquals('', ime.inputText_);
assertEquals(0, ime.cursor_);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
}
function testMoveCursor() {
var ime = getIme();
// Precomposition mode.
ime.moveCursor_(1);
assertEquals(0, ime.cursor_);
// Composition mode.
ime.insertCharacters_('abcde');
ime.moveCursor_(2);
assertEquals(2, ime.cursor_);
ime.moveCursor_(-1);
assertEquals(2, ime.cursor_);
ime.moveCursor_(100);
assertEquals(2, ime.cursor_);
// Conversion mode.
ime.focusCandidate_(1);
ime.moveCursor_(0);
assertEquals(2, ime.cursor_);
}
function testExpandShrinkSegment() {
var ime = getIme();
ime.isUpdated_ = [];
ime.generateCandidates_ = function(opt_segmentIndex) {
var segmentIndex = (opt_segmentIndex == null) ?
this.focusedSegmentIndex_ : opt_segmentIndex;
this.isUpdated_[segmentIndex] = true;
};
ime.clearUpdatedSegmentList_ = function() {
this.isUpdated_ = [];
};
ime.compareUpdatedSegmentIndexes_ = function(indexes) {
for (var i = 0; i < indexes.length; ++i) {
if (!this.isUpdated_[indexes[i]]) {
return false;
}
}
return true;
};
ime.compareSegmentBoundaries_ = function(indexes) {
if (this.segments_.length !== indexes.length) {
return false;
}
for (var i = 0; i < this.segments_.length; ++i) {
if (this.segments_[i].start !== indexes[i]) {
return false;
}
}
return true;
};
ime.insertCharacters_('abcde');
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
// abcde -> abcde
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([]));
assertTrue(ime.compareSegmentBoundaries_([0]));
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.CONVERSION,
ime.state_);
// abcde -> abcd|e
ime.clearUpdatedSegmentList_();
ime.shrinkSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([0, 1]));
assertTrue(ime.compareSegmentBoundaries_([0, 4]));
// abcd|e -> abcde|
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([0]));
assertTrue(ime.compareSegmentBoundaries_([0]));
// abcde| -> ab|cde
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
// ab|cde -> a|bcde
ime.clearUpdatedSegmentList_();
ime.shrinkSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([0, 1]));
assertTrue(ime.compareSegmentBoundaries_([0, 1]));
// a|bcde -> a|bcde
ime.clearUpdatedSegmentList_();
ime.shrinkSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([]));
assertTrue(ime.compareSegmentBoundaries_([0, 1]));
// a|bcde -> ab|cde
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([0, 1]));
assertTrue(ime.compareSegmentBoundaries_([0, 2]));
ime.focusedSegmentIndex_ = 1;
// ab|cde -> ab|cd|e
ime.clearUpdatedSegmentList_();
ime.shrinkSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([1, 2]));
assertTrue(ime.compareSegmentBoundaries_([0, 2, 4]));
// ab|cd|e -> ab|cde
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([1]));
assertTrue(ime.compareSegmentBoundaries_([0, 2]));
// ab|cde -> ab|c|de
ime.shrinkSegment_();
ime.shrinkSegment_();
// ab|c|de -> ab|c|de
ime.clearUpdatedSegmentList_();
ime.shrinkSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([]));
assertTrue(ime.compareSegmentBoundaries_([0, 2, 3]));
// ab|c|de -> ab|cd|e
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([1, 2]));
assertTrue(ime.compareSegmentBoundaries_([0, 2, 4]));
// ab|cd|e -> abc|d|e
ime.focusedSegmentIndex_ = 0;
ime.expandSegment_();
// abc|d|e -> abcd|e
ime.clearUpdatedSegmentList_();
ime.expandSegment_();
assertTrue(ime.compareUpdatedSegmentIndexes_([0]));
assertTrue(ime.compareSegmentBoundaries_([0, 4]));
}
function testResetSegments() {
var ime = getIme();
ime.resetSegments_();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
assertEquals(0, ime.segments_.length);
ime.insertCharacters_('abc');
ime.resetSegments_();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
assertEquals(1, ime.segments_.length);
ime.state_ = sampleImeForImeExtensionApi.SampleIme.State.CONVERSION;
ime.resetSegments_();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
assertEquals(1, ime.segments_.length);
ime.shrinkSegment_();
ime.resetSegments_();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
assertEquals(1, ime.segments_.length);
}
function testCandidates() {
var ime = getIme();
ime.insertCharacters_('foostar');
assertEquals(1, ime.segments_.length);
assertNotEquals(0, ime.segments_[0].candidates.length);
assertEquals('\uFF46\uFF4F\uFF4F\uFF53\uFF54\uFF41\uFF52', // 'foostar'
ime.segments_[0].candidates[0]);
// 'foostar' -> 'foo|star'
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
assertEquals(2, ime.segments_.length);
assertNotEquals(0, ime.segments_[0].candidates.length);
assertNotEquals(0, ime.segments_[1].candidates.length);
assertEquals('\uFF46\uFF4F\uFF4F', // 'foo'
ime.segments_[0].candidates[0]);
assertEquals('\uFF53\uFF54\uFF41\uFF52', // 'star'
ime.segments_[1].candidates[0]);
assertNotEquals(-1, findInArray(ime.segments_[1].candidates,
'\u2606')); // '☆'
// Dummy candidates.
var dummyCandidate = 'DummyCandidate1';
ime.useDummyCandidates_ = false;
ime.generateCandidates_(0);
assertEquals(-1, findInArray(ime.segments_[0].candidates, dummyCandidate));
ime.useDummyCandidates_ = true;
ime.generateCandidates_(0);
assertNotEquals(-1, findInArray(ime.segments_[0].candidates, dummyCandidate));
var segmentLength = ime.segments_.length;
ime.getInputTextOnSegment_(-1);
assertEquals(segmentLength, ime.segments_.length);
ime.getInputTextOnSegment_(100);
assertEquals(segmentLength, ime.segments_.length);
}
function testSelectCandidate() {
var ime = getIme();
ime.focusCandidate_(0);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
assertEquals(0, ime.segments_.length);
ime.insertCharacters_('abcde');
ime.focusCandidate_(0);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.CONVERSION,
ime.state_);
assertEquals(0, ime.segments_[0].focusedIndex);
ime.focusCandidate_(1);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.CONVERSION,
ime.state_);
assertEquals(1, ime.segments_[0].focusedIndex);
ime.shrinkSegment_();
ime.focusSegment_(1);
ime.focusCandidate_(2);
assertEquals(2, ime.segments_[1].focusedIndex);
ime.focusCandidate_(100);
assertEquals(2, ime.segments_[1].focusedIndex);
ime.focusCandidate_(-1);
assertEquals(2, ime.segments_[1].focusedIndex);
}
function testGetPreeditText() {
var ime = getIme();
assertEquals('', ime.getPreeditText_());
ime.insertCharacters_('foo');
assertEquals('\uFF46\uFF4F\uFF4F', ime.getPreeditText_()); // 'foo'
ime.insertCharacters_('star');
// 'foostar' -> 'foo|star'
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.focusSegment_(1);
var index = findInArray(ime.segments_[1].candidates, '\u2606'); // '☆'
assertNotEquals(-1, index);
ime.focusCandidate_(index);
assertEquals('\uFF46\uFF4F\uFF4F\u2606', ime.getPreeditText_()); // 'foo☆'
}
function testUpdatePreedit() {
var ime = getIme();
// Precomposition mode.
mockControl.createMethodMock(chrome.input.ime, 'clearComposition')({
contextID: CONTEXT.contextID
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updatePreedit_();
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
// Composition mode.
ime.insertCharacters_('abstarc');
ime.moveCursor_(2);
mockControl.createMethodMock(chrome.input.ime, 'setComposition')({
contextID: CONTEXT.contextID,
text: '\uFF41\uFF42\uFF53\uFF54\uFF41\uFF52\uFF43', // 'abstarc'
segments: [{
start: 0,
end: 7,
style: 'underline'
}],
cursor: 2
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updatePreedit_();
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
// 'abstarc' -> 'ab|star|c'
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.shrinkSegment_();
ime.focusSegment_(1);
ime.shrinkSegment_();
// Conversion mode.
ime.focusCandidate_(findInArray(ime.segments_[1].candidates,
'\u2606')); // '☆'
assertEquals('\uFF41\uFF42\u2606\uFF43', ime.getPreeditText_());
mockControl.createMethodMock(chrome.input.ime, 'setComposition')({
contextID: CONTEXT.contextID,
text: '\uFF41\uFF42\u2606\uFF43', // 'ab☆c'
selectionStart: 2,
selectionEnd: 3,
segments: [
{
start: 0,
end: 2,
style: 'underline'
}, {
start: 2,
end: 3,
style: 'doubleUnderline'
}, {
start: 3,
end: 4,
style: 'underline'
}
],
cursor: 2
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updatePreedit_();
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.CONVERSION,
ime.state_);
// Backs to composition mode.
ime.resetSegments_();
mockControl.createMethodMock(chrome.input.ime, 'setComposition')({
contextID: CONTEXT.contextID,
text: '\uFF41\uFF42\uFF53\uFF54\uFF41\uFF52\uFF43', // 'abstarc'
segments: [{
start: 0,
end: 7,
style: 'underline'
}],
cursor: 2
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updatePreedit_();
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
}
function testUpdateCandidates() {
var ime = getIme();
// Precomposition mode.
mockControl.createMethodMock(
chrome.input.ime, 'setCandidateWindowProperties')({
engineID: ENGINE_ID,
properties: {
visible: false,
auxiliaryTextVisible: false
}
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updateCandidates_();
mockControl.$verifyAll();
// Simpe verifier for chrome.input.ime.setCandidates.
var simpleVerifier = function(expected, actual) {
assertEquals(expected[0].contextID, actual[0].contextID);
var candidates = actual[0].candidates;
assertTrue(candidates.length > 0);
assertEquals('1st candidate', candidates[0].annotation);
for (var i = 0; i < candidates.length; ++i) {
assertEquals(i, candidates[i].id);
assertTrue(!!candidates[i].candidate);
var label_index = i % sampleImeForImeExtensionApi.SampleIme.PAGE_SIZE_;
var label = String.fromCharCode(0x2160 + label_index); // 'Ⅰ' + index
assertEquals(label, candidates[i].label);
}
assertTrue(callbackMatcher.matches(actual[1]));
return true;
};
// Composition and Conversion mode.
ime.insertCharacters_('abcde');
mockControl.createMethodMock(chrome.input.ime, 'setCandidates')({
contextID: CONTEXT.contextID
}).$registerArgumentListVerifier('setCandidates', simpleVerifier).$times(1);
mockControl.createMethodMock(chrome.input.ime, 'setCursorPosition')({
contextID: CONTEXT.contextID,
candidateID: ime.segments_[0].focusedIndex
}, callbackMatcher).$times(1);
mockControl.createMethodMock(
chrome.input.ime, 'setCandidateWindowProperties')({
engineID: ENGINE_ID,
properties: {
visible: true,
cursorVisible: true,
vertical: true,
pageSize: 5,
auxiliaryTextVisible: true,
auxiliaryText: 'Sample IME'
}
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updateCandidates_();
mockControl.$verifyAll();
}
function testUpdateCommitText() {
var ime = getIme();
ime.insertCharacters_('abcde');
ime.shrinkSegment_();
ime.focusCandidate_(findInArray(ime.segments_[0].candidates, 'Abcd'));
ime.focusedSegmentIndex_ = 1;
// 'e'
ime.focusCandidate_(findInArray(ime.segments_[1].candidates, '\uFF45'));
var text = ime.getPreeditText_();
assertEquals('Abcd' + '\uFF45', text); // 'Abcd|e'
ime.commit_();
assertEquals(text, ime.commitText_);
mockControl.createMethodMock(chrome.input.ime, 'commitText')({
contextID: CONTEXT.contextID,
text: text
}, callbackMatcher).$times(1);
mockControl.$replayAll();
ime.updateCommitText_();
mockControl.$verifyAll();
assertEquals(null, ime.commitText_);
// Shouldn't call chrome.input.ime.commitText() since it doesn't have
// commitText_.
mockControl.createMethodMock(chrome.input.ime, 'commitText')().$times(0);
mockControl.$replayAll();
ime.updateCommitText_();
mockControl.$verifyAll();
}
function testUpdate() {
var ime = getIme();
mockControl.createMethodMock(ime, 'updatePreedit_')().$times(1);
mockControl.createMethodMock(ime, 'updateCandidates_')().$times(1);
mockControl.createMethodMock(ime, 'updateCommitText_')().$times(1);
mockControl.$replayAll();
ime.update_();
mockControl.$verifyAll();
}
function testHandleKey() {
var ime = getIme();
mockControl.createMethodMock(ime, 'update_')().$times(0);
mockControl.$replayAll();
assertFalse(ime.handleKey_({key: '0'}));
assertFalse(ime.handleKey_({key: '!'}));
assertFalse(ime.handleKey_({key: 'a', altKey: true}));
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
mockControl.createMethodMock(ime, 'update_')().$times(1);
mockControl.$replayAll();
assertTrue(ime.handleKey_({key: 'a'}));
mockControl.$verifyAll();
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
assertEquals('a', ime.getInputTextOnSegment_());
}
function testHandleSpecialKey() {
var ime = getIme();
// Precomposition mode.
assertFalse(ime.handleSpecialKey_({key: 'Backspace'}));
assertFalse(ime.handleSpecialKey_({key: 'Delete'}));
assertFalse(ime.handleSpecialKey_({key: 'Up'}));
assertFalse(ime.handleSpecialKey_({key: 'Left'}));
assertFalse(ime.handleSpecialKey_({key: 'Enter'}));
assertFalse(ime.handleSpecialKey_({key: 'Left', ctrlKey: true}));
assertFalse(ime.handleSpecialKey_({key: 'DUMMY'}));
var verify = function(key, isCalled) {
var expectedTimes = isCalled ? 1 : 0;
mockControl.createMethodMock(ime, 'update_')().$times(expectedTimes);
mockControl.$replayAll();
assertTrue(ime.handleSpecialKey_(key));
mockControl.$verifyAll();
};
// Composition mode.
ime.insertCharacters_('abcdefgh');
verify({key: 'Backspace'}, true);
assertEquals('abcdefg', ime.getInputTextOnSegment_());
verify({key: 'Left'}, true);
assertEquals(6, ime.cursor_);
verify({key: 'Delete'}, true);
assertEquals('abcdef', ime.getInputTextOnSegment_());
verify({key: 'Left'}, true);
verify({key: 'Left'}, true);
assertEquals(4, ime.cursor_);
verify({key: 'Right'}, true);
assertEquals(5, ime.cursor_);
verify({key: 'DUMMY'}, false);
// Conversion mode.
verify({key: 'Left', shiftKey: true}, true);
verify({key: 'Left', shiftKey: true}, true);
assertEquals('abcd', ime.getInputTextOnSegment_());
verify({key: 'Right', shiftKey: true}, true);
assertEquals('abcde', ime.getInputTextOnSegment_());
verify({key: 'Right'}, true);
assertEquals('f', ime.getInputTextOnSegment_());
verify({key: 'Left'}, true);
assertEquals('abcde', ime.getInputTextOnSegment_());
verify({key: 'Down'}, true);
assertEquals(1, ime.segments_[0].focusedIndex);
verify({key: ' '}, true);
assertEquals(2, ime.segments_[0].focusedIndex);
verify({key: 'Up'}, true);
assertEquals(1, ime.segments_[0].focusedIndex);
verify({key: 'DUMMY'}, false);
// Check cursor key on Conversion mode.
var lastCandidateIndex = ime.segments_[0].candidates.length - 1;
verify({key: 'Up'}, true);
assertEquals(0, ime.segments_[0].focusedIndex);
verify({key: 'Up'}, true);
assertEquals(lastCandidateIndex, ime.segments_[0].focusedIndex);
verify({key: 'Up'}, true);
assertEquals(lastCandidateIndex - 1, ime.segments_[0].focusedIndex);
verify({key: 'Down'}, true);
assertEquals(lastCandidateIndex, ime.segments_[0].focusedIndex);
verify({key: 'Down'}, true);
assertEquals(0, ime.segments_[0].focusedIndex);
verify({key: 'Right'}, true);
assertEquals(1, ime.focusedSegmentIndex_);
verify({key: 'Right'}, true);
assertEquals(1, ime.focusedSegmentIndex_);
verify({key: 'Left'}, true);
assertEquals(0, ime.focusedSegmentIndex_);
verify({key: 'Left'}, true);
assertEquals(0, ime.focusedSegmentIndex_);
verify({key: 'Backspace'}, true);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
verify({key: 'Left', shiftKey: true}, true);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.CONVERSION,
ime.state_);
verify({key: 'Delete'}, true);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.COMPOSITION,
ime.state_);
verify({key: 'Enter'}, true);
assertEquals(sampleImeForImeExtensionApi.SampleIme.State.PRECOMPOSITION,
ime.state_);
}
function testIgnoreKey() {
var ime = getIme();
ime.insertCharacters_('a');
var keyEvent = {
type: 'keydown',
key: 'ChromeOSSwitchWindow',
altKey: false,
ctrlKey: false,
shiftKey: false
};
assertTrue(ime.onKeyEvent(ENGINE_ID, keyEvent));
keyEvent.ctrlKey = true;
assertFalse(ime.onKeyEvent(ENGINE_ID, keyEvent));
keyEvent.shiftKey = true;
assertFalse(ime.onKeyEvent(ENGINE_ID, keyEvent));
keyEvent.altKey = true;
assertTrue(ime.onKeyEvent(ENGINE_ID, keyEvent));
}
function testSetUpMenu() {
var ime = getIme();
// Simpe verifier for chrome.input.ime.setUpMenu.
var simpleVerifier = function(expected, actual) {
assertEquals(ENGINE_ID, actual[0].engineID);
assertEquals(4, actual[0].items.length);
assertTrue(callbackMatcher.matches(actual[1]));
return true;
};
mockControl.createMethodMock(chrome.input.ime, 'setMenuItems')()
.$registerArgumentListVerifier('setMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.setUpMenu_();
mockControl.$verifyAll();
}
function testOnActivate() {
var ime = getIme();
var ANOTHER_ENGINE_ID = 24680;
mockControl.createMethodMock(ime, 'setUpMenu_')().$times(1);
mockControl.createMethodMock(ime, 'clear_')().$times(1);
mockControl.$replayAll();
ime.onActivate(ANOTHER_ENGINE_ID);
mockControl.$verifyAll();
assertEquals(ANOTHER_ENGINE_ID, ime.engineID_);
}
function testOnDeactivated() {
var ime = getIme();
mockControl.createMethodMock(ime, 'clear_')().$times(1);
mockControl.$replayAll();
ime.onDeactivated(ENGINE_ID);
mockControl.$verifyAll();
assertEquals('', ime.engineID_);
}
function testOnFocusBlurUpdate() {
var ime = getIme();
assertEquals(CONTEXT, ime.context_);
mockControl.createMethodMock(ime, 'clear_')().$times(1);
mockControl.$replayAll();
ime.onBlur(CONTEXT.contextID);
mockControl.$verifyAll();
assertEquals(null, ime.context_);
mockControl.createMethodMock(ime, 'clear_')().$times(1);
mockControl.$replayAll();
ime.onFocus(CONTEXT);
mockControl.$verifyAll();
assertEquals(CONTEXT, ime.context_);
var ANOTHER_CONTEXT = {
contextID: 54321,
type: 'text'
};
mockControl.createMethodMock(ime, 'clear_')().$times(0);
mockControl.createMethodMock(ime, 'update_')().$times(1);
mockControl.$replayAll();
ime.onInputContextUpdate(ANOTHER_CONTEXT);
mockControl.$verifyAll();
assertEquals(ANOTHER_CONTEXT, ime.context_);
}
function testOnKeyEvent() {
var ime = getIme();
var input = [
[false, false],
[false, true],
[true, false],
[true, true]
];
for (var i = 0; i < input.length; ++i) {
mockControl.createMethodMock(ime, 'handleKey_')(_).
$returns(input[i][0]).$anyTimes();
mockControl.createMethodMock(ime, 'handleSpecialKey_')(_).
$returns(input[i][1]).$anyTimes();
mockControl.$replayAll();
assertFalse(ime.onKeyEvent(ENGINE_ID, {type: 'keyup'}));
assertEquals(input[i][0] || input[i][1],
ime.onKeyEvent(ENGINE_ID, {type: 'keydown'}));
mockControl.$verifyAll();
mockControl.$resetAll();
}
}
function testOnCandidateClicked() {
var ime = getIme();
mockControl.createMethodMock(ime, 'focusCandidate_')().$times(0);
mockControl.$replayAll();
ime.onCandidateClicked(ENGINE_ID, CLICKED_ID, 'right');
ime.onCandidateClicked(ENGINE_ID, CLICKED_ID, 'middle');
mockControl.$verifyAll();
var CLICKED_ID = 3;
mockControl.createMethodMock(ime, 'focusCandidate_')(CLICKED_ID).$times(1);
mockControl.createMethodMock(ime, 'update_')().$times(1);
mockControl.$replayAll();
ime.onCandidateClicked(ENGINE_ID, CLICKED_ID, 'left');
mockControl.$verifyAll();
}
function testOnMenuItemActivated() {
var ime = getIme();
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')().$times(0);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, '__dummy_menu_item_name__');
mockControl.$verifyAll();
// Simpe verifier for chrome.input.ime.updateMenuItems.
var simpleVerifier = function(expected, actual) {
assertEquals(ENGINE_ID, actual[0].engineID);
assertEquals(4, actual[0].items.length);
assertTrue(callbackMatcher.matches(actual[1]));
for (var i = 0; i < expected[0].length; ++i) {
var expectedItem = expected[0][i];
var actualItem = actual[0].items[i];
for (var key in expectedItem) {
assertEquals(expectedItem[key], actualItem[key]);
}
}
return true;
};
// Initial state of menu items
var expectedItems = [
{
id: 'enable_dummy_candidates',
label: 'Enable dummy candidates',
style: 'radio',
checked: true,
enabled: true,
visible: true
}, {
id: 'disable_dummy_candidates',
label: 'Disable dummy candidates',
style: 'radio',
checked: false,
enabled: true,
visible: true
}, {
id: 'enable_radio_menu',
label: 'Enable radio menu',
style: 'check',
checked: true
}, {
id: 'display_radio_menu',
label: 'Display radio menu',
style: 'check',
checked: true
}
];
// Disables dummy candidate.
expectedItems[0].checked = false;
expectedItems[1].checked = true;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'disable_dummy_candidates');
mockControl.$verifyAll();
assertFalse(ime.useDummyCandidates_);
// Enable dummy candidate.
expectedItems[0].checked = true;
expectedItems[1].checked = false;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'enable_dummy_candidates');
mockControl.$verifyAll();
assertTrue(ime.useDummyCandidates_);
// Disables radio menu item.
expectedItems[0].enabled = false;
expectedItems[1].enabled = false;
expectedItems[2].checked = false;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'enable_radio_menu');
mockControl.$verifyAll();
// Enables radio menu item.
expectedItems[0].enabled = true;
expectedItems[1].enabled = true;
expectedItems[2].checked = true;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'enable_radio_menu');
mockControl.$verifyAll();
// Hides radio menu item.
expectedItems[0].visible = false;
expectedItems[1].visible = false;
expectedItems[3].checked = false;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'display_radio_menu');
mockControl.$verifyAll();
// Shows radio menu item.
expectedItems[0].visible = true;
expectedItems[1].visible = true;
expectedItems[3].checked = true;
mockControl.createMethodMock(chrome.input.ime, 'updateMenuItems')(
expectedItems).$registerArgumentListVerifier(
'updateMenuItems', simpleVerifier).$times(1);
mockControl.$replayAll();
ime.onMenuItemActivated(ENGINE_ID, 'display_radio_menu');
mockControl.$verifyAll();
}