1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.tasks.tab_groups;
6 
7 import static org.hamcrest.CoreMatchers.equalTo;
8 import static org.junit.Assert.assertThat;
9 import static org.mockito.ArgumentMatchers.any;
10 import static org.mockito.ArgumentMatchers.eq;
11 import static org.mockito.Mockito.doReturn;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.verify;
14 import static org.mockito.Mockito.when;
15 
16 import android.content.Context;
17 import android.content.SharedPreferences;
18 
19 import org.junit.Before;
20 import org.junit.Rule;
21 import org.junit.Test;
22 import org.junit.rules.TestRule;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.MockitoAnnotations;
26 import org.robolectric.annotation.Config;
27 
28 import org.chromium.base.ContextUtils;
29 import org.chromium.base.UserDataHost;
30 import org.chromium.chrome.browser.tab.Tab;
31 import org.chromium.chrome.browser.tab.TabImpl;
32 import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
33 import org.chromium.chrome.browser.tabmodel.TabModel;
34 import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
35 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
36 import org.chromium.chrome.browser.tasks.tab_management.TabUiUnitTestUtils;
37 import org.chromium.chrome.test.util.browser.Features;
38 import org.chromium.testing.local.LocalRobolectricTestRunner;
39 
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.List;
43 
44 /**
45  * Tests for {@link TabGroupUtils}.
46  */
47 @SuppressWarnings("ResultOfMethodCallIgnored")
48 @RunWith(LocalRobolectricTestRunner.class)
49 @Config(manifest = Config.NONE)
50 public class TabGroupUtilsUnitTest {
51     @Rule
52     public TestRule mProcessor = new Features.JUnitProcessor();
53 
54     private static final String TAB_GROUP_TITLES_FILE_NAME = "tab_group_titles";
55     private static final String TAB1_TITLE = "Tab1";
56     private static final String TAB2_TITLE = "Tab2";
57     private static final String TAB3_TITLE = "Tab3";
58     private static final int TAB1_ID = 456;
59     private static final int TAB2_ID = 789;
60     private static final int TAB3_ID = 123;
61     private static final int POSITION1 = 0;
62     private static final int POSITION2 = 1;
63     private static final int POSITION3 = 2;
64 
65     @Mock
66     Context mContext;
67     @Mock
68     TabModel mTabModel;
69     @Mock
70     TabModelSelector mTabModelSelector;
71     @Mock
72     TabModelFilterProvider mTabModelFilterProvider;
73     @Mock
74     TabGroupModelFilter mTabGroupModelFilter;
75     @Mock
76     SharedPreferences mSharedPreferences;
77     @Mock
78     SharedPreferences.Editor mEditor;
79     @Mock
80     SharedPreferences.Editor mPutStringEditor;
81     @Mock
82     SharedPreferences.Editor mRemoveEditor;
83 
84     private TabImpl mTab1;
85     private TabImpl mTab2;
86     private TabImpl mTab3;
87 
88     @Before
setUp()89     public void setUp() {
90 
91         MockitoAnnotations.initMocks(this);
92 
93         mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE, "");
94         mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, TAB2_TITLE, "");
95         mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE, "");
96 
97         doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider();
98         doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getCurrentTabModelFilter();
99         doReturn(POSITION1).when(mTabModel).indexOf(mTab1);
100         doReturn(POSITION2).when(mTabModel).indexOf(mTab2);
101         doReturn(POSITION3).when(mTabModel).indexOf(mTab3);
102         doReturn(mSharedPreferences)
103                 .when(mContext)
104                 .getSharedPreferences(TAB_GROUP_TITLES_FILE_NAME, Context.MODE_PRIVATE);
105         doReturn(mEditor).when(mSharedPreferences).edit();
106         doReturn(mRemoveEditor).when(mEditor).remove(any(String.class));
107         doReturn(mPutStringEditor).when(mEditor).putString(any(String.class), any(String.class));
108         ContextUtils.initApplicationContextForTests(mContext);
109     }
110 
111     @Test
testGetSelectedTabInGroupForTab()112     public void testGetSelectedTabInGroupForTab() {
113         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2));
114         createTabGroup(tabs, TAB1_ID);
115         doReturn(mTab1).when(mTabGroupModelFilter).getTabAt(POSITION1);
116         doReturn(POSITION1).when(mTabGroupModelFilter).indexOf(mTab1);
117         doReturn(POSITION1).when(mTabGroupModelFilter).indexOf(mTab2);
118 
119         assertThat(TabGroupUtils.getSelectedTabInGroupForTab(mTabModelSelector, mTab1),
120                 equalTo(mTab1));
121         assertThat(TabGroupUtils.getSelectedTabInGroupForTab(mTabModelSelector, mTab2),
122                 equalTo(mTab1));
123     }
124 
125     @Test
testGetFirstTabModelIndexForList()126     public void testGetFirstTabModelIndexForList() {
127         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, mTab3));
128 
129         assertThat(TabGroupUtils.getFirstTabModelIndexForList(mTabModel, tabs), equalTo(POSITION1));
130     }
131 
132     @Test
testGetLastTabModelIndexForList()133     public void testGetLastTabModelIndexForList() {
134         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, mTab3));
135 
136         assertThat(TabGroupUtils.getLastTabModelIndexForList(mTabModel, tabs), equalTo(POSITION3));
137     }
138 
139     @Test
testDeleteTabGroupTitle()140     public void testDeleteTabGroupTitle() {
141         TabGroupUtils.deleteTabGroupTitle(TAB1_ID);
142 
143         verify(mEditor).remove(eq(String.valueOf(TAB1_ID)));
144         verify(mRemoveEditor).apply();
145     }
146 
147     @Test
testGetTabGroupTitle()148     public void testGetTabGroupTitle() {
149         // Mock that we have a stored tab group title with reference to TAB1_ID.
150         when(mSharedPreferences.getString(
151                      String.valueOf(CriticalPersistedTabData.from(mTab1).getRootId()), null))
152                 .thenReturn(TAB1_TITLE);
153 
154         assertThat(TabGroupUtils.getTabGroupTitle(TAB1_ID), equalTo(TAB1_TITLE));
155     }
156 
157     @Test
testStoreTabGroupTitle()158     public void testStoreTabGroupTitle() {
159         TabGroupUtils.storeTabGroupTitle(TAB1_ID, TAB1_TITLE);
160 
161         verify(mEditor).putString(eq(String.valueOf(TAB1_ID)), eq(TAB1_TITLE));
162         verify(mPutStringEditor).apply();
163     }
164 
createTabGroup(List<Tab> tabs, int rootId)165     private void createTabGroup(List<Tab> tabs, int rootId) {
166         for (Tab tab : tabs) {
167             when(mTabGroupModelFilter.getRelatedTabList(tab.getId())).thenReturn(tabs);
168             CriticalPersistedTabData criticalPersistedTabData =
169                     mock(CriticalPersistedTabData.class);
170             UserDataHost userDataHost = new UserDataHost();
171             userDataHost.setUserData(CriticalPersistedTabData.class, criticalPersistedTabData);
172             doReturn(userDataHost).when(tab).getUserDataHost();
173             doReturn(rootId).when(criticalPersistedTabData).getRootId();
174         }
175     }
176 }
177