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