66
77import static org .junit .Assert .assertNotNull ;
88import static org .junit .Assert .assertNull ;
9+ import static org .mockito .ArgumentMatchers .anyInt ;
910import static org .mockito .Mockito .mock ;
1011import static org .mockito .Mockito .verify ;
1112import static org .mockito .Mockito .when ;
1213
1314import android .app .Activity ;
1415import android .content .Context ;
16+ import androidx .biometric .BiometricManager ;
1517import androidx .lifecycle .Lifecycle ;
1618import io .flutter .embedding .engine .FlutterEngine ;
1719import io .flutter .embedding .engine .dart .DartExecutor ;
2022import io .flutter .embedding .engine .plugins .lifecycle .HiddenLifecycleReference ;
2123import io .flutter .plugin .common .MethodCall ;
2224import io .flutter .plugin .common .MethodChannel ;
25+ import java .util .ArrayList ;
26+ import java .util .Collections ;
2327import org .junit .Test ;
2428
2529public class LocalAuthTest {
@@ -31,6 +35,50 @@ public void isDeviceSupportedReturnsFalse() {
3135 verify (mockResult ).success (false );
3236 }
3337
38+ @ Test
39+ public void deviceSupportsBiometrics_returnsTrueForPresentNonEnrolledBiometrics () {
40+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
41+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
42+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
43+ when (mockBiometricManager .canAuthenticate ())
44+ .thenReturn (BiometricManager .BIOMETRIC_ERROR_NONE_ENROLLED );
45+ plugin .setBiometricManager (mockBiometricManager );
46+ plugin .onMethodCall (new MethodCall ("deviceSupportsBiometrics" , null ), mockResult );
47+ verify (mockResult ).success (true );
48+ }
49+
50+ @ Test
51+ public void deviceSupportsBiometrics_returnsTrueForPresentEnrolledBiometrics () {
52+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
53+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
54+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
55+ when (mockBiometricManager .canAuthenticate ()).thenReturn (BiometricManager .BIOMETRIC_SUCCESS );
56+ plugin .setBiometricManager (mockBiometricManager );
57+ plugin .onMethodCall (new MethodCall ("deviceSupportsBiometrics" , null ), mockResult );
58+ verify (mockResult ).success (true );
59+ }
60+
61+ @ Test
62+ public void deviceSupportsBiometrics_returnsFalseForNoBiometricHardware () {
63+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
64+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
65+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
66+ when (mockBiometricManager .canAuthenticate ())
67+ .thenReturn (BiometricManager .BIOMETRIC_ERROR_NO_HARDWARE );
68+ plugin .setBiometricManager (mockBiometricManager );
69+ plugin .onMethodCall (new MethodCall ("deviceSupportsBiometrics" , null ), mockResult );
70+ verify (mockResult ).success (false );
71+ }
72+
73+ @ Test
74+ public void deviceSupportsBiometrics_returnsFalseForNullBiometricManager () {
75+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
76+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
77+ plugin .setBiometricManager (null );
78+ plugin .onMethodCall (new MethodCall ("deviceSupportsBiometrics" , null ), mockResult );
79+ verify (mockResult ).success (false );
80+ }
81+
3482 @ Test
3583 public void onDetachedFromActivity_ShouldReleaseActivity () {
3684 final Activity mockActivity = mock (Activity .class );
@@ -61,4 +109,122 @@ public void onDetachedFromActivity_ShouldReleaseActivity() {
61109 plugin .onDetachedFromActivity ();
62110 assertNull (plugin .getActivity ());
63111 }
112+
113+ @ Test
114+ public void getEnrolledBiometrics_shouldReturnError_whenNoActivity () {
115+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
116+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
117+
118+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
119+ verify (mockResult )
120+ .error ("no_activity" , "local_auth plugin requires a foreground activity" , null );
121+ }
122+
123+ @ Test
124+ public void getEnrolledBiometrics_shouldReturnError_whenFinishingActivity () {
125+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
126+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
127+ final Activity mockActivity = buildMockActivity ();
128+ when (mockActivity .isFinishing ()).thenReturn (true );
129+ setPluginActivity (plugin , mockActivity );
130+
131+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
132+ verify (mockResult )
133+ .error ("no_activity" , "local_auth plugin requires a foreground activity" , null );
134+ }
135+
136+ @ Test
137+ public void getEnrolledBiometrics_shouldReturnEmptyList_withoutHardwarePresent () {
138+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
139+ setPluginActivity (plugin , buildMockActivity ());
140+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
141+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
142+ when (mockBiometricManager .canAuthenticate (anyInt ()))
143+ .thenReturn (BiometricManager .BIOMETRIC_ERROR_NO_HARDWARE );
144+ plugin .setBiometricManager (mockBiometricManager );
145+
146+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
147+ verify (mockResult ).success (Collections .emptyList ());
148+ }
149+
150+ @ Test
151+ public void getEnrolledBiometrics_shouldReturnEmptyList_withNoMethodsEnrolled () {
152+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
153+ setPluginActivity (plugin , buildMockActivity ());
154+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
155+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
156+ when (mockBiometricManager .canAuthenticate (anyInt ()))
157+ .thenReturn (BiometricManager .BIOMETRIC_ERROR_NONE_ENROLLED );
158+ plugin .setBiometricManager (mockBiometricManager );
159+
160+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
161+ verify (mockResult ).success (Collections .emptyList ());
162+ }
163+
164+ @ Test
165+ public void getEnrolledBiometrics_shouldOnlyAddEnrolledBiometrics () {
166+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
167+ setPluginActivity (plugin , buildMockActivity ());
168+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
169+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
170+ when (mockBiometricManager .canAuthenticate (BiometricManager .Authenticators .BIOMETRIC_WEAK ))
171+ .thenReturn (BiometricManager .BIOMETRIC_SUCCESS );
172+ when (mockBiometricManager .canAuthenticate (BiometricManager .Authenticators .BIOMETRIC_STRONG ))
173+ .thenReturn (BiometricManager .BIOMETRIC_ERROR_NONE_ENROLLED );
174+ plugin .setBiometricManager (mockBiometricManager );
175+
176+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
177+ verify (mockResult )
178+ .success (
179+ new ArrayList <String >() {
180+ {
181+ add ("weak" );
182+ }
183+ });
184+ }
185+
186+ @ Test
187+ public void getEnrolledBiometrics_shouldAddStrongBiometrics () {
188+ final LocalAuthPlugin plugin = new LocalAuthPlugin ();
189+ setPluginActivity (plugin , buildMockActivity ());
190+ final MethodChannel .Result mockResult = mock (MethodChannel .Result .class );
191+ final BiometricManager mockBiometricManager = mock (BiometricManager .class );
192+ when (mockBiometricManager .canAuthenticate (BiometricManager .Authenticators .BIOMETRIC_WEAK ))
193+ .thenReturn (BiometricManager .BIOMETRIC_SUCCESS );
194+ when (mockBiometricManager .canAuthenticate (BiometricManager .Authenticators .BIOMETRIC_STRONG ))
195+ .thenReturn (BiometricManager .BIOMETRIC_SUCCESS );
196+ plugin .setBiometricManager (mockBiometricManager );
197+
198+ plugin .onMethodCall (new MethodCall ("getEnrolledBiometrics" , null ), mockResult );
199+ verify (mockResult )
200+ .success (
201+ new ArrayList <String >() {
202+ {
203+ add ("weak" );
204+ add ("strong" );
205+ }
206+ });
207+ }
208+
209+ private Activity buildMockActivity () {
210+ final Activity mockActivity = mock (Activity .class );
211+ final Context mockContext = mock (Context .class );
212+ when (mockActivity .getBaseContext ()).thenReturn (mockContext );
213+ when (mockActivity .getApplicationContext ()).thenReturn (mockContext );
214+ return mockActivity ;
215+ }
216+
217+ private void setPluginActivity (LocalAuthPlugin plugin , Activity activity ) {
218+ final HiddenLifecycleReference mockLifecycleReference = mock (HiddenLifecycleReference .class );
219+ final FlutterPluginBinding mockPluginBinding = mock (FlutterPluginBinding .class );
220+ final ActivityPluginBinding mockActivityBinding = mock (ActivityPluginBinding .class );
221+ final FlutterEngine mockFlutterEngine = mock (FlutterEngine .class );
222+ final DartExecutor mockDartExecutor = mock (DartExecutor .class );
223+ when (mockPluginBinding .getFlutterEngine ()).thenReturn (mockFlutterEngine );
224+ when (mockFlutterEngine .getDartExecutor ()).thenReturn (mockDartExecutor );
225+ when (mockActivityBinding .getActivity ()).thenReturn (activity );
226+ when (mockActivityBinding .getLifecycle ()).thenReturn (mockLifecycleReference );
227+ plugin .onAttachedToEngine (mockPluginBinding );
228+ plugin .onAttachedToActivity (mockActivityBinding );
229+ }
64230}
0 commit comments