From 498b7c676c7214597c63e97b05cc3274732b8a3f Mon Sep 17 00:00:00 2001 From: Daniel Frett Date: Mon, 18 Mar 2024 16:48:51 -0600 Subject: [PATCH 1/4] lift the languages menu expanded boolen out of the LanguagesFilter This change will allow us to implement Paparazzi Tests for the LanguagesFilter Menu --- .../ui/dashboard/tools/ToolFilters.kt | 23 ++--- .../ui/dashboard/tools/ToolsPresenter.kt | 11 ++- .../ui/dashboard/tools/ToolsScreen.kt | 2 + .../ui/dashboard/tools/ToolFiltersTest.kt | 38 +++----- .../ui/dashboard/tools/ToolsPresenterTest.kt | 97 ++++++++++++++++++- 5 files changed, 127 insertions(+), 44 deletions(-) diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt index 5331ab04e2..1b16bf4ed1 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt @@ -134,13 +134,10 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M val selectedLanguage by rememberUpdatedState(filters.selectedLanguage) val eventSink by rememberUpdatedState(filters.eventSink) - var expanded by rememberSaveable { mutableStateOf(false) } + val expanded by rememberUpdatedState(filters.showLanguagesMenu) ElevatedButton( - onClick = { - if (!expanded) eventSink(ToolsScreen.FiltersEvent.UpdateLanguageQuery("")) - expanded = !expanded - }, + onClick = { eventSink(ToolsScreen.FiltersEvent.ToggleLanguagesMenu) }, modifier = modifier ) { Text( @@ -154,10 +151,8 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M LazyDropdownMenu( expanded = expanded, - onDismissRequest = { expanded = false }, - modifier = Modifier - .sizeIn(maxHeight = DROPDOWN_MAX_HEIGHT, maxWidth = DROPDOWN_MAX_WIDTH) - .testTag(TEST_TAG_FILTER_DROPDOWN) + onDismissRequest = { eventSink(ToolsScreen.FiltersEvent.ToggleLanguagesMenu) }, + modifier = Modifier.sizeIn(maxHeight = DROPDOWN_MAX_HEIGHT, maxWidth = DROPDOWN_MAX_WIDTH) ) { item { SearchBar( @@ -175,10 +170,7 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M FilterMenuItem( label = stringResource(R.string.dashboard_tools_section_filter_language_any), supportingText = stringResource(R.string.dashboard_tools_section_filter_available_tools_all), - onClick = { - eventSink(ToolsScreen.FiltersEvent.SelectLanguage(null)) - expanded = false - } + onClick = { eventSink(ToolsScreen.FiltersEvent.SelectLanguage(null)) } ) } @@ -190,10 +182,7 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M count, count, ), - onClick = { - eventSink(ToolsScreen.FiltersEvent.SelectLanguage(it.code)) - expanded = false - }, + onClick = { eventSink(ToolsScreen.FiltersEvent.SelectLanguage(it.code)) }, modifier = Modifier.animateItemPlacement() ) } diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenter.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenter.kt index d944fbd000..09980b2eb9 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenter.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenter.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import com.slack.circuit.codegen.annotations.CircuitInject import com.slack.circuit.runtime.Navigator @@ -98,7 +99,8 @@ class ToolsPresenter @AssistedInject constructor( // selected language val selectedLocale by remember { settings.getDashboardFilterLocaleFlow() }.collectAsState(null) - var languageQuery by remember { mutableStateOf("") } + var showLanguagesMenu by rememberSaveable { mutableStateOf(false) } + var languageQuery by rememberSaveable { mutableStateOf("") } val filtersEventSink: (ToolsScreen.FiltersEvent) -> Unit = remember { { @@ -108,8 +110,14 @@ class ToolsPresenter @AssistedInject constructor( } is ToolsScreen.FiltersEvent.SelectLanguage -> scope.launch { settings.updateDashboardFilterLocale(it.locale) + showLanguagesMenu = false + languageQuery = "" } is ToolsScreen.FiltersEvent.UpdateLanguageQuery -> languageQuery = it.query + ToolsScreen.FiltersEvent.ToggleLanguagesMenu -> { + showLanguagesMenu = !showLanguagesMenu + languageQuery = "" + } } } } @@ -117,6 +125,7 @@ class ToolsPresenter @AssistedInject constructor( return ToolsScreen.Filters( categories = rememberFilterCategories(selectedLocale), selectedCategory = selectedCategory, + showLanguagesMenu = showLanguagesMenu, languages = rememberFilterLanguages(selectedCategory, languageQuery), languageQuery = languageQuery, selectedLanguage = languagesRepository.rememberLanguage(selectedLocale), diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsScreen.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsScreen.kt index bb48999973..24c55f9d0e 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsScreen.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsScreen.kt @@ -23,6 +23,7 @@ data object ToolsScreen : Screen { data class Filters( val categories: List> = emptyList(), val selectedCategory: String? = null, + val showLanguagesMenu: Boolean = false, val languages: List> = emptyList(), val languageQuery: String = "", val selectedLanguage: Language? = null, @@ -36,6 +37,7 @@ data object ToolsScreen : Screen { } sealed interface FiltersEvent : CircuitUiEvent { + data object ToggleLanguagesMenu : FiltersEvent data class UpdateLanguageQuery(val query: String) : FiltersEvent data class SelectCategory(val category: String?) : FiltersEvent data class SelectLanguage(val locale: Locale?) : FiltersEvent diff --git a/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersTest.kt b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersTest.kt index 10b691192f..f34ec10f7e 100644 --- a/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersTest.kt +++ b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersTest.kt @@ -1,6 +1,7 @@ package org.cru.godtools.ui.dashboard.tools import android.app.Application +import androidx.compose.ui.test.assertHasClickAction import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag @@ -14,7 +15,6 @@ import org.cru.godtools.model.Tool import org.cru.godtools.ui.dashboard.tools.ToolsScreen.Filters.Filter import org.junit.Rule import org.junit.Test -import org.junit.experimental.categories.Categories.CategoryFilter import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -167,18 +167,19 @@ class ToolFiltersTest { } @Test - fun `LanguageFilter() - Dropdown Menu - Show when button is clicked`() { + fun `LanguageFilter() - Button toggles menu`() { composeTestRule.setContent { - LanguageFilter(ToolsScreen.Filters(eventSink = events)) + LanguageFilter( + ToolsScreen.Filters( + selectedLanguage = Language(Locale.ENGLISH), + eventSink = events, + ) + ) } - // dropdown menu not shown - composeTestRule.onNodeWithTag(TEST_TAG_FILTER_DROPDOWN).assertDoesNotExist() - // click button to show dropdown - composeTestRule.onNode(hasClickAction()).performClick() - composeTestRule.onNodeWithTag(TEST_TAG_FILTER_DROPDOWN).assertExists() - events.assertEvent(ToolsScreen.FiltersEvent.UpdateLanguageQuery("")) + composeTestRule.onNodeWithText("English").assertHasClickAction().performClick() + events.assertEvent(ToolsScreen.FiltersEvent.ToggleLanguagesMenu) } @Test @@ -186,6 +187,7 @@ class ToolFiltersTest { composeTestRule.setContent { LanguageFilter( filters = ToolsScreen.Filters( + showLanguagesMenu = true, languages = listOf( Filter(Language(Locale.FRENCH), 1), Filter(Language(Locale.GERMAN), 1), @@ -194,12 +196,10 @@ class ToolFiltersTest { ), ) } - composeTestRule.onNode(hasClickAction()).performClick() composeTestRule.onNodeWithText("English", substring = true, ignoreCase = true).assertDoesNotExist() composeTestRule.onNodeWithText("French", substring = true, ignoreCase = true).assertExists() composeTestRule.onNodeWithText("German", substring = true, ignoreCase = true).assertExists() - events.assertEvent(ToolsScreen.FiltersEvent.UpdateLanguageQuery("")) } @Test @@ -208,6 +208,7 @@ class ToolFiltersTest { LanguageFilter( filters = ToolsScreen.Filters( selectedLanguage = Language(Locale.FRENCH), + showLanguagesMenu = true, languages = listOf( Filter(Language(Locale.FRENCH), 1), Filter(Language(Locale.GERMAN), 1), @@ -216,14 +217,9 @@ class ToolFiltersTest { ), ) } - composeTestRule.onNode(hasClickAction()).performClick() composeTestRule.onNodeWithText("Any language", substring = true, ignoreCase = true).performClick() - composeTestRule.onNodeWithTag(TEST_TAG_FILTER_DROPDOWN).assertDoesNotExist() - events.assertEvents( - ToolsScreen.FiltersEvent.UpdateLanguageQuery(""), - ToolsScreen.FiltersEvent.SelectLanguage(null) - ) + events.assertEvent(ToolsScreen.FiltersEvent.SelectLanguage(null)) } @Test @@ -231,6 +227,7 @@ class ToolFiltersTest { composeTestRule.setContent { LanguageFilter( filters = ToolsScreen.Filters( + showLanguagesMenu = true, languages = listOf( Filter(Language(Locale.FRENCH), 1), Filter(Language(Locale.GERMAN), 1), @@ -239,14 +236,9 @@ class ToolFiltersTest { ), ) } - composeTestRule.onNode(hasClickAction()).performClick() composeTestRule.onNodeWithText("French", substring = true, ignoreCase = true).performClick() - composeTestRule.onNodeWithTag(TEST_TAG_FILTER_DROPDOWN).assertDoesNotExist() - events.assertEvents( - ToolsScreen.FiltersEvent.UpdateLanguageQuery(""), - ToolsScreen.FiltersEvent.SelectLanguage(Locale.FRENCH) - ) + events.assertEvents(ToolsScreen.FiltersEvent.SelectLanguage(Locale.FRENCH)) } // endregion LanguageFilter } diff --git a/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenterTest.kt b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenterTest.kt index ffad804768..b0d7396a6b 100644 --- a/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenterTest.kt +++ b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolsPresenterTest.kt @@ -16,7 +16,9 @@ import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertNull +import kotlin.test.assertTrue import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest @@ -32,6 +34,7 @@ import org.cru.godtools.model.randomTool import org.cru.godtools.model.randomTranslation import org.cru.godtools.ui.banner.BannerType import org.cru.godtools.ui.dashboard.tools.ToolsScreen.Filters.Filter +import org.cru.godtools.ui.dashboard.tools.ToolsScreen.FiltersEvent import org.cru.godtools.ui.tools.FakeToolCardPresenter import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -220,6 +223,25 @@ class ToolsPresenterTest { } // endregion State.filters.categories + // region State.filters.showLanguagesMenu + @Test + fun `State - filters - showLanguagesMenu`() = runTest { + presenter.test { + with(expectMostRecentItem()) { + assertFalse(filters.showLanguagesMenu) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + with(expectMostRecentItem()) { + assertTrue(filters.showLanguagesMenu) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + assertFalse(expectMostRecentItem().filters.showLanguagesMenu) + } + } + // endregion State.filters.showLanguagesMenu + // region State.filters.languages @Test fun `State - filters - languages - no category`() = runTest { @@ -240,7 +262,7 @@ class ToolsPresenterTest { val languages = listOf(Language(Locale.ENGLISH), Language(Locale.FRENCH)) presenter.test { - awaitItem().filters.eventSink(ToolsScreen.FiltersEvent.SelectCategory(Tool.CATEGORY_GOSPEL)) + awaitItem().filters.eventSink(FiltersEvent.SelectCategory(Tool.CATEGORY_GOSPEL)) gospelLanguagesFlow.value = languages assertEquals(languages.map { Filter(it, 0) }, expectMostRecentItem().filters.languages) @@ -271,6 +293,26 @@ class ToolsPresenterTest { ) } } + + @Test + fun `State - filters - languages - filtered by languageQuery`() = runTest { + val languages = listOf(Language(Locale.ENGLISH), Language(Locale.FRENCH)) + languagesFlow.value = languages + + presenter.test { + expectMostRecentItem().filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + with(expectMostRecentItem()) { + assertEquals(languages.map { Filter(it, 0) }, filters.languages) + filters.eventSink(FiltersEvent.UpdateLanguageQuery("french")) + } + + assertEquals(listOf(Filter(Language(Locale.FRENCH), 0)), expectMostRecentItem().filters.languages) + } + + verifyAll { + languagesRepository.getLanguagesFlow() + } + } // endregion State.filters.languages // region State.filters.selectedLanguage @@ -286,7 +328,7 @@ class ToolsPresenterTest { @Test fun `State - filters - selectedLanguage - language not found`() = runTest { presenter.test { - awaitItem().filters.eventSink(ToolsScreen.FiltersEvent.SelectLanguage(Locale.ENGLISH)) + awaitItem().filters.eventSink(FiltersEvent.SelectLanguage(Locale.ENGLISH)) assertNull(expectMostRecentItem().filters.selectedLanguage) } @@ -300,7 +342,7 @@ class ToolsPresenterTest { every { languagesRepository.findLanguageFlow(Locale.ENGLISH) } returns flowOf(language) presenter.test { - awaitItem().filters.eventSink(ToolsScreen.FiltersEvent.SelectLanguage(Locale.ENGLISH)) + awaitItem().filters.eventSink(FiltersEvent.SelectLanguage(Locale.ENGLISH)) assertEquals(language, expectMostRecentItem().filters.selectedLanguage) } @@ -309,6 +351,55 @@ class ToolsPresenterTest { } // endregion State.filters.selectedLanguage + // region FiltersEvent.ToggleLanguagesMenu + @Test + fun `FiltersEvent - ToggleLanguagesMenu`() = runTest { + presenter.test { + with(expectMostRecentItem()) { + assertFalse(filters.showLanguagesMenu) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + with(expectMostRecentItem()) { + assertTrue(filters.showLanguagesMenu) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + assertFalse(expectMostRecentItem().filters.showLanguagesMenu) + } + } + + @Test + fun `FiltersEvent - ToggleLanguagesMenu - resets languageQuery`() = runTest { + presenter.test { + expectMostRecentItem().filters.eventSink(FiltersEvent.UpdateLanguageQuery("test")) + + with(expectMostRecentItem()) { + assertFalse(filters.showLanguagesMenu) + assertEquals("test", filters.languageQuery) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + with(expectMostRecentItem()) { + assertTrue(filters.showLanguagesMenu) + assertEquals("", filters.languageQuery) + filters.eventSink(FiltersEvent.UpdateLanguageQuery("test")) + } + + with(expectMostRecentItem()) { + assertTrue(filters.showLanguagesMenu) + assertEquals("test", filters.languageQuery) + filters.eventSink(FiltersEvent.ToggleLanguagesMenu) + } + + with(expectMostRecentItem()) { + assertFalse(filters.showLanguagesMenu) + assertEquals("", filters.languageQuery) + } + } + } + // endregion FiltersEvent.ToggleLanguagesMenu + // region State.tools @Test fun `State - tools - return only default variants`() = runTest { From 3f0b28e1d40d8188490542fb272fc647066e740f Mon Sep 17 00:00:00 2001 From: Daniel Frett Date: Wed, 20 Mar 2024 11:21:08 -0600 Subject: [PATCH 2/4] add a couple paparazzi tests for the LanguageFilter --- ... English Selected[NIGHT,ACCESSIBILITY].png | 3 + ...glish Selected[NIGHT,NO_ACCESSIBILITY].png | 3 + ...glish Selected[NOTNIGHT,ACCESSIBILITY].png | 3 + ...sh Selected[NOTNIGHT,NO_ACCESSIBILITY].png | 3 + ...Language Selected[NIGHT,ACCESSIBILITY].png | 3 + ...guage Selected[NIGHT,NO_ACCESSIBILITY].png | 3 + ...guage Selected[NOTNIGHT,ACCESSIBILITY].png | 3 + ...ge Selected[NOTNIGHT,NO_ACCESSIBILITY].png | 3 + .../tools/ToolFiltersPaparazziTest.kt | 57 +++++++++++++++++++ 9 files changed, 81 insertions(+) create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,NO_ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,NO_ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,NO_ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png create mode 100644 app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,NO_ACCESSIBILITY].png create mode 100644 app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersPaparazziTest.kt diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png new file mode 100644 index 0000000000..d1d80663f5 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6d876097442dbed9d6b4ffaa281e0985b6d676bc9352eccbd9f4658b752920e +size 12797 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,NO_ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,NO_ACCESSIBILITY].png new file mode 100644 index 0000000000..6821f99c11 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,NO_ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3aeac6822ed967928a9a65cee7679ffa16e213c4ab54eb94467127830ad62cc9 +size 7229 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png new file mode 100644 index 0000000000..38f06ace61 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e2e7aa4a3fada2a3f4b671bf1bf4b83aab4ec9ed6ca1bcbf79efe60745a37b6 +size 13173 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,NO_ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,NO_ACCESSIBILITY].png new file mode 100644 index 0000000000..3e5fd150e6 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,NO_ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d4b70cb2a18c05f06696561bdc764387aa8f1a80ee13a1f94c15484d4d5dabe +size 7419 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png new file mode 100644 index 0000000000..2ed57d636f --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c82b286d766984cc4ef71065973c583715258580024f21ef2f2d4306281bc221 +size 15080 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,NO_ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,NO_ACCESSIBILITY].png new file mode 100644 index 0000000000..4def56feb6 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,NO_ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c80abbf5dafed4b0167e3b017bc39535ea9aacd01c6fb3174230615fd209046d +size 8607 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png new file mode 100644 index 0000000000..7a4d03e7a8 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cac9279757e47149d87abd59997591992345a6da038b7756e6c8860c39c6d079 +size 15250 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,NO_ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,NO_ACCESSIBILITY].png new file mode 100644 index 0000000000..fbb28328d6 --- /dev/null +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,NO_ACCESSIBILITY].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f78a14ea9ed98db7e5c370bb4c5690938aea38eeb0807d81090e752e72596d8 +size 8652 diff --git a/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersPaparazziTest.kt b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersPaparazziTest.kt new file mode 100644 index 0000000000..7c29294e24 --- /dev/null +++ b/app/src/testDebug/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFiltersPaparazziTest.kt @@ -0,0 +1,57 @@ +package org.cru.godtools.ui.dashboard.tools + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.ui.Modifier +import com.android.resources.NightMode +import com.google.testing.junit.testparameterinjector.TestParameter +import com.google.testing.junit.testparameterinjector.TestParameterInjector +import java.util.Locale +import kotlin.test.Ignore +import kotlin.test.Test +import org.cru.godtools.model.Language +import org.cru.godtools.ui.BasePaparazziTest +import org.junit.runner.RunWith + +@RunWith(TestParameterInjector::class) +class ToolFiltersPaparazziTest( + @TestParameter nightMode: NightMode, + @TestParameter accessibilityMode: AccessibilityMode, +) : BasePaparazziTest(nightMode = nightMode, accessibilityMode = accessibilityMode) { + @Test + fun `LanguageFilter - Button - No Language Selected`() = renderLanguageFilter( + ToolsScreen.Filters( + selectedLanguage = null, + showLanguagesMenu = false, + ) + ) + + @Test + fun `LanguageFilter - Button - English Selected`() = renderLanguageFilter( + ToolsScreen.Filters( + selectedLanguage = Language(Locale.ENGLISH), + showLanguagesMenu = false, + ) + ) + + // TODO: It appears that LayoutLib does not correctly support Popups/Windows currently + // see: https://issuetracker.google.com/issues/317792376 + // see: https://issuetracker.google.com/issues/308808808 + // see: https://issuetracker.google.com/issues/321623569 + @Test + @Ignore("Ignored for now due to LayoutLib rendering issues") + fun `LanguageFilter - Dropdown Menu`() = renderLanguageFilter( + ToolsScreen.Filters( + selectedLanguage = Language(Locale.ENGLISH), + showLanguagesMenu = true, + languages = listOf( + ToolsScreen.Filters.Filter(Language(Locale.ENGLISH), 12345), + ToolsScreen.Filters.Filter(Language(Locale.FRENCH), 1), + ToolsScreen.Filters.Filter(Language(Locale("es")), 3), + ), + ) + ) + + private fun renderLanguageFilter(filters: ToolsScreen.Filters) = centerInSnapshot { + LanguageFilter(filters, modifier = Modifier.fillMaxWidth(0.5f)) + } +} From 8f4816a8a8ca9b3aa43d0775ca15e3d320f11e5c Mon Sep 17 00:00:00 2001 From: Daniel Frett Date: Wed, 20 Mar 2024 11:37:57 -0600 Subject: [PATCH 3/4] make the searchbar sticky for the languages filter menu --- .../ui/dashboard/tools/ToolFilters.kt | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt index 1b16bf4ed1..c8ca0ac943 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Search @@ -20,6 +21,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SearchBar +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -43,7 +45,7 @@ import org.cru.godtools.ui.languages.LanguageName import org.jetbrains.annotations.VisibleForTesting private val DROPDOWN_MAX_HEIGHT = 700.dp -private val DROPDOWN_MAX_WIDTH = 400.dp +private val DROPDOWN_MAX_WIDTH = 350.dp internal const val TEST_TAG_FILTER_DROPDOWN = "filter_dropdown" @@ -154,19 +156,28 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M onDismissRequest = { eventSink(ToolsScreen.FiltersEvent.ToggleLanguagesMenu) }, modifier = Modifier.sizeIn(maxHeight = DROPDOWN_MAX_HEIGHT, maxWidth = DROPDOWN_MAX_WIDTH) ) { + stickyHeader { + Surface(color = MaterialTheme.colorScheme.surface) { + SearchBar( + query, + onQueryChange = { eventSink(ToolsScreen.FiltersEvent.UpdateLanguageQuery(it)) }, + onSearch = { eventSink(ToolsScreen.FiltersEvent.UpdateLanguageQuery(it)) }, + active = false, + onActiveChange = {}, + colors = GodToolsTheme.searchBarColors, + leadingIcon = { Icon(Icons.Filled.Search, null) }, + placeholder = { + Text(stringResource(R.string.language_settings_downloadable_languages_search)) + }, + content = {}, + modifier = Modifier + .padding(horizontal = 12.dp) + .fillMaxWidth() + .wrapContentWidth() + ) + } + } item { - SearchBar( - query, - onQueryChange = { eventSink(ToolsScreen.FiltersEvent.UpdateLanguageQuery(it)) }, - onSearch = { eventSink(ToolsScreen.FiltersEvent.UpdateLanguageQuery(it)) }, - active = false, - onActiveChange = {}, - colors = GodToolsTheme.searchBarColors, - leadingIcon = { Icon(Icons.Filled.Search, null) }, - placeholder = { Text(stringResource(R.string.language_settings_downloadable_languages_search)) }, - content = {}, - modifier = Modifier.padding(horizontal = 12.dp) - ) FilterMenuItem( label = stringResource(R.string.dashboard_tools_section_filter_language_any), supportingText = stringResource(R.string.dashboard_tools_section_filter_available_tools_all), From b725ed17c4d605f14ec152130845a14f632bab83 Mon Sep 17 00:00:00 2001 From: Daniel Frett Date: Wed, 20 Mar 2024 11:53:42 -0600 Subject: [PATCH 4/4] change the role of the Category & Language filters to be dropdown lists --- .../org/cru/godtools/ui/dashboard/tools/ToolFilters.kt | 7 +++++-- ...er - Button - English Selected[NIGHT,ACCESSIBILITY].png | 4 ++-- ...- Button - English Selected[NOTNIGHT,ACCESSIBILITY].png | 4 ++-- ... Button - No Language Selected[NIGHT,ACCESSIBILITY].png | 4 ++-- ...tton - No Language Selected[NOTNIGHT,ACCESSIBILITY].png | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt index c8ca0ac943..f6a57e760b 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/tools/ToolFilters.kt @@ -34,6 +34,9 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import org.ccci.gto.android.common.androidx.compose.material3.ui.menu.LazyDropdownMenu @@ -82,7 +85,7 @@ internal fun CategoryFilter(filters: ToolsScreen.Filters, modifier: Modifier = M ElevatedButton( onClick = { expanded = !expanded }, - modifier = modifier + modifier = modifier.semantics { role = Role.DropdownList } ) { Text( selectedCategory?.let { getToolCategoryName(it, LocalContext.current) } @@ -140,7 +143,7 @@ internal fun LanguageFilter(filters: ToolsScreen.Filters, modifier: Modifier = M ElevatedButton( onClick = { eventSink(ToolsScreen.FiltersEvent.ToggleLanguagesMenu) }, - modifier = modifier + modifier = modifier.semantics { role = Role.DropdownList } ) { Text( text = selectedLanguage?.getDisplayName(context, LocalAppLanguage.current) diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png index d1d80663f5..6e6ca3ac1e 100644 --- a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NIGHT,ACCESSIBILITY].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6d876097442dbed9d6b4ffaa281e0985b6d676bc9352eccbd9f4658b752920e -size 12797 +oid sha256:4c599f05c82887a735d3cec203a2fc6434a7b926a722f82c7a8db707088ac29b +size 13554 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png index 38f06ace61..4c5652303e 100644 --- a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - English Selected[NOTNIGHT,ACCESSIBILITY].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e2e7aa4a3fada2a3f4b671bf1bf4b83aab4ec9ed6ca1bcbf79efe60745a37b6 -size 13173 +oid sha256:17462506379ffbfe285b590ae59805957f47dd3ff48df10429ca8c2c87c243d1 +size 13888 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png index 2ed57d636f..ceb1b910a1 100644 --- a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NIGHT,ACCESSIBILITY].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c82b286d766984cc4ef71065973c583715258580024f21ef2f2d4306281bc221 -size 15080 +oid sha256:a3c9ae2834b1575795594aa9c10fd35a4c22d077b2914ac9b4efb39d39638396 +size 15723 diff --git a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png index 7a4d03e7a8..5f558ec47c 100644 --- a/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png +++ b/app/src/test/snapshots/images/org.cru.godtools.ui.dashboard.tools_ToolFiltersPaparazziTest_LanguageFilter - Button - No Language Selected[NOTNIGHT,ACCESSIBILITY].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cac9279757e47149d87abd59997591992345a6da038b7756e6c8860c39c6d079 -size 15250 +oid sha256:e2355a06d1aa33766a4931c9e3c1a8ef7324cc1f21a771136ef92bbbb52c0e75 +size 15951