1 /*
2  * Copyright (C) 2024 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.development.domain.interactor
18 
19 import android.content.ClipData
20 import android.content.ClipDescription
21 import android.content.clipboardManager
22 import android.content.pm.UserInfo
23 import android.content.res.mainResources
24 import android.os.Build
25 import android.provider.Settings
26 import androidx.test.ext.junit.runners.AndroidJUnit4
27 import androidx.test.filters.SmallTest
28 import com.android.internal.R
29 import com.android.systemui.SysuiTestCase
30 import com.android.systemui.development.shared.model.BuildNumber
31 import com.android.systemui.kosmos.Kosmos
32 import com.android.systemui.kosmos.collectLastValue
33 import com.android.systemui.kosmos.runCurrent
34 import com.android.systemui.kosmos.testScope
35 import com.android.systemui.testKosmos
36 import com.android.systemui.user.data.repository.fakeUserRepository
37 import com.android.systemui.util.settings.fakeGlobalSettings
38 import com.google.common.truth.Truth.assertThat
39 import kotlinx.coroutines.test.runTest
40 import org.junit.Test
41 import org.junit.runner.RunWith
42 import org.mockito.kotlin.argumentCaptor
43 import org.mockito.kotlin.verify
44 
45 @RunWith(AndroidJUnit4::class)
46 @SmallTest
47 class BuildNumberInteractorTest : SysuiTestCase() {
48 
49     private val kosmos =
<lambda>null50         testKosmos().apply {
51             fakeUserRepository.setUserInfos(listOf(adminUserInfo, nonAdminUserInfo))
52         }
53 
54     private val expectedBuildNumber =
55         BuildNumber(
56             kosmos.mainResources.getString(
57                 R.string.bugreport_status,
58                 Build.VERSION.RELEASE_OR_CODENAME,
59                 Build.ID,
60             )
61         )
62 
63     private val clipLabel =
64         kosmos.mainResources.getString(
65             com.android.systemui.res.R.string.build_number_clip_data_label
66         )
67 
68     private val underTest = kosmos.buildNumberInteractor
69 
70     @Test
nonAdminUser_settingEnabled_buildNumberNullnull71     fun nonAdminUser_settingEnabled_buildNumberNull() =
72         with(kosmos) {
73             testScope.runTest {
74                 val buildNumber by collectLastValue(underTest.buildNumber)
75 
76                 fakeUserRepository.setSelectedUserInfo(nonAdminUserInfo)
77                 setSettingValue(true)
78 
79                 assertThat(buildNumber).isNull()
80             }
81         }
82 
83     @Test
adminUser_buildNumberCorrect_onlyWhenSettingEnablednull84     fun adminUser_buildNumberCorrect_onlyWhenSettingEnabled() =
85         with(kosmos) {
86             testScope.runTest {
87                 val buildNumber by collectLastValue(underTest.buildNumber)
88 
89                 fakeUserRepository.setSelectedUserInfo(adminUserInfo)
90 
91                 setSettingValue(false)
92                 assertThat(buildNumber).isNull()
93 
94                 setSettingValue(true)
95                 assertThat(buildNumber).isEqualTo(expectedBuildNumber)
96             }
97         }
98 
99     @Test
copyToClipboardnull100     fun copyToClipboard() =
101         with(kosmos) {
102             testScope.runTest {
103                 fakeUserRepository.setSelectedUserInfo(adminUserInfo)
104 
105                 underTest.copyBuildNumber()
106                 runCurrent()
107 
108                 val argumentCaptor = argumentCaptor<ClipData>()
109 
110                 verify(clipboardManager).setPrimaryClip(argumentCaptor.capture())
111 
112                 with(argumentCaptor.firstValue) {
113                     assertThat(description.label).isEqualTo(clipLabel)
114                     assertThat(description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN))
115                         .isTrue()
116                     assertThat(itemCount).isEqualTo(1)
117                     assertThat(getItemAt(0).text).isEqualTo(expectedBuildNumber.value)
118                 }
119             }
120         }
121 
122     private companion object {
123         const val SETTING_NAME = Settings.Global.DEVELOPMENT_SETTINGS_ENABLED
124 
125         val adminUserInfo =
126             UserInfo(
127                 /* id= */ 10,
128                 /* name= */ "",
129                 /* flags */ UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
130             )
131         val nonAdminUserInfo =
132             UserInfo(/* id= */ 11, /* name= */ "", /* flags */ UserInfo.FLAG_FULL)
133 
setSettingValuenull134         fun Kosmos.setSettingValue(enabled: Boolean) {
135             fakeGlobalSettings.putInt(SETTING_NAME, if (enabled) 1 else 0)
136         }
137     }
138 }
139