Skip to content

Commit 62df659

Browse files
@W-20784385: [MSDK Android] Only Show Authorized Hosts Device Management Parameter In-Operative (#2816)
1 parent 52463f5 commit 62df659

4 files changed

Lines changed: 127 additions & 15 deletions

File tree

libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/LoginViewModel.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ import com.salesforce.androidsdk.auth.defaultBuildAccountName
6060
import com.salesforce.androidsdk.auth.onAuthFlowComplete
6161
import com.salesforce.androidsdk.config.BootConfig
6262
import com.salesforce.androidsdk.config.OAuthConfig
63+
import com.salesforce.androidsdk.config.RuntimeConfig.ConfigKey.OnlyShowAuthorizedHosts
64+
import com.salesforce.androidsdk.config.RuntimeConfig.getRuntimeConfig
6365
import com.salesforce.androidsdk.security.SalesforceKeyGenerator.getRandom128ByteKey
6466
import com.salesforce.androidsdk.security.SalesforceKeyGenerator.getSHA256Hash
6567
import com.salesforce.androidsdk.ui.LoginActivity.Companion.ABOUT_BLANK
@@ -135,6 +137,8 @@ open class LoginViewModel(val bootConfig: BootConfig) : ViewModel() {
135137
internal val defaultTitleText: String
136138
get() = if (loginUrl.value == ABOUT_BLANK) "" else selectedServer.value ?: ""
137139

140+
internal val serverPickerAddConnectionButtonVisible = !getRuntimeConfig(SalesforceSDKManager.getInstance().appContext).getBoolean(OnlyShowAuthorizedHosts)
141+
138142
/** Additional Auth Values used for login. */
139143
open var additionalParameters = hashMapOf<String, String>()
140144

libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/components/PickerBottomSheet.kt

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ import com.salesforce.androidsdk.R.string.sf__server_url_default_custom_label
123123
import com.salesforce.androidsdk.R.string.sf__server_url_default_custom_url
124124
import com.salesforce.androidsdk.R.string.sf__server_url_save
125125
import com.salesforce.androidsdk.accounts.UserAccount
126+
import com.salesforce.androidsdk.accounts.UserAccountManager
126127
import com.salesforce.androidsdk.app.SalesforceSDKManager
128+
import com.salesforce.androidsdk.config.LoginServerManager
127129
import com.salesforce.androidsdk.config.LoginServerManager.LoginServer
128130
import com.salesforce.androidsdk.ui.LoginViewModel
129131
import com.salesforce.androidsdk.ui.theme.hintTextColor
@@ -145,10 +147,21 @@ internal const val TEXT_SELECTION_ALPHA = 0.2f
145147
@OptIn(ExperimentalMaterial3Api::class)
146148
@Composable
147149
fun PickerBottomSheet(pickerStyle: PickerStyle) {
148-
val viewModel: LoginViewModel = viewModel(factory = SalesforceSDKManager.getInstance().loginViewModelFactory)
149-
val loginServerManager = SalesforceSDKManager.getInstance().loginServerManager
150-
val userAccountManager = SalesforceSDKManager.getInstance().userAccountManager
151-
val activity = LocalContext.current.getActivity()
150+
TestablePickerBottomSheet(
151+
pickerStyle = pickerStyle,
152+
)
153+
}
154+
155+
@OptIn(ExperimentalMaterial3Api::class)
156+
@Composable
157+
@VisibleForTesting
158+
internal fun TestablePickerBottomSheet(
159+
pickerStyle: PickerStyle,
160+
viewModel: LoginViewModel = viewModel(factory = SalesforceSDKManager.getInstance().loginViewModelFactory),
161+
loginServerManager: LoginServerManager = SalesforceSDKManager.getInstance().loginServerManager,
162+
userAccountManager: UserAccountManager = SalesforceSDKManager.getInstance().userAccountManager,
163+
activity: FragmentActivity? = LocalContext.current.getActivity(),
164+
) {
152165
val onNewLoginServerSelected = { newSelectedServer: Any?, closePicker: Boolean ->
153166
if (newSelectedServer != null && newSelectedServer is LoginServer) {
154167
viewModel.showServerPicker.value = !closePicker
@@ -193,8 +206,9 @@ fun PickerBottomSheet(pickerStyle: PickerStyle) {
193206
when (pickerStyle) {
194207
PickerStyle.LoginServerPicker ->
195208
PickerBottomSheet(
196-
pickerStyle,
197-
sheetState,
209+
addButtonVisible = viewModel.serverPickerAddConnectionButtonVisible,
210+
pickerStyle = pickerStyle,
211+
sheetState = sheetState,
198212
list = loginServerManager.loginServers,
199213
selectedListItem = loginServerManager.selectedLoginServer,
200214
onItemSelected = onNewLoginServerSelected,
@@ -205,8 +219,8 @@ fun PickerBottomSheet(pickerStyle: PickerStyle) {
205219

206220
PickerStyle.UserAccountPicker ->
207221
PickerBottomSheet(
208-
pickerStyle,
209-
sheetState,
222+
pickerStyle = pickerStyle,
223+
sheetState = sheetState,
210224
list = userAccountManager.authenticatedUsers,
211225
selectedListItem = userAccountManager.currentUser,
212226
onItemSelected = onUserAccountSelected,
@@ -227,6 +241,7 @@ internal fun PickerBottomSheet(
227241
sheetState: SheetState,
228242
list: List<Any>,
229243
selectedListItem: Any?,
244+
addButtonVisible: Boolean = true,
230245
onItemSelected: (Any?, Boolean) -> Unit,
231246
getValidServer: ((String) -> String?)? = null,
232247
addNewLoginServer: ((String, String) -> Unit)? = null,
@@ -427,7 +442,7 @@ internal fun PickerBottomSheet(
427442
)
428443

429444
// Add New Connection/Account Button
430-
if (listItem == mutableList.last()) {
445+
if (listItem == mutableList.last() && addButtonVisible) {
431446
OutlinedButton(
432447
onClick = {
433448
when (pickerStyle) {

libs/test/SalesforceSDKTest/src/com/salesforce/androidsdk/rest/ClientManagerMockTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.salesforce.androidsdk.rest
22

33
import android.accounts.Account
44
import android.content.Context
5+
import android.content.Context.MODE_PRIVATE
56
import android.content.Intent
67
import androidx.test.filters.SmallTest
78
import androidx.test.platform.app.InstrumentationRegistry
@@ -53,6 +54,10 @@ class ClientManagerMockTest {
5354
every { packageName } returns "packageName"
5455
every { sendBroadcast(any()) } just runs
5556
every { externalCacheDir } returns null
57+
every { filesDir } returns targetContext.filesDir
58+
every { getSharedPreferences(any(), any()) } answers {
59+
targetContext.getSharedPreferences(firstArg(), MODE_PRIVATE)
60+
}
5661
}
5762

5863
mockkObject(SalesforceSDKManager)

libs/test/SalesforceSDKTest/src/com/salesforce/androidsdk/ui/PickerBottomSheetTest.kt

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,19 @@ import androidx.compose.ui.test.onNodeWithText
4949
import androidx.compose.ui.test.performClick
5050
import androidx.compose.ui.test.performTextClearance
5151
import androidx.compose.ui.test.performTextInput
52+
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
5253
import androidx.test.rule.GrantPermissionRule
54+
import com.salesforce.androidsdk.R.string.sf__account_selector_text
55+
import com.salesforce.androidsdk.R.string.sf__custom_url_button
56+
import com.salesforce.androidsdk.R.string.sf__pick_server
57+
import com.salesforce.androidsdk.accounts.UserAccountManager
5358
import com.salesforce.androidsdk.config.LoginServerManager.LoginServer
5459
import com.salesforce.androidsdk.ui.components.AddConnection
5560
import com.salesforce.androidsdk.ui.components.PickerBottomSheet
5661
import com.salesforce.androidsdk.ui.components.PickerStyle
62+
import com.salesforce.androidsdk.ui.components.TestablePickerBottomSheet
5763
import com.salesforce.androidsdk.ui.components.UserAccountMock
64+
import io.mockk.mockk
5865
import org.junit.Assert
5966
import org.junit.Rule
6067
import org.junit.Test
@@ -108,6 +115,44 @@ class PickerBottomSheetTest {
108115

109116
// Google's recommended naming scheme for test is "thingUnderTest_TriggerOfTest_ResultOfTest"
110117

118+
// region Public API Tests
119+
120+
@OptIn(ExperimentalMaterial3Api::class)
121+
@Test
122+
fun pickerBottomSheet_publicApiUserAccountPicker_displaysUserAccountPicker() {
123+
val userAccountManager = mockk<UserAccountManager>(relaxed = true)
124+
composeTestRule.setContent {
125+
TestablePickerBottomSheet(
126+
pickerStyle = PickerStyle.UserAccountPicker,
127+
userAccountManager = userAccountManager
128+
)
129+
}
130+
131+
val context = getInstrumentation().targetContext
132+
val button = composeTestRule.onNode(hasText(context.getString(sf__account_selector_text)))
133+
134+
button.assertIsDisplayed()
135+
}
136+
137+
@OptIn(ExperimentalMaterial3Api::class)
138+
@Test
139+
fun pickerBottomSheet_publicApiLoginServerPicker_displaysLoginServerPicker() {
140+
val userAccountManager = mockk<UserAccountManager>(relaxed = true)
141+
composeTestRule.setContent {
142+
TestablePickerBottomSheet(
143+
pickerStyle = PickerStyle.LoginServerPicker,
144+
userAccountManager = userAccountManager
145+
)
146+
}
147+
148+
val context = getInstrumentation().targetContext
149+
val button = composeTestRule.onNode(hasText(context.getString(sf__pick_server)))
150+
151+
button.assertIsDisplayed()
152+
}
153+
154+
// endregion
155+
111156
// region Add Connection Tests
112157
@Test
113158
fun saveButton_RespondsTo_InputValidation() {
@@ -249,6 +294,38 @@ class PickerBottomSheetTest {
249294
customListItem.onChildAt(0).assertIsSelected()
250295
}
251296

297+
@OptIn(ExperimentalMaterial3Api::class)
298+
@Test
299+
fun serverList_AddButtonVisibleTrue_DisplaysAddNewConnectionButton() {
300+
composeTestRule.setContent {
301+
PickerBottomSheetTestWrapper(
302+
pickerStyle = PickerStyle.LoginServerPicker,
303+
addButtonVisible = true,
304+
)
305+
}
306+
307+
val context = getInstrumentation().targetContext
308+
val button = composeTestRule.onNode(hasText(context.getString(sf__custom_url_button)))
309+
310+
button.assertIsDisplayed()
311+
}
312+
313+
@OptIn(ExperimentalMaterial3Api::class)
314+
@Test
315+
fun serverList_AddButtonVisibleFalse_HidesAddNewConnectionButton() {
316+
composeTestRule.setContent {
317+
PickerBottomSheetTestWrapper(
318+
pickerStyle = PickerStyle.LoginServerPicker,
319+
addButtonVisible = false,
320+
)
321+
}
322+
323+
val context = getInstrumentation().targetContext
324+
val button = composeTestRule.onNode(hasText(context.getString(sf__custom_url_button)))
325+
326+
button.assertDoesNotExist()
327+
}
328+
252329
@OptIn(ExperimentalMaterial3Api::class)
253330
@Test
254331
fun selectedServer_UpdatesOn_UIServerSelection() {
@@ -380,17 +457,28 @@ internal fun PickerBottomSheetTestWrapper(
380457
initialValue = SheetValue.Expanded,
381458
skipHiddenState = false,
382459
),
383-
list: List<Any> = when(pickerStyle) {
460+
list: List<Any> = when (pickerStyle) {
384461
PickerStyle.LoginServerPicker -> serverList
385462
PickerStyle.UserAccountPicker -> userList
386463
},
387464
selectedListItem: Any = list.first(),
388-
onItemSelected: (Any?, Boolean) -> Unit = { _,_ -> },
465+
addButtonVisible: Boolean = true,
466+
onItemSelected: (Any?, Boolean) -> Unit = { _, _ -> },
389467
getValidServer: ((String) -> String?)? = { _ -> "" },
390-
addNewLoginServer: ((String, String) -> Unit)? = { _,_ -> },
468+
addNewLoginServer: ((String, String) -> Unit)? = { _, _ -> },
391469
removeLoginServer: ((LoginServer) -> Unit)? = { },
392470
addNewAccount: (() -> Unit)? = { },
393471
) {
394-
PickerBottomSheet(pickerStyle, sheetState, list, selectedListItem, onItemSelected, getValidServer,
395-
addNewLoginServer, removeLoginServer, addNewAccount)
396-
}
472+
PickerBottomSheet(
473+
pickerStyle = pickerStyle,
474+
sheetState = sheetState,
475+
list = list,
476+
selectedListItem = selectedListItem,
477+
addButtonVisible = addButtonVisible,
478+
onItemSelected = onItemSelected,
479+
getValidServer = getValidServer,
480+
addNewLoginServer = addNewLoginServer,
481+
removeLoginServer = removeLoginServer,
482+
addNewAccount = addNewAccount,
483+
)
484+
}

0 commit comments

Comments
 (0)