diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SsoUtilsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SsoUtilsTest.kt index d522cc4bc6d..184a351919e 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SsoUtilsTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SsoUtilsTest.kt @@ -2,13 +2,14 @@ package com.x8bit.bitwarden.data.auth.repository.util import android.content.Intent import android.net.Uri +import com.bitwarden.ui.platform.base.BaseRobolectricTest import io.mockk.every import io.mockk.mockk -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.Test +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test -class SsoUtilsTest { +class SsoUtilsTest : BaseRobolectricTest() { @Test fun `generateUriForSso should generate the correct URI`() { @@ -20,7 +21,7 @@ class SsoUtilsTest { val codeVerifier = "test_code_verifier" val expectedUrl = "https://identity.bitwarden.com/connect/authorize" + "?client_id=mobile" + - "&redirect_uri=bitwarden%3A%2F%2Fsso-callback" + + "&redirect_uri=https%3A%2F%2Fbitwarden.com%2Fsso-callback" + "&response_type=code" + "&scope=api%20offline_access" + "&state=test_state" + diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/WebAuthUtilsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/WebAuthUtilsTest.kt index df60d5ba846..0996cfc6260 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/WebAuthUtilsTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/WebAuthUtilsTest.kt @@ -2,14 +2,15 @@ package com.x8bit.bitwarden.data.auth.repository.util import android.content.Intent import android.net.Uri +import com.bitwarden.ui.platform.base.BaseRobolectricTest import com.bitwarden.ui.platform.manager.intent.model.AuthTabData import io.mockk.every import io.mockk.mockk import kotlinx.serialization.json.JsonObject -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test +import org.junit.Assert.assertEquals +import org.junit.Test -class WebAuthUtilsTest { +class WebAuthUtilsTest : BaseRobolectricTest() { @Test fun `generateUriForWebAuth should return valid Uri`() { diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/accessibility/parser/AccessibilityParserTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/accessibility/parser/AccessibilityParserTest.kt index 186a10e37e6..af44a23b599 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/accessibility/parser/AccessibilityParserTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/accessibility/parser/AccessibilityParserTest.kt @@ -3,17 +3,18 @@ package com.x8bit.bitwarden.data.autofill.accessibility.parser import android.net.Uri import android.view.accessibility.AccessibilityNodeInfo import androidx.core.net.toUri +import com.bitwarden.ui.platform.base.BaseRobolectricTest import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilityNodeInfoManager import com.x8bit.bitwarden.data.autofill.accessibility.model.Browser import com.x8bit.bitwarden.data.autofill.accessibility.model.FillableFields import io.mockk.every import io.mockk.mockk import io.mockk.verify -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.Test +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test -class AccessibilityParserTest { +class AccessibilityParserTest : BaseRobolectricTest() { private val accessibilityNodeInfoManager: AccessibilityNodeInfoManager = mockk() @@ -142,12 +143,13 @@ class AccessibilityParserTest { @Suppress("MaxLineLength") @Test fun `parseForUriOrPackageName should return null when package is a supported browser and URL bar is not found`() { - val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar") + val testPackageName = "com.android.chrome" + val testBrowser = Browser(packageName = testPackageName, urlFieldId = "url_bar") val rootNode = mockk { - every { packageName } returns testBrowser.packageName + every { packageName } returns testPackageName every { findAccessibilityNodeInfosByViewId( - "$packageName:id/${testBrowser.possibleUrlFieldIds.first()}", + "$testPackageName:id/${testBrowser.possibleUrlFieldIds.first()}", ) } returns emptyList() } @@ -160,16 +162,17 @@ class AccessibilityParserTest { @Suppress("MaxLineLength") @Test fun `parseForUriOrPackageName should return null when URL bar node has no text or content description`() { - val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar") + val testPackageName = "com.android.chrome" + val testBrowser = Browser(packageName = testPackageName, urlFieldId = "url_bar") val emptyNode = mockk { every { text } returns null every { contentDescription } returns null } val rootNode = mockk { - every { packageName } returns testBrowser.packageName + every { packageName } returns testPackageName every { findAccessibilityNodeInfosByViewId( - "${testBrowser.packageName}:id/${testBrowser.possibleUrlFieldIds.first()}", + "$testPackageName:id/${testBrowser.possibleUrlFieldIds.first()}", ) } returns listOf(emptyNode) } @@ -246,7 +249,7 @@ class AccessibilityParserTest { predicate = any(), ) } returns listOf(urlNode) - val expectedResult = "https://www.reddit.com".toUri() + val expectedResult = Uri.parse("https://www.reddit.com") val result = accessibilityParser.parseForUriOrPackageName(rootNode = rootNode) @@ -256,16 +259,17 @@ class AccessibilityParserTest { @Suppress("MaxLineLength") @Test fun `parseForUriOrPackageName should return the site url un-augmented with https protocol as a URI when package is a supported browser and URL is found`() { - val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar") + val testPackageName = "com.android.chrome" + val testBrowser = Browser(packageName = testPackageName, urlFieldId = "url_bar") val url = "https://www.google.com" val urlNode = mockk { every { text } returns url } val rootNode = mockk { - every { packageName } returns testBrowser.packageName + every { packageName } returns testPackageName every { findAccessibilityNodeInfosByViewId( - "$packageName:id/${testBrowser.possibleUrlFieldIds.first()}", + "$testPackageName:id/${testBrowser.possibleUrlFieldIds.first()}", ) } returns listOf(urlNode) } @@ -279,16 +283,17 @@ class AccessibilityParserTest { @Suppress("MaxLineLength") @Test fun `parseForUriOrPackageName should return the site url un-augmented with http protocol as a URI when package is a supported browser and URL is found`() { - val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar") + val testPackageName = "com.android.chrome" + val testBrowser = Browser(packageName = testPackageName, urlFieldId = "url_bar") val url = "http://www.google.com" val urlNode = mockk { every { text } returns url } val rootNode = mockk { - every { packageName } returns testBrowser.packageName + every { packageName } returns testPackageName every { findAccessibilityNodeInfosByViewId( - "$packageName:id/${testBrowser.possibleUrlFieldIds.first()}", + "$testPackageName:id/${testBrowser.possibleUrlFieldIds.first()}", ) } returns listOf(urlNode) } @@ -302,16 +307,17 @@ class AccessibilityParserTest { @Suppress("MaxLineLength") @Test fun `parseForUriOrPackageName should return the site url augmented with https protocol as a URI when package is a supported browser and URL is found`() { - val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar") + val testPackageName = "com.android.chrome" + val testBrowser = Browser(packageName = testPackageName, urlFieldId = "url_bar") val url = "www.google.com" val urlNode = mockk { every { text } returns url } val rootNode = mockk { - every { packageName } returns testBrowser.packageName + every { packageName } returns testPackageName every { findAccessibilityNodeInfosByViewId( - "$packageName:id/${testBrowser.possibleUrlFieldIds.first()}", + "$testPackageName:id/${testBrowser.possibleUrlFieldIds.first()}", ) } returns listOf(urlNode) } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/network/ssl/CertificateManagerTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/network/ssl/CertificateManagerTest.kt index 582d80ce8c0..fc5286a1178 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/network/ssl/CertificateManagerTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/network/ssl/CertificateManagerTest.kt @@ -55,6 +55,7 @@ class CertificateManagerTest { environmentRepository = mockEnvironmentRepository, context = mockContext, ) + @BeforeEach fun setUp() { mockkStatic(KeyStore::class, KeyChain::class) @@ -130,6 +131,9 @@ class CertificateManagerTest { @Test fun `mutualTlsCertificate should return null when keyUri is invalid`() { + every { + mockEnvironment.environmentUrlData + } returns DEFAULT_ENV_URL_DATA.copy(keyUri = null) assertNull(certificateManager.mutualTlsCertificate) } @@ -667,6 +671,7 @@ class CertificateManagerTest { @Test fun `getCertificateChain should return null when mutualTlsCertificate is null`() { + setupMockUri(authority = "") assertNull(certificateManager.getCertificateChain("mockAlias")) } @@ -684,6 +689,7 @@ class CertificateManagerTest { @Test fun `getPrivateKey should return null when mutualTlsCertificate is null`() { + setupMockUri(authority = "") assertNull(certificateManager.getPrivateKey("mockAlias")) } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/flightrecorder/recordedlogs/RecordedLogsViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/flightrecorder/recordedlogs/RecordedLogsViewModelTest.kt index f99a949f82d..70838c33ec5 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/flightrecorder/recordedlogs/RecordedLogsViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/flightrecorder/recordedlogs/RecordedLogsViewModelTest.kt @@ -56,6 +56,7 @@ class RecordedLogsViewModelTest : BaseViewModelTest() { File::toURI, Uri::parse, ) + every { Uri.parse(any()) } returns mockk() } @AfterEach diff --git a/authenticator/src/test/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryTest.kt b/authenticator/src/test/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryTest.kt index 273494458d2..e1bb57de204 100644 --- a/authenticator/src/test/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryTest.kt +++ b/authenticator/src/test/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryTest.kt @@ -1,6 +1,7 @@ package com.bitwarden.authenticator.data.authenticator.repository import android.net.Uri +import android.text.TextUtils import app.cash.turbine.test import com.bitwarden.authenticator.data.authenticator.datasource.disk.util.FakeAuthenticatorDiskSource import com.bitwarden.authenticator.data.authenticator.datasource.entity.createMockAuthenticatorItemEntity @@ -24,6 +25,8 @@ import com.bitwarden.authenticatorbridge.manager.model.AccountSyncState import com.bitwarden.authenticatorbridge.model.SharedAccountData import com.bitwarden.core.data.manager.dispatcher.FakeDispatcherManager import com.bitwarden.core.data.repository.model.DataState +import com.bitwarden.core.data.util.asFailure +import com.bitwarden.core.data.util.asSuccess import com.bitwarden.core.data.util.mockBuilder import com.bitwarden.data.manager.file.FileManager import com.bitwarden.ui.platform.model.FileData @@ -86,6 +89,8 @@ class AuthenticatorRepositoryTest { mockBuilder { it.appendPath(any()) } mockBuilder { it.appendQueryParameter(any(), any()) } every { anyConstructed().build() } returns mockBuiltUri + mockkStatic(TextUtils::htmlEncode) + every { TextUtils.htmlEncode(any()) } returns "" } @AfterEach @@ -93,6 +98,7 @@ class AuthenticatorRepositoryTest { unmockkStatic(Uri::class) unmockkStatic(List::toAuthenticatorItems) unmockkConstructor(Uri.Builder::class) + unmockkStatic(TextUtils::htmlEncode) } @Test @@ -396,7 +402,7 @@ class AuthenticatorRepositoryTest { coEvery { mockFileManager.uriToByteArray(mockUri) - } returns Result.success(testByteArray) + } returns testByteArray.asSuccess() coEvery { mockImportManager.import( @@ -424,7 +430,7 @@ class AuthenticatorRepositoryTest { coEvery { mockFileManager.uriToByteArray(mockUri) - } returns Result.failure(RuntimeException("File read error")) + } returns RuntimeException("File read error").asFailure() val result = authenticatorRepository.importVaultData( format = ImportFileFormat.BITWARDEN_JSON, @@ -446,7 +452,7 @@ class AuthenticatorRepositoryTest { coEvery { mockFileManager.uriToByteArray(mockUri) - } returns Result.success(testByteArray) + } returns testByteArray.asSuccess() coEvery { mockImportManager.import( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8ba832a78f1..1ab5de2fc32 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ androidxBiometrics = "1.2.0-alpha05" androidxBrowser = "1.10.0" androidxCamera = "1.6.1" androidxComposeBom = "2026.06.00" -androidxCore = "1.18.0" +androidxCore = "1.19.0" androidxCredentials = "1.6.0" androidxCredentialsProviderEvents = "1.0.0-alpha06" androidxHiltNavigationCompose = "1.3.0"