Flutter Engine
The Flutter Engine
SingleViewPresentationTest.java
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package io.flutter.plugin.platform;
6
7import static io.flutter.Build.API_LEVELS;
8import static org.junit.Assert.assertEquals;
9import static org.mockito.Mockito.mock;
10import static org.mockito.Mockito.spy;
11import static org.mockito.Mockito.when;
12
13import android.annotation.TargetApi;
14import android.content.Context;
15import android.hardware.display.DisplayManager;
16import android.view.Display;
17import android.view.inputmethod.InputMethodManager;
18import androidx.test.core.app.ApplicationProvider;
19import androidx.test.ext.junit.runners.AndroidJUnit4;
20import org.junit.Test;
21import org.junit.runner.RunWith;
22import org.robolectric.annotation.Config;
23
24@Config(manifest = Config.NONE)
25@RunWith(AndroidJUnit4.class)
26@TargetApi(API_LEVELS.API_28)
28 @Test
29 @Config(minSdk = API_LEVELS.API_21, maxSdk = API_LEVELS.API_30)
30 public void returnsOuterContextInputMethodManager() {
31 // There's a bug in Android Q caused by the IMM being instanced per display.
32 // https://github.com/flutter/flutter/issues/38375. We need the context returned by
33 // SingleViewPresentation to be consistent from its instantiation instead of defaulting to
34 // what the system would have returned at call time.
35
36 // It's not possible to set up the exact same conditions as the unit test in the bug here,
37 // but we can make sure that we're wrapping the Context passed in at instantiation time and
38 // returning the same InputMethodManager from it. This test passes in a Spy context instance
39 // that initially returns a mock. Without the bugfix this test falls back to Robolectric's
40 // system service instead of the spy's and fails.
41
42 // Create an SVP under test with a Context that returns a local IMM mock.
43 Context context = spy(ApplicationProvider.getApplicationContext());
44 InputMethodManager expected = mock(InputMethodManager.class);
45 when(context.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(expected);
46 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
48 new SingleViewPresentation(context, dm.getDisplay(0), null, null, null, false);
49
50 // Get the IMM from the SVP's context.
51 InputMethodManager actual =
52 (InputMethodManager) svp.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
53
54 // This should be the mocked instance from construction, not the IMM from the greater
55 // Android OS (or Robolectric's shadow, in this case).
56 assertEquals(expected, actual);
57 }
58
59 @Test
60 @Config(minSdk = API_LEVELS.API_21, maxSdk = API_LEVELS.API_30)
61 public void returnsOuterContextInputMethodManager_createDisplayContext() {
62 // The IMM should also persist across display contexts created from the base context.
63
64 // Create an SVP under test with a Context that returns a local IMM mock.
65 Context context = spy(ApplicationProvider.getApplicationContext());
66 InputMethodManager expected = mock(InputMethodManager.class);
67 when(context.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(expected);
68 Display display =
69 ((DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE)).getDisplay(0);
71 new SingleViewPresentation(context, display, null, null, null, false);
72
73 // Get the IMM from the SVP's context.
74 InputMethodManager actual =
75 (InputMethodManager)
76 svp.getContext()
77 .createDisplayContext(display)
78 .getSystemService(Context.INPUT_METHOD_SERVICE);
79
80 // This should be the mocked instance from construction, not the IMM from the greater
81 // Android OS (or Robolectric's shadow, in this case).
82 assertEquals(expected, actual);
83 }
84}
static final int API_21
Definition: Build.java:11
static final int API_30
Definition: Build.java:20