44import android .content .res .AssetManager ;
55import android .provider .Settings ;
66import android .util .SparseIntArray ;
7- import android .view .KeyEvent ;
8- import android .view .View ;
97import android .view .inputmethod .EditorInfo ;
108import android .view .inputmethod .InputConnection ;
119import android .view .inputmethod .InputMethodManager ;
1210import android .view .inputmethod .InputMethodSubtype ;
11+ import android .view .KeyEvent ;
12+ import android .view .View ;
1313
1414import java .nio .ByteBuffer ;
15- import java .util .Arrays ;
1615
17- import org .junit .Test ;
1816import org .junit .runner .RunWith ;
19- import org .robolectric .RobolectricTestRunner ;
20- import org .robolectric .RuntimeEnvironment ;
17+ import org .junit .Test ;
18+
19+ import org .json .JSONArray ;
20+ import org .json .JSONException ;
21+
2122import org .robolectric .annotation .Config ;
2223import org .robolectric .annotation .Implementation ;
2324import org .robolectric .annotation .Implements ;
25+ import org .robolectric .RobolectricTestRunner ;
26+ import org .robolectric .RuntimeEnvironment ;
2427import org .robolectric .shadow .api .Shadow ;
2528import org .robolectric .shadows .ShadowBuild ;
2629import org .robolectric .shadows .ShadowInputMethodManager ;
2730
28- import io . flutter . Log ;
29- import io . flutter . embedding . engine . FlutterJNI ;
31+ import org . mockito . ArgumentCaptor ;
32+
3033import io .flutter .embedding .engine .dart .DartExecutor ;
34+ import io .flutter .embedding .engine .FlutterJNI ;
3135import io .flutter .embedding .engine .systemchannels .TextInputChannel ;
36+ import io .flutter .plugin .common .BinaryMessenger ;
3237import io .flutter .plugin .common .JSONMethodCodec ;
3338import io .flutter .plugin .common .MethodCall ;
3439import io .flutter .plugin .platform .PlatformViewsController ;
3540
3641import static org .junit .Assert .assertEquals ;
3742import static org .junit .Assert .assertTrue ;
43+
44+ import static org .mockito .Mockito .any ;
3845import static org .mockito .Mockito .mock ;
3946import static org .mockito .Mockito .spy ;
4047import static org .mockito .Mockito .times ;
4350@ Config (manifest = Config .NONE , shadows = TextInputPluginTest .TestImm .class , sdk = 27 )
4451@ RunWith (RobolectricTestRunner .class )
4552public class TextInputPluginTest {
53+ // Verifies the method and arguments for a captured method call.
54+ private void verifyMethodCall (ByteBuffer buffer , String methodName , String [] expectedArgs ) throws JSONException {
55+ buffer .rewind ();
56+ MethodCall methodCall = JSONMethodCodec .INSTANCE .decodeMethodCall (buffer );
57+ assertEquals (methodName , methodCall .method );
58+ if (expectedArgs != null ) {
59+ JSONArray args = methodCall .arguments ();
60+ assertEquals (expectedArgs .length , args .length ());
61+ for (int i = 0 ; i < args .length (); i ++) {
62+ assertEquals (expectedArgs [i ], args .get (i ).toString ());
63+ }
64+ }
65+ }
66+
4667 @ Test
47- public void textInputPlugin_RequestsReattachOnCreation () {
68+ public void textInputPlugin_RequestsReattachOnCreation () throws JSONException {
4869 // Initialize a general TextInputPlugin.
4970 InputMethodSubtype inputMethodSubtype = mock (InputMethodSubtype .class );
5071 TestImm testImm = Shadow .extract (RuntimeEnvironment .application .getSystemService (Context .INPUT_METHOD_SERVICE ));
@@ -55,8 +76,12 @@ public void textInputPlugin_RequestsReattachOnCreation() {
5576 DartExecutor dartExecutor = spy (new DartExecutor (mockFlutterJni , mock (AssetManager .class )));
5677 TextInputPlugin textInputPlugin = new TextInputPlugin (testView , dartExecutor , mock (PlatformViewsController .class ));
5778
58- ByteBuffer message = JSONMethodCodec .INSTANCE .encodeMethodCall (new MethodCall ("TextInputClient.requestExistingInputState" , null ));
59- verify (dartExecutor , times (1 )).send ("flutter/textinput" , message , null );
79+ ArgumentCaptor <String > channelCaptor = ArgumentCaptor .forClass (String .class );
80+ ArgumentCaptor <ByteBuffer > bufferCaptor = ArgumentCaptor .forClass (ByteBuffer .class );
81+
82+ verify (dartExecutor , times (1 )).send (channelCaptor .capture (), bufferCaptor .capture (), any (BinaryMessenger .BinaryReply .class ));
83+ assertEquals ("flutter/textinput" , channelCaptor .getValue ());
84+ verifyMethodCall (bufferCaptor .getValue (), "TextInputClient.requestExistingInputState" , null );
6085 }
6186
6287 @ Test
@@ -161,33 +186,40 @@ public void setTextInputEditingState_nullInputMethodSubtype() {
161186 }
162187
163188 @ Test
164- public void inputConnection_createsActionFromEnter () {
165- Log .setLogLevel (android .util .Log .VERBOSE );
189+ public void inputConnection_createsActionFromEnter () throws JSONException {
166190 TestImm testImm = Shadow .extract (RuntimeEnvironment .application .getSystemService (Context .INPUT_METHOD_SERVICE ));
167191 FlutterJNI mockFlutterJni = mock (FlutterJNI .class );
168192 View testView = new View (RuntimeEnvironment .application );
169193 DartExecutor dartExecutor = spy (new DartExecutor (mockFlutterJni , mock (AssetManager .class )));
170194 TextInputPlugin textInputPlugin = new TextInputPlugin (testView , dartExecutor , mock (PlatformViewsController .class ));
171- textInputPlugin .setTextInputClient (0 , new TextInputChannel .Configuration (false , false , true , TextInputChannel .TextCapitalization .NONE , new TextInputChannel .InputType (TextInputChannel .TextInputType .TEXT , false , false ), null , null ));
195+ textInputPlugin .setTextInputClient (
196+ 0 ,
197+ new TextInputChannel .Configuration (
198+ false , false , true , TextInputChannel .TextCapitalization .NONE ,
199+ new TextInputChannel .InputType (TextInputChannel .TextInputType .TEXT , false , false ), null , null ));
172200 // There's a pending restart since we initialized the text input client. Flush that now.
173201 textInputPlugin .setTextInputEditingState (testView , new TextInputChannel .TextEditState ("" , 0 , 0 ));
174202
175-
176- ByteBuffer message = JSONMethodCodec .INSTANCE .encodeMethodCall (
177- new MethodCall ("TextInputClient.performAction" , Arrays .asList (0 , "TextInputAction.done" )));
178- verify (dartExecutor , times (1 )).send ("flutter/textinput" , message , null );
203+ ArgumentCaptor <String > channelCaptor = ArgumentCaptor .forClass (String .class );
204+ ArgumentCaptor <ByteBuffer > bufferCaptor = ArgumentCaptor .forClass (ByteBuffer .class );
205+ verify (dartExecutor , times (1 )).send (channelCaptor .capture (), bufferCaptor .capture (), any (BinaryMessenger .BinaryReply .class ));
206+ assertEquals ("flutter/textinput" , channelCaptor .getValue ());
207+ verifyMethodCall (bufferCaptor .getValue (), "TextInputClient.requestExistingInputState" , null );
179208 InputConnection connection = textInputPlugin .createInputConnection (testView , new EditorInfo ());
180209
181210 connection .sendKeyEvent (new KeyEvent (KeyEvent .ACTION_DOWN , KeyEvent .KEYCODE_ENTER ));
182- verify (dartExecutor , times (2 )).send ("flutter/textinput" , message , null );
211+ verify (dartExecutor , times (2 )).send (channelCaptor .capture (), bufferCaptor .capture (), any (BinaryMessenger .BinaryReply .class ));
212+ assertEquals ("flutter/textinput" , channelCaptor .getValue ());
213+ verifyMethodCall (bufferCaptor .getValue (), "TextInputClient.performAction" , new String [] {"0" , "TextInputAction.done" });
183214 connection .sendKeyEvent (new KeyEvent (KeyEvent .ACTION_UP , KeyEvent .KEYCODE_ENTER ));
184215
185216 connection .sendKeyEvent (new KeyEvent (KeyEvent .ACTION_DOWN , KeyEvent .KEYCODE_NUMPAD_ENTER ));
186- verify (dartExecutor , times (3 )).send ("flutter/textinput" , message , null );
217+ verify (dartExecutor , times (3 )).send (channelCaptor .capture (), bufferCaptor .capture (), any (BinaryMessenger .BinaryReply .class ));
218+ assertEquals ("flutter/textinput" , channelCaptor .getValue ());
219+ verifyMethodCall (bufferCaptor .getValue (), "TextInputClient.performAction" , new String [] {"0" , "TextInputAction.done" });
187220 connection .sendKeyEvent (new KeyEvent (KeyEvent .ACTION_UP , KeyEvent .KEYCODE_NUMPAD_ENTER ));
188221 }
189222
190-
191223 @ Implements (InputMethodManager .class )
192224 public static class TestImm extends ShadowInputMethodManager {
193225 private InputMethodSubtype currentInputMethodSubtype ;
0 commit comments