|
27 | 27 | import android.provider.Settings;
|
28 | 28 | import android.text.InputType;
|
29 | 29 | import android.text.Selection;
|
| 30 | +import android.util.SparseArray; |
30 | 31 | import android.util.SparseIntArray;
|
31 | 32 | import android.view.KeyEvent;
|
32 | 33 | import android.view.View;
|
|
55 | 56 | import io.flutter.plugin.platform.PlatformViewsController;
|
56 | 57 | import java.nio.ByteBuffer;
|
57 | 58 | import java.util.ArrayList;
|
| 59 | +import java.util.HashMap; |
58 | 60 | import java.util.List;
|
59 | 61 | import org.json.JSONArray;
|
60 | 62 | import org.json.JSONException;
|
@@ -927,6 +929,92 @@ public void autofill_testLifeCycle() {
|
927 | 929 | assertEquals("1".hashCode(), testAfm.exitId);
|
928 | 930 | }
|
929 | 931 |
|
| 932 | + @Test |
| 933 | + public void autofill_testAutofillUpdatesTheFramework() { |
| 934 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { |
| 935 | + return; |
| 936 | + } |
| 937 | + |
| 938 | + TestAfm testAfm = |
| 939 | + Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class)); |
| 940 | + FlutterView testView = new FlutterView(RuntimeEnvironment.application); |
| 941 | + TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class))); |
| 942 | + TextInputPlugin textInputPlugin = |
| 943 | + new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class)); |
| 944 | + |
| 945 | + // Set up an autofill scenario with 2 fields. |
| 946 | + final TextInputChannel.Configuration.Autofill autofill1 = |
| 947 | + new TextInputChannel.Configuration.Autofill( |
| 948 | + "1", |
| 949 | + new String[] {"HINT1"}, |
| 950 | + new TextInputChannel.TextEditState("field 1", 0, 0, -1, -1)); |
| 951 | + final TextInputChannel.Configuration.Autofill autofill2 = |
| 952 | + new TextInputChannel.Configuration.Autofill( |
| 953 | + "2", |
| 954 | + new String[] {"HINT2", "EXTRA"}, |
| 955 | + new TextInputChannel.TextEditState("field 2", 0, 0, -1, -1)); |
| 956 | + |
| 957 | + final TextInputChannel.Configuration config1 = |
| 958 | + new TextInputChannel.Configuration( |
| 959 | + false, |
| 960 | + false, |
| 961 | + true, |
| 962 | + TextInputChannel.TextCapitalization.NONE, |
| 963 | + null, |
| 964 | + null, |
| 965 | + null, |
| 966 | + autofill1, |
| 967 | + null); |
| 968 | + final TextInputChannel.Configuration config2 = |
| 969 | + new TextInputChannel.Configuration( |
| 970 | + false, |
| 971 | + false, |
| 972 | + true, |
| 973 | + TextInputChannel.TextCapitalization.NONE, |
| 974 | + null, |
| 975 | + null, |
| 976 | + null, |
| 977 | + autofill2, |
| 978 | + null); |
| 979 | + |
| 980 | + final TextInputChannel.Configuration autofillConfiguration = |
| 981 | + new TextInputChannel.Configuration( |
| 982 | + false, |
| 983 | + false, |
| 984 | + true, |
| 985 | + TextInputChannel.TextCapitalization.NONE, |
| 986 | + null, |
| 987 | + null, |
| 988 | + null, |
| 989 | + autofill1, |
| 990 | + new TextInputChannel.Configuration[] {config1, config2}); |
| 991 | + |
| 992 | + textInputPlugin.setTextInputClient(0, autofillConfiguration); |
| 993 | + textInputPlugin.setTextInputEditingState( |
| 994 | + testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1)); |
| 995 | + |
| 996 | + final SparseArray<AutofillValue> autofillValues = new SparseArray(); |
| 997 | + autofillValues.append("1".hashCode(), AutofillValue.forText("focused field")); |
| 998 | + autofillValues.append("2".hashCode(), AutofillValue.forText("unfocused field")); |
| 999 | + |
| 1000 | + // Autofill both fields. |
| 1001 | + textInputPlugin.autofill(autofillValues); |
| 1002 | + |
| 1003 | + // Verify the Editable has been updated. |
| 1004 | + assertTrue(textInputPlugin.getEditable().toString().equals("focused field")); |
| 1005 | + |
| 1006 | + // The autofill value of the focused field is sent via updateEditingState. |
| 1007 | + verify(textInputChannel, times(1)) |
| 1008 | + .updateEditingState(anyInt(), eq("focused field"), eq(13), eq(13), eq(-1), eq(-1)); |
| 1009 | + |
| 1010 | + final ArgumentCaptor<HashMap> mapCaptor = ArgumentCaptor.forClass(HashMap.class); |
| 1011 | + |
| 1012 | + verify(textInputChannel, times(1)).updateEditingStateWithTag(anyInt(), mapCaptor.capture()); |
| 1013 | + final TextInputChannel.TextEditState editState = |
| 1014 | + (TextInputChannel.TextEditState) mapCaptor.getValue().get("2"); |
| 1015 | + assertEquals(editState.text, "unfocused field"); |
| 1016 | + } |
| 1017 | + |
930 | 1018 | @Test
|
931 | 1019 | public void autofill_testSetTextIpnutClientUpdatesSideFields() {
|
932 | 1020 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
0 commit comments