1 /* 2 * Copyright (C) 2020 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.documentsui; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.content.Context; 22 import android.net.Uri; 23 import android.os.UserHandle; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 27 import androidx.test.InstrumentationRegistry; 28 29 import com.android.documentsui.base.DocumentInfo; 30 import com.android.documentsui.base.RootInfo; 31 import com.android.documentsui.base.State; 32 import com.android.documentsui.base.UserId; 33 import com.android.documentsui.testing.TestEnv; 34 import com.android.documentsui.testing.TestProvidersAccess; 35 36 import com.google.android.collect.Lists; 37 import com.google.android.material.tabs.TabLayout; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 42 import java.util.Collections; 43 import java.util.List; 44 45 public class ProfileTabsTest { 46 47 private final UserId systemUser = UserId.of(UserHandle.SYSTEM); 48 private final UserId managedUser = UserId.of(100); 49 50 private ProfileTabs mProfileTabs; 51 52 private Context mContext; 53 private TabLayout mTabLayout; 54 private TestEnvironment mTestEnv; 55 private State mState; 56 private TestUserIdManager mTestUserIdManager; 57 private TestCommonAddons mTestCommonAddons; 58 private boolean mIsListenerInvoked; 59 60 @Before setUp()61 public void setUp() { 62 TestEnv.create(); 63 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 64 mContext.setTheme(R.style.DocumentsTheme); 65 mContext.getTheme().applyStyle(R.style.DocumentsDefaultTheme, false); 66 LayoutInflater layoutInflater = LayoutInflater.from(mContext); 67 mState = new State(); 68 mState.supportsCrossProfile = true; 69 mState.stack.changeRoot(TestProvidersAccess.DOWNLOADS); 70 mState.stack.push(TestEnv.FOLDER_0); 71 View view = layoutInflater.inflate(R.layout.directory_header, null); 72 73 mTabLayout = view.findViewById(R.id.tabs); 74 mTestEnv = new TestEnvironment(); 75 mTestEnv.isSearchExpanded = false; 76 77 mTestUserIdManager = new TestUserIdManager(); 78 mTestCommonAddons = new TestCommonAddons(); 79 mTestCommonAddons.mCurrentRoot = TestProvidersAccess.DOWNLOADS; 80 } 81 82 @Test testUpdateView_singleUser_shouldHide()83 public void testUpdateView_singleUser_shouldHide() { 84 initializeWithUsers(systemUser); 85 86 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 87 assertThat(mTabLayout.getTabCount()).isEqualTo(0); 88 } 89 90 @Test testUpdateView_twoUsers_shouldShow()91 public void testUpdateView_twoUsers_shouldShow() { 92 initializeWithUsers(systemUser, managedUser); 93 94 assertThat(mTabLayout.getVisibility()).isEqualTo(View.VISIBLE); 95 assertThat(mTabLayout.getTabCount()).isEqualTo(2); 96 97 TabLayout.Tab tab1 = mTabLayout.getTabAt(0); 98 assertThat(tab1.getTag()).isEqualTo(systemUser); 99 assertThat(tab1.getText()).isEqualTo(mContext.getString(R.string.personal_tab)); 100 101 TabLayout.Tab tab2 = mTabLayout.getTabAt(1); 102 assertThat(tab2.getTag()).isEqualTo(managedUser); 103 assertThat(tab2.getText()).isEqualTo(mContext.getString(R.string.work_tab)); 104 } 105 106 @Test testUpdateView_twoUsers_doesNotSupportCrossProfile_shouldHide()107 public void testUpdateView_twoUsers_doesNotSupportCrossProfile_shouldHide() { 108 initializeWithUsers(systemUser, managedUser); 109 110 mState.supportsCrossProfile = false; 111 mProfileTabs.updateView(); 112 113 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 114 } 115 116 @Test testUpdateView_twoUsers_subFolder_shouldHide()117 public void testUpdateView_twoUsers_subFolder_shouldHide() { 118 initializeWithUsers(systemUser, managedUser); 119 120 // Push 1 more folder. Now the stack has size of 2. 121 mState.stack.push(TestEnv.FOLDER_1); 122 123 mProfileTabs.updateView(); 124 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 125 assertThat(mTabLayout.getTabCount()).isEqualTo(2); 126 } 127 128 @Test testUpdateView_twoUsers_recents_subFolder_shouldHide()129 public void testUpdateView_twoUsers_recents_subFolder_shouldHide() { 130 initializeWithUsers(systemUser, managedUser); 131 132 mState.stack.changeRoot(TestProvidersAccess.RECENTS); 133 // This(stack of size 2 in Recents) may not happen in real world. 134 mState.stack.push((TestEnv.FOLDER_0)); 135 136 mProfileTabs.updateView(); 137 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 138 assertThat(mTabLayout.getTabCount()).isEqualTo(2); 139 } 140 141 @Test testUpdateView_twoUsers_thirdParty_shouldHide()142 public void testUpdateView_twoUsers_thirdParty_shouldHide() { 143 initializeWithUsers(systemUser, managedUser); 144 145 mState.stack.changeRoot(TestProvidersAccess.PICKLES); 146 mState.stack.push((TestEnv.FOLDER_0)); 147 148 mProfileTabs.updateView(); 149 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 150 assertThat(mTabLayout.getTabCount()).isEqualTo(2); 151 } 152 153 @Test testUpdateView_twoUsers_isSearching_shouldHide()154 public void testUpdateView_twoUsers_isSearching_shouldHide() { 155 mTestEnv.isSearchExpanded = true; 156 initializeWithUsers(systemUser, managedUser); 157 158 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 159 assertThat(mTabLayout.getTabCount()).isEqualTo(2); 160 } 161 162 @Test testUpdateView_getSelectedUser_afterUsersChanged()163 public void testUpdateView_getSelectedUser_afterUsersChanged() { 164 initializeWithUsers(systemUser, managedUser); 165 mProfileTabs.updateView(); 166 mTabLayout.selectTab(mTabLayout.getTabAt(1)); 167 assertThat(mTabLayout.getVisibility()).isEqualTo(View.VISIBLE); 168 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(managedUser); 169 170 mTestUserIdManager.userIds = Collections.singletonList(systemUser); 171 mProfileTabs.updateView(); 172 assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE); 173 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 174 } 175 176 @Test testUpdateView_afterCurrentRootChanged_shouldChangeSelectedUser()177 public void testUpdateView_afterCurrentRootChanged_shouldChangeSelectedUser() { 178 initializeWithUsers(systemUser, managedUser); 179 mProfileTabs.updateView(); 180 181 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 182 183 RootInfo newRoot = RootInfo.copyRootInfo(mTestCommonAddons.mCurrentRoot); 184 newRoot.userId = managedUser; 185 mTestCommonAddons.mCurrentRoot = newRoot; 186 mProfileTabs.updateView(); 187 188 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(managedUser); 189 // updating view should not trigger listener callback. 190 assertThat(mIsListenerInvoked).isFalse(); 191 } 192 193 @Test testgetSelectedUser_twoUsers()194 public void testgetSelectedUser_twoUsers() { 195 initializeWithUsers(systemUser, managedUser); 196 197 mTabLayout.selectTab(mTabLayout.getTabAt(0)); 198 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 199 200 mTabLayout.selectTab(mTabLayout.getTabAt(1)); 201 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(managedUser); 202 assertThat(mIsListenerInvoked).isTrue(); 203 } 204 205 @Test testReselectedUser_doesNotInvokeListener()206 public void testReselectedUser_doesNotInvokeListener() { 207 initializeWithUsers(systemUser, managedUser); 208 209 assertThat(mTabLayout.getSelectedTabPosition()).isAtLeast(0); 210 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 211 212 mTabLayout.selectTab(mTabLayout.getTabAt(0)); 213 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 214 assertThat(mIsListenerInvoked).isFalse(); 215 } 216 217 @Test testgetSelectedUser_singleUsers()218 public void testgetSelectedUser_singleUsers() { 219 initializeWithUsers(systemUser); 220 221 assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser); 222 } 223 initializeWithUsers(UserId... userIds)224 private void initializeWithUsers(UserId... userIds) { 225 mTestUserIdManager.userIds = Lists.newArrayList(userIds); 226 for (UserId userId : userIds) { 227 if (userId.isSystem()) { 228 mTestUserIdManager.systemUser = userId; 229 } else { 230 mTestUserIdManager.managedUser = userId; 231 } 232 } 233 234 mProfileTabs = new ProfileTabs(mTabLayout, mState, mTestUserIdManager, mTestEnv, 235 mTestCommonAddons); 236 mProfileTabs.updateView(); 237 mProfileTabs.setListener(userId -> mIsListenerInvoked = true); 238 } 239 240 /** 241 * A test implementation of {@link NavigationViewManager.Environment}. 242 */ 243 private static class TestEnvironment implements NavigationViewManager.Environment { 244 245 public boolean isSearchExpanded = false; 246 247 @Override getCurrentRoot()248 public RootInfo getCurrentRoot() { 249 throw new UnsupportedOperationException("not implemented"); 250 } 251 252 @Override getDrawerTitle()253 public String getDrawerTitle() { 254 throw new UnsupportedOperationException("not implemented"); 255 } 256 257 @Override refreshCurrentRootAndDirectory(int animation)258 public void refreshCurrentRootAndDirectory(int animation) { 259 throw new UnsupportedOperationException("not implemented"); 260 } 261 262 @Override isSearchExpanded()263 public boolean isSearchExpanded() { 264 return isSearchExpanded; 265 } 266 } 267 268 private static class TestCommonAddons implements AbstractActionHandler.CommonAddons { 269 270 private RootInfo mCurrentRoot; 271 272 @Override restoreRootAndDirectory()273 public void restoreRootAndDirectory() { 274 throw new UnsupportedOperationException("not implemented"); 275 } 276 277 @Override refreshCurrentRootAndDirectory(int anim)278 public void refreshCurrentRootAndDirectory(int anim) { 279 throw new UnsupportedOperationException("not implemented"); 280 } 281 282 @Override onRootPicked(RootInfo root)283 public void onRootPicked(RootInfo root) { 284 throw new UnsupportedOperationException("not implemented"); 285 } 286 287 @Override onDocumentsPicked(List<DocumentInfo> docs)288 public void onDocumentsPicked(List<DocumentInfo> docs) { 289 throw new UnsupportedOperationException("not implemented"); 290 } 291 292 @Override onDocumentPicked(DocumentInfo doc)293 public void onDocumentPicked(DocumentInfo doc) { 294 throw new UnsupportedOperationException("not implemented"); 295 } 296 297 @Override getCurrentRoot()298 public RootInfo getCurrentRoot() { 299 return mCurrentRoot; 300 } 301 302 @Override getCurrentDirectory()303 public DocumentInfo getCurrentDirectory() { 304 throw new UnsupportedOperationException("not implemented"); 305 } 306 307 @Override getSelectedUser()308 public UserId getSelectedUser() { 309 throw new UnsupportedOperationException("not implemented"); 310 } 311 312 @Override isInRecents()313 public boolean isInRecents() { 314 throw new UnsupportedOperationException("not implemented"); 315 } 316 317 @Override setRootsDrawerOpen(boolean open)318 public void setRootsDrawerOpen(boolean open) { 319 throw new UnsupportedOperationException("not implemented"); 320 } 321 322 @Override setRootsDrawerLocked(boolean locked)323 public void setRootsDrawerLocked(boolean locked) { 324 throw new UnsupportedOperationException("not implemented"); 325 } 326 327 @Override updateNavigator()328 public void updateNavigator() { 329 throw new UnsupportedOperationException("not implemented"); 330 } 331 332 @Override notifyDirectoryNavigated(Uri docUri)333 public void notifyDirectoryNavigated(Uri docUri) { 334 throw new UnsupportedOperationException("not implemented"); 335 } 336 } 337 } 338 339