Add unit test for Keyboards & HomeScaffold

Bug: 260660819
Test: Unit test
Change-Id: I848684ef1729a24564ae681cefd225203572b562
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Keyboards.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Keyboards.kt
index 8d0313f..3f7cc19 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Keyboards.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Keyboards.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.foundation.text.KeyboardActionScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.snapshotFlow
@@ -32,7 +31,7 @@
  */
 @OptIn(ExperimentalComposeUiApi::class)
 @Composable
-fun hideKeyboardAction(): KeyboardActionScope.() -> Unit {
+fun hideKeyboardAction(): () -> Unit {
     val keyboardController = LocalSoftwareKeyboardController.current
     return { keyboardController?.hide() }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index b4852e4..4218489b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -158,6 +158,7 @@
 private fun SearchBox(query: TextFieldValue, onQueryChange: (TextFieldValue) -> Unit) {
     val focusRequester = remember { FocusRequester() }
     val textStyle = MaterialTheme.typography.bodyLarge
+    val hideKeyboardAction = hideKeyboardAction()
     TextField(
         value = query,
         onValueChange = onQueryChange,
@@ -173,7 +174,7 @@
             )
         },
         keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
-        keyboardActions = KeyboardActions(onSearch = hideKeyboardAction()),
+        keyboardActions = KeyboardActions(onSearch = { hideKeyboardAction() }),
         singleLine = true,
         colors = TextFieldDefaults.textFieldColors(
             containerColor = Color.Transparent,
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/KeyboardsTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/KeyboardsTest.kt
new file mode 100644
index 0000000..944ef7f
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/KeyboardsTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.framework.compose
+
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.Text
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.platform.SoftwareKeyboardController
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@OptIn(ExperimentalComposeUiApi::class)
+@RunWith(AndroidJUnit4::class)
+class KeyboardsTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val mockito: MockitoRule = MockitoJUnit.rule()
+
+    @Mock
+    lateinit var keyboardController: SoftwareKeyboardController
+
+    @Test
+    fun hideKeyboardAction_callControllerHide() {
+        lateinit var action: () -> Unit
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalSoftwareKeyboardController provides keyboardController) {
+                action = hideKeyboardAction()
+            }
+        }
+
+        action()
+
+        verify(keyboardController).hide()
+    }
+
+    @Test
+    fun rememberLazyListStateAndHideKeyboardWhenStartScroll_notCallHideInitially() {
+        setLazyColumn(scroll = false)
+
+        verify(keyboardController, never()).hide()
+    }
+
+    @Test
+    fun rememberLazyListStateAndHideKeyboardWhenStartScroll_callHideWhenScroll() {
+        setLazyColumn(scroll = true)
+
+        verify(keyboardController).hide()
+    }
+
+    private fun setLazyColumn(scroll: Boolean) {
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalSoftwareKeyboardController provides keyboardController) {
+                val lazyListState = rememberLazyListStateAndHideKeyboardWhenStartScroll()
+                LazyColumn(
+                    modifier = Modifier.size(100.dp),
+                    state = lazyListState,
+                ) {
+                    items(count = 10) {
+                        Text(text = it.toString())
+                    }
+                }
+                if (scroll) {
+                    LaunchedEffect(Unit) {
+                        lazyListState.animateScrollToItem(1)
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/HomeScaffoldTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/HomeScaffoldTest.kt
new file mode 100644
index 0000000..6ccbbd0
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/HomeScaffoldTest.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.scaffold
+
+import androidx.compose.material3.Text
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class HomeScaffoldTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @Test
+    fun title_isDisplayed() {
+        composeTestRule.setContent {
+            HomeScaffold(title = TITLE) {
+                Text(text = "AAA")
+                Text(text = "BBB")
+            }
+        }
+
+        composeTestRule.onNodeWithText(TITLE).assertIsDisplayed()
+    }
+
+    @Test
+    fun items_areDisplayed() {
+        composeTestRule.setContent {
+            HomeScaffold(title = TITLE) {
+                Text(text = "AAA")
+                Text(text = "BBB")
+            }
+        }
+
+        composeTestRule.onNodeWithText("AAA").assertIsDisplayed()
+        composeTestRule.onNodeWithText("BBB").assertIsDisplayed()
+    }
+
+    private companion object {
+        const val TITLE = "title"
+    }
+}