From 677a65d143ddf42de7bcab28100421bf5bbcd593 Mon Sep 17 00:00:00 2001 From: Joshua Trask Date: Thu, 5 Oct 2023 19:43:40 +0000 Subject: `showEmptyState()` -> EmptyStateUiHelper As part of ongoing work to pull low-level empty state responsibilities out of the pager adapter, this CL generally replicates the change prototyped in ag/24516421/5..7, in smaller incremental steps to "show the work." As originally described in that CL: "... moves most of the low-level logic of `showEmptyState()` into the UI helper. (...) also has the UI helper take responsibility for setting the visibility of the main "list view" in sync (opposite of) the empty state visibility." As presented in this CL, the "incremental steps" per-snapshot are: 1. Extract most of the implementation directly to the new method at `EmptyStateUiHelper.showEmptyState()`. The general functionality is covered by existing integration tests (e.g., commenting-out the new method body causes `UnbundledChooserActivityWorkProfileTest` to fail). New `EmptyStateUiHelper` unit tests cover finer points of the empty-state "button" conditions, and I've added a TODO comment at one place legacy behavior seemingly may not align with the original developer intent. 2. Also make the UI helper responsible for propagating empty-state visibility changes back to the main list view (hiding the main list when we show an empty state, and restoring it when the empty state is hidden). 3. Look up all the sub-views during `EmptyStateUiHelper` construction so we don't have to keep repeating their View IDs throughout. 4. Tighten visibility on `EmptyStateUiHelper.resetViewVisibilities()` now that it's a private `showEmptyState()` implementation detail (updated to package-protected/visible-for-testing). Also move the method to the end of the class (after all the public methods). Bug: 302311217 Test: IntentResolverUnitTests Change-Id: Iac0cf3d62e2c3bf22afa6a2796ae4e731b706c02 --- .../v2/emptystate/EmptyStateUiHelperTest.kt | 88 +++++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) (limited to 'java/tests') diff --git a/java/tests/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelperTest.kt b/java/tests/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelperTest.kt index 27ed7e38..696dd1fd 100644 --- a/java/tests/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelperTest.kt +++ b/java/tests/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelperTest.kt @@ -20,12 +20,18 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import android.widget.TextView import androidx.test.platform.app.InstrumentationRegistry +import com.android.intentresolver.any +import com.android.intentresolver.emptystate.EmptyState +import com.android.intentresolver.mock import com.google.common.truth.Truth.assertThat import java.util.Optional import java.util.function.Supplier import org.junit.Before import org.junit.Test +import org.mockito.Mockito.never +import org.mockito.Mockito.verify class EmptyStateUiHelperTest { private val context = InstrumentationRegistry.getInstrumentation().getContext() @@ -37,8 +43,9 @@ class EmptyStateUiHelperTest { } lateinit var rootContainer: ViewGroup - lateinit var emptyStateTitleView: View - lateinit var emptyStateSubtitleView: View + lateinit var mainListView: View // Visible when no empty state is showing. + lateinit var emptyStateTitleView: TextView + lateinit var emptyStateSubtitleView: TextView lateinit var emptyStateButtonView: View lateinit var emptyStateProgressView: View lateinit var emptyStateDefaultTextView: View @@ -55,6 +62,7 @@ class EmptyStateUiHelperTest { rootContainer, true ) + mainListView = rootContainer.requireViewById(com.android.internal.R.id.resolver_list) emptyStateRootView = rootContainer.requireViewById(com.android.internal.R.id.resolver_empty_state) emptyStateTitleView = @@ -68,7 +76,12 @@ class EmptyStateUiHelperTest { emptyStateDefaultTextView = rootContainer.requireViewById(com.android.internal.R.id.empty) emptyStateContainerView = rootContainer.requireViewById(com.android.internal.R.id.resolver_empty_state_container) - emptyStateUiHelper = EmptyStateUiHelper(rootContainer, containerPaddingSupplier) + emptyStateUiHelper = + EmptyStateUiHelper( + rootContainer, + com.android.internal.R.id.resolver_list, + containerPaddingSupplier + ) } @Test @@ -112,10 +125,12 @@ class EmptyStateUiHelperTest { @Test fun testHide() { emptyStateRootView.visibility = View.VISIBLE + mainListView.visibility = View.GONE emptyStateUiHelper.hide() assertThat(emptyStateRootView.visibility).isEqualTo(View.GONE) + assertThat(mainListView.visibility).isEqualTo(View.VISIBLE) } @Test @@ -143,4 +158,71 @@ class EmptyStateUiHelperTest { assertThat(emptyStateContainerView.paddingRight).isEqualTo(3) assertThat(emptyStateContainerView.paddingBottom).isEqualTo(42) } + + @Test + fun testShowEmptyState_noOnClickHandler() { + mainListView.visibility = View.VISIBLE + + // Note: an `EmptyState.ClickListener` isn't invoked directly by the UI helper; it has to be + // built into the "on-click handler" that's injected to implement the button-press. We won't + // display the button without a click "handler," even if it *does* have a `ClickListener`. + val clickListener = mock() + + val emptyState = + object : EmptyState { + override fun getTitle() = "Test title" + override fun getSubtitle() = "Test subtitle" + + override fun getButtonClickListener() = clickListener + } + emptyStateUiHelper.showEmptyState(emptyState, null) + + assertThat(mainListView.visibility).isEqualTo(View.GONE) + assertThat(emptyStateRootView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateTitleView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateSubtitleView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateButtonView.visibility).isEqualTo(View.GONE) + assertThat(emptyStateProgressView.visibility).isEqualTo(View.GONE) + assertThat(emptyStateDefaultTextView.visibility).isEqualTo(View.GONE) + + assertThat(emptyStateTitleView.text).isEqualTo("Test title") + assertThat(emptyStateSubtitleView.text).isEqualTo("Test subtitle") + + verify(clickListener, never()).onClick(any()) + } + + @Test + fun testShowEmptyState_withOnClickHandlerAndClickListener() { + mainListView.visibility = View.VISIBLE + + val clickListener = mock() + val onClickHandler = mock() + + val emptyState = + object : EmptyState { + override fun getTitle() = "Test title" + override fun getSubtitle() = "Test subtitle" + + override fun getButtonClickListener() = clickListener + } + emptyStateUiHelper.showEmptyState(emptyState, onClickHandler) + + assertThat(mainListView.visibility).isEqualTo(View.GONE) + assertThat(emptyStateRootView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateTitleView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateSubtitleView.visibility).isEqualTo(View.VISIBLE) + assertThat(emptyStateButtonView.visibility).isEqualTo(View.VISIBLE) // Now shown. + assertThat(emptyStateProgressView.visibility).isEqualTo(View.GONE) + assertThat(emptyStateDefaultTextView.visibility).isEqualTo(View.GONE) + + assertThat(emptyStateTitleView.text).isEqualTo("Test title") + assertThat(emptyStateSubtitleView.text).isEqualTo("Test subtitle") + + emptyStateButtonView.performClick() + + verify(onClickHandler).onClick(emptyStateButtonView) + // The test didn't explicitly configure its `OnClickListener` to relay the click event on + // to the `EmptyState.ClickListener`, so it still won't have fired here. + verify(clickListener, never()).onClick(any()) + } } -- cgit v1.2.3-59-g8ed1b