blob: 59e4f2b1465d17bd0cd61496c2e1b78c4947d7ba [file] [log] [blame]
Cole Faustd4e193b2019-10-03 09:49:26 -07001/*
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
17package com.android.car.ui.toolbar;
18
19import static com.google.common.truth.Truth.assertThat;
20
Ram Parameswaran05fec072019-10-17 13:24:27 -070021import static org.mockito.Mockito.spy;
22import static org.mockito.Mockito.when;
23
Cole Faustd4e193b2019-10-03 09:49:26 -070024import android.content.Context;
Ram Parameswaran05fec072019-10-17 13:24:27 -070025import android.content.res.Resources;
Cole Faustd4e193b2019-10-03 09:49:26 -070026import android.view.View;
27import android.view.ViewGroup;
28
29import com.android.car.ui.CarUiRobolectricTestRunner;
30import com.android.car.ui.R;
Cole Faustb2830152019-10-10 14:49:43 -070031import com.android.car.ui.utils.ShadowTypeface;
Cole Faustd4e193b2019-10-03 09:49:26 -070032
33import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.robolectric.Robolectric;
37import org.robolectric.RuntimeEnvironment;
38import org.robolectric.android.controller.ActivityController;
39import org.robolectric.annotation.Config;
40
41import java.util.Arrays;
42import java.util.Collections;
43import java.util.List;
44
45@RunWith(CarUiRobolectricTestRunner.class)
Cole Faustb2830152019-10-10 14:49:43 -070046@Config(qualifiers = "land", shadows = ShadowTypeface.class)
Cole Faustd4e193b2019-10-03 09:49:26 -070047public class ToolbarTest {
48
49 private Context mContext;
Ram Parameswaran05fec072019-10-17 13:24:27 -070050 private Resources mResources;
Cole Faustd4e193b2019-10-03 09:49:26 -070051 private ActivityController<TestActivity> mActivityController;
52 private TestActivity mActivity;
53 private Toolbar mToolbar;
54
55 @Before
56 public void setUp() {
57 mContext = RuntimeEnvironment.application;
Ram Parameswaran05fec072019-10-17 13:24:27 -070058 mResources = mContext.getResources();
Cole Faustd4e193b2019-10-03 09:49:26 -070059 mActivityController = Robolectric.buildActivity(TestActivity.class);
60 mActivityController.setup();
Cole Faustd4e193b2019-10-03 09:49:26 -070061 mActivity = mActivityController.get();
62 mToolbar = mActivity.findViewById(R.id.toolbar);
63 }
64
65 @Test
66 public void getters_nochanges_shouldReturnDefaults() {
67 assertThat(mToolbar.getBackgroundShown()).isEqualTo(true);
68 assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(false);
69 assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.HOME);
70 assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
71 Toolbar.NavButtonMode.BACK);
72 }
73
74 @Test
75 public void setState_subpage_shouldCauseGetStateToReturnSubpage() {
76 mToolbar.setState(Toolbar.State.SUBPAGE);
77
78 assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
79 }
80
81 @Test
82 public void configurationChange_shouldNotLoseProperties() {
83 mToolbar.setTitle("Foo");
84 mToolbar.setSearchHint("Foo2");
85 mToolbar.setBackgroundShown(false);
86 mToolbar.setShowMenuItemsWhileSearching(true);
87 mToolbar.setState(Toolbar.State.SUBPAGE);
88 mToolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
89
90 // TODO this is supposed to change the configuration, but doesn't
91 RuntimeEnvironment.setQualifiers("+port");
92 mActivityController.configurationChange();
93 mActivity = mActivityController.get();
94 mToolbar = mActivity.findViewById(R.id.toolbar);
95
96 assertThat(mToolbar.getTitle().toString()).isEqualTo("Foo");
97 assertThat(mToolbar.getSearchHint().toString()).isEqualTo("Foo2");
98 assertThat(mToolbar.getBackgroundShown()).isEqualTo(false);
99 assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(true);
100 assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
101 assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
102 Toolbar.NavButtonMode.CLOSE);
103 }
104
105 @Test
106 public void setCustomView_shouldInflateViewIntoToolbar() {
107 mToolbar.setCustomView(R.layout.test_custom_view);
108
109 View v = mToolbar.findViewById(R.id.text_box_1);
110
111 assertThat(v).isNotNull();
112 assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(
113 Toolbar.State.SUBPAGE_CUSTOM);
114 }
115
116 @Test
117 public void showLogo_whenSet_andStateIsHome() {
118 mToolbar.setState(Toolbar.State.HOME);
119 mToolbar.setLogo(R.drawable.test_ic_launcher);
120
Cole Faustdb6866c2019-10-09 15:56:07 -0700121 assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isTrue();
Cole Faustd4e193b2019-10-03 09:49:26 -0700122 }
123
124 @Test
125 public void hideLogo_whenSet_andStateIsNotHome() {
126 mToolbar.setState(Toolbar.State.SUBPAGE);
127 mToolbar.setLogo(R.drawable.test_ic_launcher);
128
Cole Faustdb6866c2019-10-09 15:56:07 -0700129 assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
Cole Faustd4e193b2019-10-03 09:49:26 -0700130 }
131
132 @Test
133 public void hideLogo_whenNotSet_andStateIsHome() {
134 mToolbar.setState(Toolbar.State.HOME);
135 mToolbar.setLogo(0);
136
Cole Faustdb6866c2019-10-09 15:56:07 -0700137 assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
Cole Faustd4e193b2019-10-03 09:49:26 -0700138 }
139
140 @Test
141 public void hideLogo_whenNotSet_andStateIsNotHome() {
142 mToolbar.setState(Toolbar.State.SUBPAGE);
143 mToolbar.setLogo(0);
144
Cole Faustdb6866c2019-10-09 15:56:07 -0700145 assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
Cole Faustd4e193b2019-10-03 09:49:26 -0700146 }
147
148 @Test
149 public void registerOnBackListener_whenBackIsPressed_shouldCallListener() {
150 mToolbar.setState(Toolbar.State.SUBPAGE);
151 Mutable<Integer> timesBackPressed = new Mutable<>(0);
152 Toolbar.OnBackListener listener = () -> {
153 timesBackPressed.value++;
154 return false;
155 };
156
157 mToolbar.registerOnBackListener(listener);
158 pressBack();
159
160 assertThat(timesBackPressed.value).isEqualTo(1);
161 assertThat(mActivity.getTimesBackPressed()).isEqualTo(1);
162 }
163
164 @Test
165 public void registerOnBackListener_whenAListenerReturnsTrue_shouldSuppressBack() {
166 mToolbar.setState(Toolbar.State.SUBPAGE);
167
168 mToolbar.registerOnBackListener(() -> true);
169 pressBack();
170 mToolbar.registerOnBackListener(() -> false);
171 pressBack();
172
173 assertThat(mActivity.getTimesBackPressed()).isEqualTo(0);
174 }
175
176 @Test
Ram Parameswaran05fec072019-10-17 13:24:27 -0700177 public void testState_twoRow_withTitle_withTabs() {
178 mockResources();
179 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
180
181 Toolbar toolbar = new Toolbar(mContext);
182 assertThat(toolbar.isTabsInSecondRow()).isTrue();
183
184 // Set title and tabs for toolbar.
185 toolbar.setTitle("Test title");
186 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
187 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
188
189 // Toolbar should display two rows, showing both title and tabs.
190 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
191 View.VISIBLE);
192 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
193 View.VISIBLE);
194 }
195
196 @Test
197 public void testState_twoRow_withTitle() {
198 mockResources();
199 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
200
201 Toolbar toolbar = new Toolbar(mContext);
202 assertThat(toolbar.isTabsInSecondRow()).isTrue();
203
204 toolbar.setTitle("Test title");
205
206 // Toolbar should display two rows, but no tabs are set so they should not be visible.
207 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
208 View.VISIBLE);
209 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
210 View.VISIBLE);
211 }
212
213 @Test
214 public void testState_twoRow_withTabs() {
215 mockResources();
216 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
217
218 Toolbar toolbar = new Toolbar(mContext);
219 assertThat(toolbar.isTabsInSecondRow()).isTrue();
220 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
221 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
222
223 // Toolbar should display two rows with an empty title and tabs.
224 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
225 View.VISIBLE);
226 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
227 View.VISIBLE);
228 }
229
230 @Test
231 public void testState_oneRow_withTitle_withTabs() {
232 mockResources();
233 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
234
235 Toolbar toolbar = new Toolbar(mContext);
236 assertThat(toolbar.isTabsInSecondRow()).isFalse();
237
238 // Set title and tabs for toolbar.
239 toolbar.setTitle("Test title");
240 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
241 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
242
243 // With only one row available, toolbar will only show tabs and not the title.
244 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
245 View.VISIBLE);
246 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
247 View.VISIBLE);
248 }
249
250 @Test
251 public void testState_oneRow_withTitle() {
252 mockResources();
253 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
254
255
256 Toolbar toolbar = new Toolbar(mContext);
257 assertThat(toolbar.isTabsInSecondRow()).isFalse();
258
259 toolbar.setTitle("Test title");
260
261 // Toolbar should display one row with the title and no tabs.
262 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
263 View.VISIBLE);
264 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
265 View.VISIBLE);
266 }
267
268 @Test
269 public void testState_oneRow_withTabs() {
270 mockResources();
271 when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
272
273
274 Toolbar toolbar = new Toolbar(mContext);
275 assertThat(toolbar.isTabsInSecondRow()).isFalse();
276
277 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
278 toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
279
280 // Toolbar should display one row with only tabs.
281 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
282 View.VISIBLE);
283 assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
284 View.VISIBLE);
285 }
286
287 @Test
Cole Faustd4e193b2019-10-03 09:49:26 -0700288 public void registerOnBackListener_whenListenerRegisteredTwice_shouldntCallListenerTwice() {
289 mToolbar.setState(Toolbar.State.SUBPAGE);
290 Mutable<Integer> timesBackPressed = new Mutable<>(0);
291 Toolbar.OnBackListener listener = () -> {
292 timesBackPressed.value++;
293 return false;
294 };
295
296 // Registering a second time shouldn't do anything
297 mToolbar.registerOnBackListener(listener);
298 mToolbar.registerOnBackListener(listener);
299 pressBack();
300
301 assertThat(timesBackPressed.value).isEqualTo(1);
302 }
303
304 @Test
305 public void unregisterOnBackListener_previouslyRegisteredListener_shouldUnregister() {
306 mToolbar.setState(Toolbar.State.SUBPAGE);
307 Mutable<Integer> timesBackPressed = new Mutable<>(0);
308 Toolbar.OnBackListener listener = () -> {
309 timesBackPressed.value++;
310 return false;
311 };
312
313 mToolbar.registerOnBackListener(listener);
314 mToolbar.unregisterOnBackListener(listener);
315 pressBack();
316
317 assertThat(timesBackPressed.value).isEqualTo(0);
318 }
319
320 @Test
321 public void menuItems_whenClicked_shouldCallListener() {
Cole Faustdb6866c2019-10-09 15:56:07 -0700322 assertThat(getMenuItemViewCount()).isEqualTo(0);
Cole Faustd4e193b2019-10-03 09:49:26 -0700323
324 Mutable<Boolean> button1Clicked = new Mutable<>(false);
325 Mutable<Boolean> button2Clicked = new Mutable<>(false);
326 mToolbar.setMenuItems(Arrays.asList(
327 createMenuItem(i -> button1Clicked.value = true),
328 createMenuItem(i -> button2Clicked.value = true)));
329
Cole Faustdb6866c2019-10-09 15:56:07 -0700330 assertThat(getMenuItemViewCount()).isEqualTo(2);
Cole Faustd4e193b2019-10-03 09:49:26 -0700331
Cole Faustdb6866c2019-10-09 15:56:07 -0700332 getMenuItemView(0).performClick();
Cole Faustd4e193b2019-10-03 09:49:26 -0700333
334 assertThat(button1Clicked.value).isTrue();
335
Cole Faustdb6866c2019-10-09 15:56:07 -0700336 getMenuItemView(1).performClick();
Cole Faustd4e193b2019-10-03 09:49:26 -0700337
338 assertThat(button2Clicked.value).isTrue();
339 }
340
341 @Test
342 public void menuItems_null_shouldRemoveExistingMenuItems() {
343 mToolbar.setMenuItems(Arrays.asList(
Ram Parameswaran05fec072019-10-17 13:24:27 -0700344 createMenuItem(i -> {
345 }),
346 createMenuItem(i -> {
347 })));
Cole Faustd4e193b2019-10-03 09:49:26 -0700348
Cole Faustdb6866c2019-10-09 15:56:07 -0700349 assertThat(getMenuItemViewCount()).isEqualTo(2);
Cole Faustd4e193b2019-10-03 09:49:26 -0700350
351 mToolbar.setMenuItems(null);
352
Cole Faustdb6866c2019-10-09 15:56:07 -0700353 assertThat(getMenuItemViewCount()).isEqualTo(0);
Cole Faustd4e193b2019-10-03 09:49:26 -0700354 }
355
356 @Test
357 public void menuItems_setVisibility_shouldDefaultToShown() {
Ram Parameswaran05fec072019-10-17 13:24:27 -0700358 MenuItem item = createMenuItem(i -> {
359 });
Cole Faustd4e193b2019-10-03 09:49:26 -0700360 mToolbar.setMenuItems(Collections.singletonList(item));
361
Cole Faustdb6866c2019-10-09 15:56:07 -0700362 assertThat(getMenuItemView(0).isShown()).isTrue();
Cole Faustd4e193b2019-10-03 09:49:26 -0700363 }
364
365 @Test
366 public void menuItems_setVisibility_shouldHide() {
Ram Parameswaran05fec072019-10-17 13:24:27 -0700367 MenuItem item = createMenuItem(i -> {
368 });
Cole Faustd4e193b2019-10-03 09:49:26 -0700369 mToolbar.setMenuItems(Collections.singletonList(item));
370
Cole Faustd4e193b2019-10-03 09:49:26 -0700371 item.setVisible(false);
Cole Faustdb6866c2019-10-09 15:56:07 -0700372 assertThat(getMenuItemView(0).isShown()).isFalse();
Cole Faustd4e193b2019-10-03 09:49:26 -0700373 }
374
375 @Test
376 public void menuItems_setVisibility_shouldReshowAfterHiding() {
Ram Parameswaran05fec072019-10-17 13:24:27 -0700377 MenuItem item = createMenuItem(i -> {
378 });
Cole Faustd4e193b2019-10-03 09:49:26 -0700379 mToolbar.setMenuItems(Collections.singletonList(item));
380
Cole Faustd4e193b2019-10-03 09:49:26 -0700381 item.setVisible(false);
382 item.setVisible(true);
Cole Faustdb6866c2019-10-09 15:56:07 -0700383 assertThat(getMenuItemView(0).isShown()).isTrue();
Cole Faustd4e193b2019-10-03 09:49:26 -0700384 }
385
386 @Test
387 public void menuItems_equalItems_shouldntRecreateViews() {
388 List<MenuItem> menuItems = Arrays.asList(
Ram Parameswaran05fec072019-10-17 13:24:27 -0700389 createMenuItem(i -> {
390 }),
391 createMenuItem(i -> {
392 }));
Cole Faustd4e193b2019-10-03 09:49:26 -0700393 mToolbar.setMenuItems(menuItems);
394
Cole Faustdb6866c2019-10-09 15:56:07 -0700395 assertThat(getMenuItemViewCount()).isEqualTo(2);
Cole Faustd4e193b2019-10-03 09:49:26 -0700396
Cole Faustdb6866c2019-10-09 15:56:07 -0700397 View firstMenuItemView = getMenuItemView(0);
Cole Faustd4e193b2019-10-03 09:49:26 -0700398
399 mToolbar.setMenuItems(menuItems);
400
Cole Faustdb6866c2019-10-09 15:56:07 -0700401 assertThat(firstMenuItemView).isSameAs(getMenuItemView(0));
Cole Faustd4e193b2019-10-03 09:49:26 -0700402 }
403
404 @Test
405 public void menuItems_searchScreen_shouldHideMenuItems() {
406 mToolbar.setMenuItems(Arrays.asList(
Ram Parameswaran05fec072019-10-17 13:24:27 -0700407 MenuItem.Builder.createSearch(mContext, i -> {
408 }),
409 createMenuItem(i -> {
410 })));
Cole Faustd4e193b2019-10-03 09:49:26 -0700411
412 mToolbar.setShowMenuItemsWhileSearching(false);
413 mToolbar.setState(Toolbar.State.SEARCH);
414
Cole Faustdb6866c2019-10-09 15:56:07 -0700415 assertThat(getMenuItemView(0).isShown()).isFalse();
416 assertThat(getMenuItemView(1).isShown()).isFalse();
Cole Faustd4e193b2019-10-03 09:49:26 -0700417 }
418
419 @Test
420 public void menuItems_showMenuItemsWhileSearching() {
421 mToolbar.setMenuItems(Arrays.asList(
Ram Parameswaran05fec072019-10-17 13:24:27 -0700422 MenuItem.Builder.createSearch(mContext, i -> {
423 }),
424 createMenuItem(i -> {
425 })));
Cole Faustd4e193b2019-10-03 09:49:26 -0700426
427 mToolbar.setShowMenuItemsWhileSearching(true);
428 mToolbar.setState(Toolbar.State.SEARCH);
429
Cole Faustdb6866c2019-10-09 15:56:07 -0700430 assertThat(getMenuItemView(0).isShown()).isFalse();
431 assertThat(getMenuItemView(1).isShown()).isTrue();
Cole Faustd4e193b2019-10-03 09:49:26 -0700432 }
433
434 private MenuItem createMenuItem(MenuItem.OnClickListener listener) {
435 return new MenuItem.Builder(mContext)
436 .setTitle("Button!")
437 .setOnClickListener(listener)
438 .build();
439 }
440
Ram Parameswaran05fec072019-10-17 13:24:27 -0700441 private void mockResources() {
442 mContext = spy(RuntimeEnvironment.application);
443 mResources = spy(mContext.getResources());
444 when(mContext.getResources()).thenReturn(mResources);
445 }
446
Cole Faustdb6866c2019-10-09 15:56:07 -0700447 private int getMenuItemViewCount() {
448 return ((ViewGroup) mToolbar
449 .findViewById(R.id.car_ui_toolbar_menu_items_container))
450 .getChildCount();
451 }
452
453 private View getMenuItemView(int index) {
454 return ((ViewGroup) mToolbar
455 .findViewById(R.id.car_ui_toolbar_menu_items_container))
456 .getChildAt(index);
457 }
458
Cole Faustd4e193b2019-10-03 09:49:26 -0700459 private void pressBack() {
Cole Faustdb6866c2019-10-09 15:56:07 -0700460 mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).performClick();
Cole Faustd4e193b2019-10-03 09:49:26 -0700461 }
462
463 private static class Mutable<T> {
464 public T value;
465
466 Mutable(T value) {
467 this.value = value;
468 }
469 }
470
471}