Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 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 androidx.ui.autofill |
| 18 | |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 19 | import android.app.Activity |
Ralston Da Silva | ad9752a | 2020-06-22 17:55:50 -0700 | [diff] [blame] | 20 | import android.graphics.Rect as AndroidRect |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 21 | import android.view.View |
| 22 | import android.view.autofill.AutofillManager |
| 23 | import androidx.test.filters.SmallTest |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 24 | import androidx.ui.ComposeUiRobolectricTestRunner |
Ralston Da Silva | ad9752a | 2020-06-22 17:55:50 -0700 | [diff] [blame] | 25 | import androidx.ui.core.toComposeRect |
| 26 | import androidx.ui.geometry.Rect |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 27 | import com.google.common.truth.Truth.assertThat |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 28 | import org.junit.Before |
| 29 | import org.junit.Rule |
| 30 | import org.junit.Test |
| 31 | import org.junit.rules.ExpectedException |
| 32 | import org.junit.runner.RunWith |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 33 | import org.robolectric.Robolectric |
| 34 | import org.robolectric.annotation.Config |
| 35 | import org.robolectric.annotation.Implementation |
| 36 | import org.robolectric.annotation.Implements |
| 37 | import org.robolectric.shadow.api.Shadow |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 38 | |
| 39 | @SmallTest |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 40 | @RunWith(ComposeUiRobolectricTestRunner::class) |
| 41 | @Config( |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 42 | shadows = [ShadowAutofillManager::class], |
| 43 | minSdk = 26 |
| 44 | ) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 45 | class AndroidAutofillTest { |
| 46 | |
| 47 | @get:Rule |
| 48 | val expectedException = ExpectedException.none()!! |
| 49 | |
| 50 | private lateinit var androidAutofill: AndroidAutofill |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 51 | private lateinit var autofillManager: ShadowAutofillManager |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 52 | private lateinit var view: View |
| 53 | private val autofillTree = AutofillTree() |
| 54 | |
| 55 | @Before |
| 56 | fun setup() { |
Ralston Da Silva | 28c2289 | 2020-05-06 12:07:02 -0700 | [diff] [blame] | 57 | val activity = Robolectric.buildActivity(Activity::class.java).get() |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 58 | view = View(activity) |
| 59 | activity.setContentView(view) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 60 | |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 61 | autofillManager = Shadow.extract<ShadowAutofillManager>( |
| 62 | activity.getSystemService(AutofillManager::class.java) |
| 63 | ) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 64 | |
| 65 | androidAutofill = AndroidAutofill(view, autofillTree) |
| 66 | } |
| 67 | |
| 68 | @Test |
| 69 | fun importantForAutofill_is_yes() { |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 70 | assertThat(view.importantForAutofill).isEqualTo(View.IMPORTANT_FOR_AUTOFILL_YES) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 71 | } |
| 72 | |
Louis Pullen-Freilich | 689e935 | 2020-06-18 20:40:43 +0100 | [diff] [blame] | 73 | @Test |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 74 | fun requestAutofillForNode_calls_notifyViewEntered() { |
| 75 | // Arrange. |
Nikolay Igotti | 2c24c56 | 2020-06-18 12:49:02 +0300 | [diff] [blame] | 76 | val bounds = Rect(0f, 0f, 0f, 0f) |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 77 | val autofillNode = AutofillNode(onFill = {}, boundingBox = bounds) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 78 | |
| 79 | // Act. |
| 80 | androidAutofill.requestAutofillForNode(autofillNode) |
| 81 | |
| 82 | // Assert. |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 83 | assertThat(autofillManager.viewEnteredStats).containsExactly( |
| 84 | ShadowAutofillManager.NotifyViewEntered(view, autofillNode.id, bounds) |
| 85 | ) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | @Test |
| 89 | fun requestAutofillForNode_beforeComposableIsPositioned_throwsError() { |
| 90 | // Arrange - Before the composable is positioned, the boundingBox is null. |
| 91 | val autofillNode = AutofillNode(onFill = {}) |
| 92 | |
| 93 | // Assert. |
| 94 | expectedException.expectMessage("requestAutofill called before onChildPositioned()") |
| 95 | |
| 96 | // Act. |
| 97 | androidAutofill.requestAutofillForNode(autofillNode) |
| 98 | } |
| 99 | |
| 100 | @Test |
| 101 | fun cancelAutofillForNode_calls_notifyViewExited() { |
| 102 | // Arrange. |
| 103 | val autofillNode = AutofillNode(onFill = {}) |
| 104 | |
| 105 | // Act. |
| 106 | androidAutofill.cancelAutofillForNode(autofillNode) |
| 107 | |
| 108 | // Assert. |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 109 | assertThat(autofillManager.viewExitedStats).containsExactly( |
| 110 | ShadowAutofillManager.NotifyViewExited(view, autofillNode.id) |
| 111 | ) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | @Implements(value = AutofillManager::class, minSdk = 26) |
| 116 | internal class ShadowAutofillManager { |
| 117 | data class NotifyViewEntered(val view: View, val virtualId: Int, val rect: Rect) |
| 118 | data class NotifyViewExited(val view: View, val virtualId: Int) |
| 119 | |
| 120 | val viewEnteredStats = mutableListOf<NotifyViewEntered>() |
| 121 | val viewExitedStats = mutableListOf<NotifyViewExited>() |
| 122 | |
| 123 | @Implementation |
Ralston Da Silva | ad9752a | 2020-06-22 17:55:50 -0700 | [diff] [blame] | 124 | fun notifyViewEntered(view: View, virtualId: Int, rect: AndroidRect) { |
| 125 | viewEnteredStats += NotifyViewEntered(view, virtualId, rect.toComposeRect()) |
Ralston Da Silva | 91f2061 | 2019-08-13 15:07:17 -0700 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | @Implementation |
| 129 | fun notifyViewExited(view: View, virtualId: Int) { |
| 130 | viewExitedStats += NotifyViewExited(view, virtualId) |
Ralston Da Silva | 3e89a47 | 2019-07-31 01:21:51 -0700 | [diff] [blame] | 131 | } |
Nikolay Igotti | 2c24c56 | 2020-06-18 12:49:02 +0300 | [diff] [blame] | 132 | } |