• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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 com.android.systemui.controls.ui
18 
19 import android.app.Activity
20 import android.graphics.Color
21 import android.graphics.drawable.ShapeDrawable
22 import android.util.DisplayMetrics
23 import android.view.View
24 import android.view.ViewGroup
25 import android.widget.PopupWindow.OnDismissListener
26 import androidx.test.ext.junit.rules.ActivityScenarioRule
27 import androidx.test.ext.junit.runners.AndroidJUnit4
28 import androidx.test.filters.SmallTest
29 import com.android.systemui.res.R
30 import com.android.systemui.SysuiTestCase
31 import com.android.systemui.activity.EmptyTestActivity
32 import com.android.systemui.util.mockito.whenever
33 import com.android.systemui.widget.FakeListAdapter
34 import com.android.systemui.widget.FakeListAdapter.FakeListAdapterItem
35 import com.google.common.truth.Truth.assertThat
36 import org.junit.Before
37 import org.junit.Rule
38 import org.junit.Test
39 import org.junit.runner.RunWith
40 import org.mockito.Mockito.mock
41 import org.mockito.Mockito.spy
42 import org.mockito.Mockito.verify
43 import org.mockito.MockitoAnnotations
44 
45 @SmallTest
46 @RunWith(AndroidJUnit4::class)
47 open class ControlsPopupMenuTest : SysuiTestCase() {
48 
49     private companion object {
50 
51         const val DISPLAY_WIDTH_NARROW = 100
52         const val DISPLAY_WIDTH_WIDE = 1000
53 
54         const val MAX_WIDTH = 380
55         const val HORIZONTAL_MARGIN = 16
56     }
57 
58     @Rule @JvmField val activityScenarioRule = ActivityScenarioRule(EmptyTestActivity::class.java)
59 
60     private val testDisplayMetrics = DisplayMetrics()
61 
62     @Before
63     fun setup() {
64         MockitoAnnotations.initMocks(this)
65     }
66 
67     @Test
68     fun testDismissListenerWorks() = testPopup { activity, popupMenu ->
69         popupMenu.setAdapter(FakeListAdapter())
70         val listener = mock(OnDismissListener::class.java)
71         popupMenu.setOnDismissListener(listener)
72         popupMenu.show()
73 
74         popupMenu.dismissImmediate()
75 
76         verify(listener).onDismiss()
77     }
78 
79     @Test
80     fun testPopupDoesntExceedMaxWidth() = testPopup { activity, popupMenu ->
81         popupMenu.setAdapter(FakeListAdapter())
82         popupMenu.width = ViewGroup.LayoutParams.MATCH_PARENT
83         testDisplayMetrics.widthPixels = DISPLAY_WIDTH_WIDE
84 
85         popupMenu.show()
86 
87         assertThat(popupMenu.width).isEqualTo(MAX_WIDTH)
88     }
89 
90     @Test
91     fun testPopupMarginsWidthLessMax() = testPopup { activity, popupMenu ->
92         popupMenu.setAdapter(FakeListAdapter())
93         popupMenu.width = ViewGroup.LayoutParams.MATCH_PARENT
94         testDisplayMetrics.widthPixels = DISPLAY_WIDTH_NARROW
95 
96         popupMenu.show()
97 
98         assertThat(popupMenu.width).isEqualTo(DISPLAY_WIDTH_NARROW - 2 * HORIZONTAL_MARGIN)
99     }
100 
101     @Test
102     fun testWrapContentDoesntExceedMax() = testPopup { activity, popupMenu ->
103         popupMenu.setAdapter(
104             FakeListAdapter(
105                 listOf(
106                     FakeListAdapterItem({ _, _, _ ->
107                         View(activity).apply { minimumWidth = MAX_WIDTH + 1 }
108                     })
109                 )
110             )
111         )
112         popupMenu.width = ViewGroup.LayoutParams.WRAP_CONTENT
113         testDisplayMetrics.widthPixels = DISPLAY_WIDTH_NARROW
114 
115         popupMenu.show()
116 
117         assertThat(popupMenu.width).isEqualTo(DISPLAY_WIDTH_NARROW - 2 * HORIZONTAL_MARGIN)
118     }
119 
120     private fun testPopup(test: (activity: Activity, popup: ControlsPopupMenu) -> Unit) {
121         activityScenarioRule.scenario.onActivity { activity ->
122             val testActivity = setupActivity(activity)
123             test(
124                 testActivity,
125                 ControlsPopupMenu(testActivity).apply { anchorView = View(testActivity) }
126             )
127         }
128     }
129 
130     private fun setupActivity(real: Activity): Activity {
131         val resources =
132             spy(real.resources).apply {
133                 whenever(getDimensionPixelSize(R.dimen.control_popup_items_divider_height))
134                     .thenReturn(1)
135                 whenever(getDimensionPixelSize(R.dimen.control_popup_horizontal_margin))
136                     .thenReturn(HORIZONTAL_MARGIN)
137                 whenever(getDimensionPixelSize(R.dimen.control_popup_max_width))
138                     .thenReturn(MAX_WIDTH)
139                 whenever(getDrawable(R.drawable.controls_popup_bg)).thenReturn(ShapeDrawable())
140                 whenever(getColor(R.color.control_popup_dim)).thenReturn(Color.WHITE)
141                 whenever(displayMetrics).thenAnswer { testDisplayMetrics }
142             }
143 
144         return spy(real).also { whenever(it.resources).thenReturn(resources) }
145     }
146 }
147