Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ androidx-test-uiautomator = "2.3.0"
androidx-test-orchestrator = "1.6.1"
androidx-arch-core-testing = "2.2.0"
mockk-android = "1.14.9"
kotlin-reflect = "2.3.20"

[libraries]
# Kotlin / serialization
Expand Down Expand Up @@ -125,3 +126,4 @@ androidx-test-uiautomator = { module = "androidx.test.uiautomator:uiautomator",
androidx-test-orchestrator = { module = "androidx.test:orchestrator", version.ref = "androidx-test-orchestrator" }
androidx-arch-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "androidx-arch-core-testing" }
mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk-android" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin-reflect" }
1 change: 1 addition & 0 deletions libs/SalesforceSDK/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dependencies {
androidTestImplementation(libs.androidx.arch.core.testing)
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
androidTestImplementation(libs.mockk.android)
androidTestImplementation(libs.kotlin.reflect)
}

android { // TODO: This cannot be resolved until newDSL=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.salesforce.androidsdk.app

import android.app.Activity
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.salesforce.androidsdk.auth.HttpAccess
Expand Down Expand Up @@ -34,6 +35,7 @@ import org.junit.runner.RunWith
/**
* Tests for `SalesforceSDKManager`.
*/
@SdkSuppress(minSdkVersion = 31)
@RunWith(AndroidJUnit4::class)
@SmallTest
class SalesforceSDKManagerTests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package com.salesforce.androidsdk.auth
import android.webkit.CookieManager
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.salesforce.androidsdk.accounts.UserAccount
import com.salesforce.androidsdk.accounts.UserAccountBuilder
Expand Down Expand Up @@ -65,6 +66,7 @@ import org.junit.runner.RunWith
* Tests for LoginViewModel that require mocking.
* These tests are separated from LoginViewModelTest to isolate mock usage.
*/
@SdkSuppress(minSdkVersion = 31)
@RunWith(AndroidJUnit4::class)
class LoginViewModelMockTest {
@get:Rule
Expand Down Expand Up @@ -379,7 +381,7 @@ class LoginViewModelMockTest {
spyViewModel.onWebServerFlowComplete(testCode, mockOnError, mockOnSuccess)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

// Verify doCodeExchange was called with correct parameters
coVerify {
Expand Down Expand Up @@ -423,7 +425,7 @@ class LoginViewModelMockTest {
)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

// Verify doCodeExchange was called with correct parameters
coVerify {
Expand Down Expand Up @@ -462,7 +464,7 @@ class LoginViewModelMockTest {
spyViewModel.onWebServerFlowComplete(testCode, mockOnError, mockOnSuccess)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

// Verify doCodeExchange was called with null loginServer and false tokenMigration
coVerify {
Expand Down Expand Up @@ -498,7 +500,7 @@ class LoginViewModelMockTest {
spyViewModel.onWebServerFlowComplete(null, mockOnError, mockOnSuccess)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

// Verify doCodeExchange was called with null code, null loginServer, and false tokenMigration
coVerify {
Expand Down Expand Up @@ -609,7 +611,7 @@ class LoginViewModelMockTest {
)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

// Verify doCodeExchange was called with the correct loginServer and tokenMigration
coVerify {
Expand Down Expand Up @@ -657,7 +659,7 @@ class LoginViewModelMockTest {
)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

coVerify {
spyViewModel.onAuthFlowComplete(
Expand Down Expand Up @@ -707,7 +709,7 @@ class LoginViewModelMockTest {
)

// Give time for the coroutine to execute
Thread.sleep(200)
Thread.sleep(2000)

coVerify {
spyViewModel.onAuthFlowComplete(
Expand Down Expand Up @@ -770,7 +772,7 @@ class LoginViewModelMockTest {
loginServer = migrationServer,
tokenMigration = true,
)
Thread.sleep(200)
Thread.sleep(2000)

// Token exchange must be performed with MIGRATION credentials.
verify {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class LoginViewModelTest {
viewModel.selectedServer.value = FAKE_SERVER_URL

// Wait for loginUrl to update after selectedServer change (async coroutine)
Thread.sleep(200)
Thread.sleep(2000)
assertNotNull(viewModel.loginUrl.value)
// LoginUrlSource prepends https:// to scheme-less servers before URL generation.
assertTrue(viewModel.loginUrl.value!!.startsWith("https://$FAKE_SERVER_URL"))
Expand All @@ -171,7 +171,7 @@ class LoginViewModelTest {
viewModel.browserCustomTabUrl.observeForever { }

// The setup() already triggers URL generation; wait for async completion.
Thread.sleep(200)
Thread.sleep(2000)

val browserCustomTabUrl = viewModel.browserCustomTabUrl.value
assertNotNull("browserCustomTabUrl should be populated for the admin flow", browserCustomTabUrl)
Expand All @@ -195,7 +195,7 @@ class LoginViewModelTest {
SalesforceSDKManager.getInstance().useWebServerAuthentication = false

viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

val browserCustomTabUrl = viewModel.browserCustomTabUrl.value
val loginUrl = viewModel.loginUrl.value
Expand Down Expand Up @@ -233,7 +233,7 @@ class LoginViewModelTest {
viewModel.browserCustomTabUrl.observeForever { }

// Wait for initial generation.
Thread.sleep(200)
Thread.sleep(2000)
val initialUrl = viewModel.browserCustomTabUrl.value
assertNotNull(initialUrl)
assertFalse(
Expand All @@ -242,7 +242,7 @@ class LoginViewModelTest {
)

viewModel.selectedServer.value = FAKE_SERVER_URL
Thread.sleep(200)
Thread.sleep(2000)

val updatedUrl = viewModel.browserCustomTabUrl.value
assertNotNull(updatedUrl)
Expand Down Expand Up @@ -366,7 +366,7 @@ class LoginViewModelTest {

viewModel.selectedServer.value = FAKE_SERVER_URL
// Wait for async update
Thread.sleep(200)
Thread.sleep(2000)
val newCodeChallenge = getSHA256Hash(viewModel.codeVerifier)
assertNotEquals(originalCodeChallenge, newCodeChallenge)
// LoginUrlSource prepends https:// to scheme-less servers before URL generation.
Expand All @@ -381,7 +381,7 @@ class LoginViewModelTest {

viewModel.reloadWebView()
// Wait for async update
Thread.sleep(200)
Thread.sleep(2000)
val newCodeChallenge = getSHA256Hash(viewModel.codeVerifier)
assertNotNull(newCodeChallenge)
assertNotEquals(originalCodeChallenge, newCodeChallenge)
Expand All @@ -399,7 +399,7 @@ class LoginViewModelTest {
viewModel.authCodeForJwtFlow = FAKE_JWT_FLOW_AUTH
viewModel.reloadWebView()
// Wait for async update
Thread.sleep(200)
Thread.sleep(2000)
assertNotEquals(expectedUrl, viewModel.loginUrl.value)

codeChallenge = getSHA256Hash(viewModel.codeVerifier)
Expand Down Expand Up @@ -450,7 +450,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL contains the custom consumer key and redirect URI
val loginUrl = viewModel.loginUrl.value!!
Expand All @@ -466,7 +466,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL contains the boot config values
val loginUrl = viewModel.loginUrl.value!!
Expand Down Expand Up @@ -499,7 +499,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL contains the custom app config values
val loginUrl = viewModel.loginUrl.value!!
Expand Down Expand Up @@ -540,7 +540,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL contains the debug override values, not app config values
val loginUrl = viewModel.loginUrl.value!!
Expand Down Expand Up @@ -701,7 +701,7 @@ class LoginViewModelTest {

// Test with test server
viewModel.selectedServer.value = "https://test.salesforce.com"
Thread.sleep(200)
Thread.sleep(2000)
var loginUrl = viewModel.loginUrl.value!!
assertTrue("URL should contain test consumer key. URL: $loginUrl",
loginUrl.contains("test_consumer_key"))
Expand All @@ -712,7 +712,7 @@ class LoginViewModelTest {

// Test with production server
viewModel.selectedServer.value = "https://login.salesforce.com"
Thread.sleep(200)
Thread.sleep(2000)
loginUrl = viewModel.loginUrl.value!!
assertTrue("URL should contain prod consumer key. URL: $loginUrl",
loginUrl.contains("prod_consumer_key"))
Expand All @@ -738,7 +738,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL is generated correctly without scopes
val loginUrl = viewModel.loginUrl.value!!
Expand All @@ -762,7 +762,7 @@ class LoginViewModelTest {

// Call reloadWebView
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify URL did not change
assertEquals("frontDoorBridgeUrl should still be front door URL", frontDoorUrl, viewModel.frontDoorBridgeUrl.value)
Expand Down Expand Up @@ -791,7 +791,7 @@ class LoginViewModelTest {
ABOUT_BLANK, viewModel.loginUrl.value)

// Wait for the new authorization URL to be generated
Thread.sleep(200)
Thread.sleep(2000)

// Verify a new URL was generated
val newUrl = viewModel.loginUrl.value
Expand Down Expand Up @@ -824,7 +824,7 @@ class LoginViewModelTest {
ABOUT_BLANK, viewModel.loginUrl.value)

// Wait for the new authorization URL to be generated
Thread.sleep(200)
Thread.sleep(2000)

// Verify a new URL was generated with different code challenge
val newUrl = viewModel.loginUrl.value
Expand All @@ -845,7 +845,7 @@ class LoginViewModelTest {

// Call reloadWebView
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify URL did not change
assertEquals("loginUrl should not change when selectedServer is null",
Expand All @@ -866,7 +866,7 @@ class LoginViewModelTest {

// Trigger URL generation
viewModel.reloadWebView()
Thread.sleep(200)
Thread.sleep(2000)

// Verify the URL contains the boot config values (fallback)
val loginUrl = viewModel.loginUrl.value!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextClearance
import androidx.compose.ui.test.performTextInput
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.rule.GrantPermissionRule
import com.salesforce.androidsdk.R.string.sf__account_selector_text
Expand Down Expand Up @@ -94,6 +95,7 @@ private val userList = listOf(user1, user2)
@VisibleForTesting
internal val customsRowCd = (hasText(customServer.name) and hasText(customServer.url))

@SdkSuppress(minSdkVersion = 31)
class PickerBottomSheetTest {

@get:Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.salesforce.androidsdk.accounts.MigrationCallbackRegistry
import com.salesforce.androidsdk.app.SalesforceSDKManager
Expand All @@ -38,6 +39,7 @@ import org.junit.runner.RunWith
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@SdkSuppress(minSdkVersion = 31)
@RunWith(AndroidJUnit4::class)
class TokenMigrationWebViewTest {

Expand Down
Loading