1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.inputmethod.cts; 18 19 import static com.android.compatibility.common.util.WidgetTestUtils.sameCharSequence; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.fail; 24 import static org.mockito.Matchers.any; 25 import static org.mockito.Matchers.anyInt; 26 import static org.mockito.Matchers.eq; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.never; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 33 import android.content.ClipDescription; 34 import android.net.Uri; 35 import android.os.Bundle; 36 import android.text.TextUtils; 37 import android.view.KeyEvent; 38 import android.view.inputmethod.CompletionInfo; 39 import android.view.inputmethod.CorrectionInfo; 40 import android.view.inputmethod.EditorInfo; 41 import android.view.inputmethod.ExtractedTextRequest; 42 import android.view.inputmethod.InputConnection; 43 import android.view.inputmethod.InputConnectionWrapper; 44 import android.view.inputmethod.InputContentInfo; 45 46 import androidx.test.filters.SmallTest; 47 import androidx.test.runner.AndroidJUnit4; 48 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.ArgumentCaptor; 52 53 @SmallTest 54 @RunWith(AndroidJUnit4.class) 55 public class InputConnectionWrapperTest { 56 @Test 57 public void testInputConnectionWrapper() { 58 InputConnection inputConnection = mock(InputConnection.class); 59 doReturn(true).when(inputConnection).commitContent(any(InputContentInfo.class), 60 anyInt(), any(Bundle.class)); 61 InputConnectionWrapper wrapper = new InputConnectionWrapper(null, true); 62 try { 63 wrapper.beginBatchEdit(); 64 fail("Failed to throw NullPointerException!"); 65 } catch (NullPointerException e) { 66 // expected 67 } 68 wrapper.setTarget(inputConnection); 69 70 wrapper.beginBatchEdit(); 71 verify(inputConnection, times(1)).beginBatchEdit(); 72 73 wrapper.clearMetaKeyStates(KeyEvent.META_ALT_ON); 74 verify(inputConnection, times(1)).clearMetaKeyStates(KeyEvent.META_ALT_ON); 75 76 wrapper.commitCompletion(new CompletionInfo(1, 1, "testText")); 77 ArgumentCaptor<CompletionInfo> completionInfoCaptor = 78 ArgumentCaptor.forClass(CompletionInfo.class); 79 verify(inputConnection, times(1)).commitCompletion(completionInfoCaptor.capture()); 80 assertEquals(1, completionInfoCaptor.getValue().getId()); 81 assertEquals(1, completionInfoCaptor.getValue().getPosition()); 82 assertEquals("testText", completionInfoCaptor.getValue().getText()); 83 84 wrapper.commitCorrection(new CorrectionInfo(0, "oldText", "newText")); 85 ArgumentCaptor<CorrectionInfo> correctionInfoCaptor = 86 ArgumentCaptor.forClass(CorrectionInfo.class); 87 verify(inputConnection, times(1)).commitCorrection(correctionInfoCaptor.capture()); 88 assertEquals(0, correctionInfoCaptor.getValue().getOffset()); 89 assertEquals("oldText", correctionInfoCaptor.getValue().getOldText()); 90 assertEquals("newText", correctionInfoCaptor.getValue().getNewText()); 91 92 wrapper.commitText("Text", 1); 93 verify(inputConnection, times(1)).commitText(sameCharSequence("Text"), eq(1)); 94 95 wrapper.deleteSurroundingText(10, 100); 96 verify(inputConnection, times(1)).deleteSurroundingText(10, 100); 97 98 wrapper.deleteSurroundingTextInCodePoints(10, 100); 99 verify(inputConnection, times(1)).deleteSurroundingTextInCodePoints(10, 100); 100 101 wrapper.endBatchEdit(); 102 verify(inputConnection, times(1)).endBatchEdit(); 103 104 wrapper.finishComposingText(); 105 verify(inputConnection, times(1)).finishComposingText(); 106 107 wrapper.getCursorCapsMode(TextUtils.CAP_MODE_CHARACTERS); 108 verify(inputConnection, times(1)).getCursorCapsMode(TextUtils.CAP_MODE_CHARACTERS); 109 110 wrapper.getExtractedText(new ExtractedTextRequest(), 0); 111 verify(inputConnection, times(1)).getExtractedText(any(ExtractedTextRequest.class), eq(0)); 112 113 wrapper.getTextAfterCursor(5, 0); 114 verify(inputConnection, times(1)).getTextAfterCursor(5, 0); 115 116 wrapper.getTextBeforeCursor(3, 0); 117 verify(inputConnection, times(1)).getTextBeforeCursor(3, 0); 118 119 wrapper.performContextMenuAction(1); 120 verify(inputConnection, times(1)).performContextMenuAction(1); 121 122 wrapper.performEditorAction(EditorInfo.IME_ACTION_GO); 123 verify(inputConnection, times(1)).performEditorAction(EditorInfo.IME_ACTION_GO); 124 125 wrapper.performPrivateCommand("com.android.action.MAIN", new Bundle()); 126 verify(inputConnection, times(1)).performPrivateCommand(eq("com.android.action.MAIN"), 127 any(Bundle.class)); 128 129 wrapper.reportFullscreenMode(true); 130 verify(inputConnection, times(1)).reportFullscreenMode(true); 131 132 wrapper.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)); 133 ArgumentCaptor<KeyEvent> keyEventCaptor = ArgumentCaptor.forClass(KeyEvent.class); 134 verify(inputConnection, times(1)).sendKeyEvent(keyEventCaptor.capture()); 135 assertEquals(KeyEvent.ACTION_DOWN, keyEventCaptor.getValue().getAction()); 136 assertEquals(KeyEvent.KEYCODE_0, keyEventCaptor.getValue().getKeyCode()); 137 138 wrapper.setComposingText("Text", 1); 139 verify(inputConnection, times(1)).setComposingText("Text", 1); 140 141 wrapper.setSelection(0, 10); 142 verify(inputConnection, times(1)).setSelection(0, 10); 143 144 wrapper.getSelectedText(0); 145 verify(inputConnection, times(1)).getSelectedText(0); 146 147 wrapper.setComposingRegion(0, 3); 148 verify(inputConnection, times(1)).setComposingRegion(0, 3); 149 150 wrapper.requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE); 151 verify(inputConnection, times(1)) 152 .requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE); 153 154 wrapper.closeConnection(); 155 verify(inputConnection, times(1)).closeConnection(); 156 157 verify(inputConnection, never()).getHandler(); 158 assertNull(wrapper.getHandler()); 159 verify(inputConnection, times(1)).getHandler(); 160 161 verify(inputConnection, never()).commitContent(any(InputContentInfo.class), anyInt(), 162 any(Bundle.class)); 163 164 final InputContentInfo inputContentInfo = new InputContentInfo( 165 Uri.parse("content://com.example/path"), 166 new ClipDescription("sample content", new String[]{"image/png"}), 167 Uri.parse("https://example.com")); 168 wrapper.commitContent(inputContentInfo, 0 /* flags */, null /* opt */); 169 verify(inputConnection, times(1)).commitContent(inputContentInfo, 0, null); 170 } 171 } 172