diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/GetTokenResponseJson.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/GetTokenResponseJson.kt
index 537483d1384..e8d688835dd 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/GetTokenResponseJson.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/GetTokenResponseJson.kt
@@ -1,7 +1,9 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model
+import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonNames
import kotlinx.serialization.json.JsonObject
/**
@@ -92,20 +94,21 @@ sealed class GetTokenResponseJson {
/**
* Models json body of an invalid request.
+ *
+ * This model supports older versions of the error response model that used lower-case keys.
*/
+ @OptIn(ExperimentalSerializationApi::class)
@Serializable
data class Invalid(
+ @JsonNames("errorModel")
@SerialName("ErrorModel")
- val errorModel: ErrorModel?,
- @SerialName("errorModel")
- val legacyErrorModel: LegacyErrorModel?,
+ private val errorModel: ErrorModel?,
) : GetTokenResponseJson() {
/**
* The error message returned from the server, or null.
*/
- val errorMessage: String?
- get() = errorModel?.errorMessage ?: legacyErrorModel?.errorMessage
+ val errorMessage: String? get() = errorModel?.errorMessage
/**
* The type of invalid responses that can be received.
@@ -131,24 +134,16 @@ sealed class GetTokenResponseJson {
/**
* The error body of an invalid request containing a message.
+ *
+ * This model supports older versions of the error response model that used lower-case
+ * keys.
*/
@Serializable
data class ErrorModel(
+ @JsonNames("message")
@SerialName("Message")
val errorMessage: String,
)
-
- /**
- * The legacy error body of an invalid request containing a message.
- *
- * This model is used to support older versions of the error response model that used
- * lower-case keys.
- */
- @Serializable
- data class LegacyErrorModel(
- @SerialName("message")
- val errorMessage: String,
- )
}
/**
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/RegisterResponseJson.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/RegisterResponseJson.kt
index bff33119442..73ad1ce4ec9 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/RegisterResponseJson.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/RegisterResponseJson.kt
@@ -1,7 +1,9 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model
+import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonNames
/**
* Models response bodies for the register request.
@@ -50,20 +52,24 @@ sealed class RegisterResponseJson {
* The values in the array should be used for display to the user, since the keys tend to come
* back as nonsense. (eg: empty string key)
*/
+ @OptIn(ExperimentalSerializationApi::class)
@Serializable
data class Invalid(
- @SerialName("message")
- private val invalidMessage: String? = null,
-
+ @JsonNames("message")
@SerialName("Message")
- private val errorMessage: String? = null,
+ private val invalidMessage: String? = null,
@SerialName("validationErrors")
- val validationErrors: Map>?,
+ private val validationErrors: Map>?,
) : RegisterResponseJson() {
/**
* A generic error message.
*/
- val message: String? get() = invalidMessage ?: errorMessage
+ val message: String?
+ get() = validationErrors
+ ?.values
+ ?.firstOrNull()
+ ?.firstOrNull()
+ ?: invalidMessage
}
}
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt
index 35c44c52c1b..54702bb5e3f 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt
@@ -19,6 +19,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequest
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyOtpRequestJson
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
import com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_VALUE_BEARER_PREFIX
+import com.x8bit.bitwarden.data.platform.datasource.network.util.NetworkErrorCode
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
import kotlinx.serialization.json.Json
@@ -73,7 +74,7 @@ class AccountsServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -104,7 +105,7 @@ class AccountsServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 429,
+ code = NetworkErrorCode.TOO_MANY_REQUESTS,
json = json,
)
?: throw throwable
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt
index a4eae0f787b..fc701503592 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt
@@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorDataModel
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenResponseJson
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
+import com.x8bit.bitwarden.data.platform.datasource.network.util.NetworkErrorCode
import com.x8bit.bitwarden.data.platform.datasource.network.util.base64UrlEncode
import com.x8bit.bitwarden.data.platform.datasource.network.util.executeForNetworkResult
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
@@ -34,7 +35,6 @@ class IdentityServiceImpl(
.preLogin(PreLoginRequestJson(email = email))
.toResult()
- @Suppress("MagicNumber")
override suspend fun register(body: RegisterRequestJson): Result =
unauthenticatedIdentityApi
.register(body)
@@ -43,17 +43,19 @@ class IdentityServiceImpl(
val bitwardenError = throwable.toBitwardenError()
bitwardenError
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: bitwardenError.parseErrorBodyOrNull(
- codes = listOf(400, 429),
+ codes = listOf(
+ NetworkErrorCode.BAD_REQUEST,
+ NetworkErrorCode.TOO_MANY_REQUESTS,
+ ),
json = json,
)
?: throw throwable
}
- @Suppress("MagicNumber")
override suspend fun getToken(
uniqueAppId: String,
email: String,
@@ -87,21 +89,20 @@ class IdentityServiceImpl(
val bitwardenError = throwable.toBitwardenError()
bitwardenError
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: bitwardenError.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: bitwardenError.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
}
- @Suppress("MagicNumber")
override suspend fun prevalidateSso(
organizationIdentifier: String,
): Result = unauthenticatedIdentityApi
@@ -113,7 +114,7 @@ class IdentityServiceImpl(
val bitwardenError = throwable.toBitwardenError()
bitwardenError
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -130,7 +131,6 @@ class IdentityServiceImpl(
.executeForNetworkResult()
.toResult()
- @Suppress("MagicNumber")
override suspend fun registerFinish(
body: RegisterFinishRequestJson,
): Result =
@@ -141,13 +141,15 @@ class IdentityServiceImpl(
val bitwardenError = throwable.toBitwardenError()
bitwardenError
.parseErrorBodyOrNull(
- codes = listOf(400, 429),
+ codes = listOf(
+ NetworkErrorCode.BAD_REQUEST,
+ NetworkErrorCode.TOO_MANY_REQUESTS,
+ ),
json = json,
)
?: throw throwable
}
- @Suppress("MagicNumber")
override suspend fun sendVerificationEmail(
body: SendVerificationEmailRequestJson,
): Result {
@@ -159,14 +161,13 @@ class IdentityServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
}
}
- @Suppress("MagicNumber")
override suspend fun verifyEmailRegistrationToken(
body: VerifyEmailTokenRequestJson,
): Result = unauthenticatedIdentityApi
@@ -179,7 +180,7 @@ class IdentityServiceImpl(
val bitwardenError = throwable.toBitwardenError()
bitwardenError
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?.checkForExpiredMessage()
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt
index 7a4c4c46b19..70f92c4873d 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt
@@ -910,14 +910,7 @@ class AuthRepositoryImpl(
}
is RegisterResponseJson.Invalid -> {
- RegisterResult.Error(
- errorMessage = it
- .validationErrors
- ?.values
- ?.firstOrNull()
- ?.firstOrNull()
- ?: it.message,
- )
+ RegisterResult.Error(errorMessage = it.message)
}
}
},
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt
index ced0336bf0d..86dbbf8d301 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt
@@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.OrganizationType
* @property name The name of the organization (if applicable).
* @property shouldManageResetPassword Indicates that this user has the permission to manage their
* own password.
+ * @property shouldManagePolicies Indicates that this user has the permission to manage policies.
* @property shouldUseKeyConnector Indicates that the organization uses a key connector.
* @property role The user's role in the organization.
*/
@@ -16,6 +17,7 @@ data class Organization(
val id: String,
val name: String?,
val shouldManageResetPassword: Boolean,
+ val shouldManagePolicies: Boolean,
val shouldUseKeyConnector: Boolean,
val role: OrganizationType,
)
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt
index c124a136387..ac665edc955 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt
@@ -22,6 +22,7 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization =
shouldUseKeyConnector = this.shouldUseKeyConnector,
role = this.type,
shouldManageResetPassword = this.permissions.shouldManageResetPassword,
+ shouldManagePolicies = this.permissions.shouldManagePolicies,
)
/**
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/ExceptionExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/ExceptionExtensions.kt
index ce6b9a3e588..e0fa602946f 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/ExceptionExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/ExceptionExtensions.kt
@@ -17,9 +17,12 @@ import retrofit2.HttpException
* will be attempted to be parsed.
* @param json [Json] serializer to use.
*/
-inline fun BitwardenError.parseErrorBodyOrNull(codes: List, json: Json): T? =
+inline fun BitwardenError.parseErrorBodyOrNull(
+ codes: List,
+ json: Json,
+): T? =
(this as? BitwardenError.Http)
- ?.takeIf { codes.any { it == this.code } }
+ ?.takeIf { codes.any { it.code == this.code } }
?.responseBodyString
?.let { responseBody ->
json.decodeFromStringOrNull(responseBody)
@@ -28,5 +31,7 @@ inline fun BitwardenError.parseErrorBodyOrNull(codes: List, jso
/**
* Helper for calling [parseErrorBodyOrNull] with a single code.
*/
-inline fun BitwardenError.parseErrorBodyOrNull(code: Int, json: Json): T? =
- parseErrorBodyOrNull(listOf(code), json)
+inline fun BitwardenError.parseErrorBodyOrNull(
+ code: NetworkErrorCode,
+ json: Json,
+): T? = parseErrorBodyOrNull(codes = listOf(code), json = json)
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkErrorCode.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkErrorCode.kt
new file mode 100644
index 00000000000..7f4e8bb2507
--- /dev/null
+++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkErrorCode.kt
@@ -0,0 +1,11 @@
+package com.x8bit.bitwarden.data.platform.datasource.network.util
+
+/**
+ * An enum that represents HTTP error codes that we may need to parse for specific responses.
+ */
+enum class NetworkErrorCode(
+ val code: Int,
+) {
+ BAD_REQUEST(code = 400),
+ TOO_MANY_REQUESTS(code = 429),
+}
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt
index 09c46cba892..7faec25b8fd 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt
@@ -31,7 +31,6 @@ sealed class FlagKey {
OnboardingFlow,
OnboardingCarousel,
ImportLoginsFlow,
- SshKeyCipherItems,
VerifiedSsoDomainEndpoint,
CredentialExchangeProtocolImport,
CredentialExchangeProtocolExport,
@@ -94,15 +93,6 @@ sealed class FlagKey {
override val isRemotelyConfigured: Boolean = true
}
- /**
- * Data object holding the feature flag key for the SSH key cipher items feature.
- */
- data object SshKeyCipherItems : FlagKey() {
- override val keyName: String = "ssh-key-vault-item"
- override val defaultValue: Boolean = false
- override val isRemotelyConfigured: Boolean = true
- }
-
/**
* Data object holding the feature flag key for the new verified SSO domain endpoint feature.
*/
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt
index 3e4fc2d836a..1170a2c6102 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt
@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service
import androidx.core.net.toUri
import com.bitwarden.vault.Attachment
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
+import com.x8bit.bitwarden.data.platform.datasource.network.util.NetworkErrorCode
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
import com.x8bit.bitwarden.data.platform.util.asFailure
@@ -110,7 +111,7 @@ class CiphersServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -229,7 +230,7 @@ class CiphersServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt
index c1d7090fc7e..d76941df947 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt
@@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.vault.datasource.network.service
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
+import com.x8bit.bitwarden.data.platform.datasource.network.util.NetworkErrorCode
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
import com.x8bit.bitwarden.data.vault.datasource.network.api.FoldersApi
@@ -33,7 +34,7 @@ class FolderServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt
index 63647394c51..313867860b5 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt
@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service
import androidx.core.net.toUri
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
+import com.x8bit.bitwarden.data.platform.datasource.network.util.NetworkErrorCode
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
import com.x8bit.bitwarden.data.vault.datasource.network.api.AzureApi
@@ -42,7 +43,7 @@ class SendsServiceImpl(
.recoverCatching { throwable ->
throwable.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -58,7 +59,7 @@ class SendsServiceImpl(
.recoverCatching { throwable ->
throwable.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -79,7 +80,7 @@ class SendsServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
@@ -143,7 +144,7 @@ class SendsServiceImpl(
throwable
.toBitwardenError()
.parseErrorBodyOrNull(
- code = 400,
+ code = NetworkErrorCode.BAD_REQUEST,
json = json,
)
?: throw throwable
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt
index 3e44ce9c828..1e3ad263417 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt
@@ -229,7 +229,7 @@ private fun TwoFactorLoginScreenContent(
.imePadding()
.verticalScroll(rememberScrollState()),
) {
- if (state.authMethod == TwoFactorAuthMethod.EMAIL) {
+ if (state.authMethod != TwoFactorAuthMethod.YUBI_KEY) {
state.imageRes?.let {
Spacer(modifier = Modifier.height(12.dp))
Image(
@@ -237,7 +237,7 @@ private fun TwoFactorLoginScreenContent(
contentDescription = null,
modifier = Modifier
.standardHorizontalMargin()
- .size(100.dp),
+ .size(124.dp),
)
Spacer(modifier = Modifier.height(12.dp))
}
@@ -261,7 +261,7 @@ private fun TwoFactorLoginScreenContent(
Spacer(modifier = Modifier.height(12.dp))
- if (state.authMethod != TwoFactorAuthMethod.EMAIL) {
+ if (state.authMethod == TwoFactorAuthMethod.YUBI_KEY) {
state.imageRes?.let {
Spacer(modifier = Modifier.height(12.dp))
Image(
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt
index 8d3abba9a14..a5eeadc8e61 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt
@@ -119,5 +119,6 @@ val TwoFactorAuthMethod.imageRes: Int?
get() = when (this) {
TwoFactorAuthMethod.YUBI_KEY -> R.drawable.yubi_key
TwoFactorAuthMethod.EMAIL -> R.drawable.img_new_device_verification
+ TwoFactorAuthMethod.AUTHENTICATOR_APP -> R.drawable.img_authenticator
else -> null
}
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt
index 9b999012697..49dfebf0057 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt
@@ -29,7 +29,6 @@ fun FlagKey.ListItemContent(
FlagKey.OnboardingCarousel,
FlagKey.OnboardingFlow,
FlagKey.ImportLoginsFlow,
- FlagKey.SshKeyCipherItems,
FlagKey.VerifiedSsoDomainEndpoint,
FlagKey.CredentialExchangeProtocolImport,
FlagKey.CredentialExchangeProtocolExport,
@@ -87,7 +86,6 @@ private fun FlagKey.getDisplayLabel(): String = when (this) {
FlagKey.OnboardingCarousel -> stringResource(R.string.onboarding_carousel)
FlagKey.OnboardingFlow -> stringResource(R.string.onboarding_flow)
FlagKey.ImportLoginsFlow -> stringResource(R.string.import_logins_flow)
- FlagKey.SshKeyCipherItems -> stringResource(R.string.ssh_key_cipher_item_types)
FlagKey.VerifiedSsoDomainEndpoint -> stringResource(R.string.verified_sso_domain_verified)
FlagKey.CredentialExchangeProtocolImport -> stringResource(R.string.cxp_import)
FlagKey.CredentialExchangeProtocolExport -> stringResource(R.string.cxp_export)
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityViewModel.kt
index 8deaf6be257..d189a23076c 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityViewModel.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityViewModel.kt
@@ -6,6 +6,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
+import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult
import com.x8bit.bitwarden.data.auth.repository.util.policyInformation
@@ -21,7 +22,9 @@ import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
+import com.x8bit.bitwarden.data.vault.datasource.network.model.OrganizationType
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
+import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
@@ -113,10 +116,10 @@ class AccountSecurityViewModel @Inject constructor(
.launchIn(viewModelScope)
policyManager
- .getActivePoliciesFlow(type = PolicyTypeJson.REMOVE_UNLOCK_WITH_PIN)
+ .getActivePoliciesFlow(type = (PolicyTypeJson.REMOVE_UNLOCK_WITH_PIN))
.map { policies ->
AccountSecurityAction.Internal.RemovePinPolicyUpdateReceive(
- removeUnlockWithPinPolicyEnabled = policies.isNotEmpty(),
+ removeUnlockWithPinPolicyEnabled = arePoliciesValid(policies),
)
}
.onEach(::sendAction)
@@ -166,6 +169,20 @@ class AccountSecurityViewModel @Inject constructor(
}
}
+ private fun arePoliciesValid(policies: List) =
+ policies.any { policy ->
+ authRepository.userStateFlow.value?.activeAccount?.organizations?.any { org ->
+ (policy.organizationId == org.id) && !isExemptFromPolicy(org)
+ } == true
+ }
+
+ private fun isExemptFromPolicy(
+ userOrg: Organization,
+ ) = userOrg.role == OrganizationType.OWNER ||
+ userOrg.role == OrganizationType.ADMIN ||
+ (userOrg.role == OrganizationType.CUSTOM &&
+ userOrg.shouldManagePolicies)
+
override fun handleAction(action: AccountSecurityAction): Unit = when (action) {
AccountSecurityAction.AccountFingerprintPhraseClick -> handleAccountFingerprintPhraseClick()
is AccountSecurityAction.AuthenticatorSyncToggle -> handleAuthenticatorSyncToggle(action)
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt
index fb2d61c7c8c..13b5b729da5 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt
@@ -47,6 +47,7 @@ import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
+import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.ChromeAutofillSettingsCard
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.util.displayLabel
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import kotlinx.collections.immutable.toImmutableList
@@ -95,6 +96,11 @@ fun AutoFillScreen(
}
AutoFillEvent.NavigateToSetupAutofill -> onNavigateToSetupAutofill()
+ is AutoFillEvent.NavigateToChromeAutofillSettings -> {
+ intentManager.startChromeAutofillSettingsActivity(
+ releaseChannel = event.releaseChannel,
+ )
+ }
}
}
@@ -139,7 +145,7 @@ fun AutoFillScreen(
actionText = stringResource(R.string.get_started),
onActionClick = remember(viewModel) {
{
- viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick)
+ viewModel.trySendAction(AutoFillAction.AutofillActionCardCtaClick)
}
},
onDismissClick = remember(viewModel) {
@@ -196,6 +202,20 @@ fun AutoFillScreen(
)
Spacer(modifier = Modifier.height(height = 8.dp))
}
+
+ if (state.chromeAutofillSettingsOptions.isNotEmpty()) {
+ ChromeAutofillSettingsCard(
+ options = state.chromeAutofillSettingsOptions,
+ onOptionClicked = remember(viewModel) {
+ {
+ viewModel.trySendAction(AutoFillAction.ChromeAutofillSelected(it))
+ }
+ },
+ enabled = state.isAutoFillServicesEnabled,
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ }
+
if (state.showPasskeyManagementRow) {
BitwardenExternalLinkRow(
text = stringResource(id = R.string.passkey_management),
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt
index 918c8a3d9d3..164b682597f 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt
@@ -5,13 +5,20 @@ import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
+import com.x8bit.bitwarden.data.autofill.manager.chrome.ChromeThirdPartyAutofillEnabledManager
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeThirdPartyAutofillStatus
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
+import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.model.ChromeAutofillSettingsOption
+import com.x8bit.bitwarden.ui.platform.util.persistentListOfNotNull
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@@ -28,6 +35,7 @@ private const val KEY_STATE = "state"
@HiltViewModel
class AutoFillViewModel @Inject constructor(
authRepository: AuthRepository,
+ chromeThirdPartyAutofillEnabledManager: ChromeThirdPartyAutofillEnabledManager,
private val savedStateHandle: SavedStateHandle,
private val settingsRepository: SettingsRepository,
private val firstTimeActionManager: FirstTimeActionManager,
@@ -50,6 +58,7 @@ class AutoFillViewModel @Inject constructor(
defaultUriMatchType = settingsRepository.defaultUriMatchType,
showAutofillActionCard = false,
activeUserId = userId,
+ chromeAutofillSettingsOptions = persistentListOf(),
)
},
) {
@@ -81,6 +90,12 @@ class AutoFillViewModel @Inject constructor(
.map { AutoFillAction.Internal.UpdateShowAutofillActionCard(it.showSetupAutofillCard) }
.onEach(::sendAction)
.launchIn(viewModelScope)
+
+ chromeThirdPartyAutofillEnabledManager
+ .chromeThirdPartyAutofillStatusFlow
+ .map { AutoFillAction.Internal.ChromeAutofillStatusReceive(status = it) }
+ .onEach(::sendAction)
+ .launchIn(viewModelScope)
}
override fun handleAction(action: AutoFillAction) = when (action) {
@@ -94,8 +109,9 @@ class AutoFillViewModel @Inject constructor(
is AutoFillAction.UseInlineAutofillClick -> handleUseInlineAutofillClick(action)
AutoFillAction.PasskeyManagementClick -> handlePasskeyManagementClick()
is AutoFillAction.Internal -> handleInternalAction(action)
- AutoFillAction.AutoFillActionCardCtaClick -> handleAutoFillActionCardCtClick()
+ AutoFillAction.AutofillActionCardCtaClick -> handleAutofillActionCardCtaClick()
AutoFillAction.DismissShowAutofillActionCard -> handleDismissShowAutofillActionCard()
+ is AutoFillAction.ChromeAutofillSelected -> handleChromeAutofillSelected(action)
}
private fun handleInternalAction(action: AutoFillAction.Internal) {
@@ -111,14 +127,34 @@ class AutoFillViewModel @Inject constructor(
is AutoFillAction.Internal.UpdateShowAutofillActionCard -> {
handleUpdateShowAutofillActionCard(action)
}
+
+ is AutoFillAction.Internal.ChromeAutofillStatusReceive -> {
+ handleChromeAutofillStatusReceive(action)
+ }
+ }
+ }
+
+ private fun handleChromeAutofillStatusReceive(
+ action: AutoFillAction.Internal.ChromeAutofillStatusReceive,
+ ) {
+ mutableStateFlow.update {
+ it.copy(
+ chromeAutofillSettingsOptions = action
+ .status
+ .toChromeAutoFillSettingsOptions(),
+ )
}
}
+ private fun handleChromeAutofillSelected(action: AutoFillAction.ChromeAutofillSelected) {
+ sendEvent(AutoFillEvent.NavigateToChromeAutofillSettings(action.releaseChannel))
+ }
+
private fun handleDismissShowAutofillActionCard() {
dismissShowAutofillActionCard()
}
- private fun handleAutoFillActionCardCtClick() {
+ private fun handleAutofillActionCardCtaClick() {
sendEvent(AutoFillEvent.NavigateToSetupAutofill)
}
@@ -216,6 +252,7 @@ data class AutoFillState(
val defaultUriMatchType: UriMatchType,
val showAutofillActionCard: Boolean,
val activeUserId: String,
+ val chromeAutofillSettingsOptions: ImmutableList,
) : Parcelable {
/**
@@ -226,6 +263,19 @@ data class AutoFillState(
get() = isAutoFillServicesEnabled
}
+@Suppress("MaxLineLength")
+private fun ChromeThirdPartyAutofillStatus.toChromeAutoFillSettingsOptions(): ImmutableList =
+ persistentListOfNotNull(
+ ChromeAutofillSettingsOption.Stable(
+ enabled = this.stableStatusData.isThirdPartyEnabled,
+ )
+ .takeIf { this.stableStatusData.isAvailable },
+ ChromeAutofillSettingsOption.Beta(
+ enabled = this.betaChannelStatusData.isThirdPartyEnabled,
+ )
+ .takeIf { this.betaChannelStatusData.isAvailable },
+ )
+
/**
* Models events for the auto-fill screen.
*/
@@ -262,6 +312,13 @@ sealed class AutoFillEvent {
val text: Text,
) : AutoFillEvent()
+ /**
+ * Navigate to the Autofill settings of the specified [releaseChannel].
+ */
+ data class NavigateToChromeAutofillSettings(
+ val releaseChannel: ChromeReleaseChannel,
+ ) : AutoFillEvent()
+
/**
* Navigates to the setup autofill screen.
*/
@@ -335,7 +392,12 @@ sealed class AutoFillAction {
/**
* User has clicked the CTA on the autofill action card.
*/
- data object AutoFillActionCardCtaClick : AutoFillAction()
+ data object AutofillActionCardCtaClick : AutoFillAction()
+
+ /**
+ * User has clicked one of the chrome autofill options.
+ */
+ data class ChromeAutofillSelected(val releaseChannel: ChromeReleaseChannel) : AutoFillAction()
/**
* Internal actions.
@@ -359,5 +421,12 @@ sealed class AutoFillAction {
* An update for changes in the [showAutofillActionCard] value from the settings repository.
*/
data class UpdateShowAutofillActionCard(val showAutofillActionCard: Boolean) : Internal()
+
+ /**
+ * Received updated [ChromeThirdPartyAutofillStatus] data.
+ */
+ data class ChromeAutofillStatusReceive(
+ val status: ChromeThirdPartyAutofillStatus,
+ ) : Internal()
}
}
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/ChromeAutofillSettingsCard.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/ChromeAutofillSettingsCard.kt
new file mode 100644
index 00000000000..e072dd9b00b
--- /dev/null
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/ChromeAutofillSettingsCard.kt
@@ -0,0 +1,94 @@
+package com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.x8bit.bitwarden.R
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
+import com.x8bit.bitwarden.ui.platform.base.util.cardStyle
+import com.x8bit.bitwarden.ui.platform.base.util.standardHorizontalMargin
+import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
+import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
+import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.model.ChromeAutofillSettingsOption
+import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.persistentListOf
+
+/**
+ * Card for displaying a list of [ChromeAutofillSettingsOption]s and whether they are
+ * currently enabled.
+ *
+ * @param options List of data to display in the card, if the list is empty nothing will be drawn.
+ * @param onOptionClicked Lambda that is invoked when an option row is clicked and passes back the
+ * [ChromeReleaseChannel] for that option.
+ * @param enabled Whether to show the switches for each option as enabled.
+ */
+@Composable
+fun ChromeAutofillSettingsCard(
+ options: ImmutableList,
+ onOptionClicked: (ChromeReleaseChannel) -> Unit,
+ enabled: Boolean,
+ modifier: Modifier = Modifier,
+) {
+ if (options.isEmpty()) return
+ Column(modifier = modifier) {
+ options.forEachIndexed { index, option ->
+ BitwardenSwitch(
+ label = option.optionText(),
+ isChecked = option.isEnabled,
+ onCheckedChange = {
+ onOptionClicked(option.chromeReleaseChannel)
+ },
+ cardStyle = if (index == 0) {
+ CardStyle.Top(
+ dividerPadding = 16.dp,
+ )
+ } else {
+ CardStyle.Middle(
+ dividerPadding = 16.dp,
+ )
+ },
+ enabled = enabled,
+ modifier = Modifier
+ .fillMaxWidth()
+ .standardHorizontalMargin(),
+ )
+ }
+ Text(
+ text = stringResource(
+ R.string.improves_login_filling_for_supported_websites_on_chrome,
+ ),
+ style = BitwardenTheme.typography.bodyMedium,
+ color = BitwardenTheme.colorScheme.text.secondary,
+ modifier = Modifier
+ .fillMaxWidth()
+ .standardHorizontalMargin()
+ .cardStyle(
+ cardStyle = CardStyle.Bottom,
+ paddingHorizontal = 16.dp,
+ )
+ .defaultMinSize(minHeight = 48.dp),
+ )
+ }
+}
+
+@Preview
+@Composable
+private fun ChromeAutofillSettingsCard_preview() {
+ BitwardenTheme {
+ ChromeAutofillSettingsCard(
+ options = persistentListOf(
+ ChromeAutofillSettingsOption.Stable(enabled = false),
+ ChromeAutofillSettingsOption.Beta(enabled = true),
+ ),
+ enabled = true,
+ onOptionClicked = {},
+ )
+ }
+}
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/model/ChromeAutofillSettingsOption.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/model/ChromeAutofillSettingsOption.kt
new file mode 100644
index 00000000000..e3c463beeb3
--- /dev/null
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/chrome/model/ChromeAutofillSettingsOption.kt
@@ -0,0 +1,42 @@
+package com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.model
+
+import android.os.Parcelable
+import com.x8bit.bitwarden.R
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
+import com.x8bit.bitwarden.ui.platform.base.util.Text
+import com.x8bit.bitwarden.ui.platform.base.util.asText
+import kotlinx.parcelize.Parcelize
+
+/**
+ * Models an option for an option for each type of supported version of Chrome to enable
+ * third party autofill. Each [ChromeAutofillSettingsOption] contains the associated
+ * [ChromeReleaseChannel], the [optionText] to display in any UI component, and
+ * whether or not the third party autofill [isEnabled].
+ */
+@Parcelize
+sealed class ChromeAutofillSettingsOption(val isEnabled: Boolean) : Parcelable {
+ abstract val chromeReleaseChannel: ChromeReleaseChannel
+ abstract val optionText: Text
+
+ /**
+ * Represents the stable Chrome release channel.
+ */
+ @Parcelize
+ data class Stable(val enabled: Boolean) : ChromeAutofillSettingsOption(isEnabled = enabled) {
+ override val chromeReleaseChannel: ChromeReleaseChannel
+ get() = ChromeReleaseChannel.STABLE
+ override val optionText: Text
+ get() = R.string.use_chrome_autofill_integration.asText()
+ }
+
+ /**
+ * Represents the beta Chrome release channel.
+ */
+ @Parcelize
+ data class Beta(val enabled: Boolean) : ChromeAutofillSettingsOption(isEnabled = enabled) {
+ override val chromeReleaseChannel: ChromeReleaseChannel
+ get() = ChromeReleaseChannel.BETA
+ override val optionText: Text
+ get() = R.string.use_chrome_beta_autofill_integration.asText()
+ }
+}
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt
index ff00823ca77..b43893b0bc4 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt
@@ -9,6 +9,7 @@ import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
import kotlinx.parcelize.Parcelize
/**
@@ -48,6 +49,11 @@ interface IntentManager {
*/
fun startCredentialManagerSettings(context: Context)
+ /**
+ * Starts the Chrome autofill settings activity for the provided [ChromeReleaseChannel].
+ */
+ fun startChromeAutofillSettingsActivity(releaseChannel: ChromeReleaseChannel): Boolean
+
/**
* Start an activity to view the given [uri] in an external browser.
*/
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt
index 3902676e627..c3a0bb92cfe 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt
@@ -26,6 +26,7 @@ import androidx.credentials.CredentialManager
import com.x8bit.bitwarden.BuildConfig
import com.x8bit.bitwarden.MainActivity
import com.x8bit.bitwarden.R
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
@@ -133,6 +134,22 @@ class IntentManagerImpl(
}
}
+ override fun startChromeAutofillSettingsActivity(
+ releaseChannel: ChromeReleaseChannel,
+ ): Boolean = try {
+ val intent = Intent(Intent.ACTION_APPLICATION_PREFERENCES)
+ .apply {
+ addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_APP_BROWSER)
+ addCategory(Intent.CATEGORY_PREFERENCE)
+ setPackage(releaseChannel.packageName)
+ }
+ context.startActivity(intent)
+ true
+ } catch (_: ActivityNotFoundException) {
+ false
+ }
+
override fun launchUri(uri: Uri) {
if (uri.scheme.equals(other = "androidapp", ignoreCase = true)) {
val packageName = uri.toString().removePrefix(prefix = "androidapp://")
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultContent.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultContent.kt
index 10a6e000303..74fdeeed3d1 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultContent.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultContent.kt
@@ -37,7 +37,6 @@ fun VaultContent(
state: VaultState.ViewState.Content,
vaultHandlers: VaultHandlers,
onOverflowOptionClick: (action: ListingItemOverflowAction.VaultAction) -> Unit,
- showSshKeys: Boolean,
modifier: Modifier = Modifier,
) {
LazyColumn(
@@ -192,11 +191,7 @@ fun VaultContent(
supportingLabel = state.secureNoteItemsCount.toString(),
onClick = vaultHandlers.secureNoteGroupClick,
showDivider = false,
- cardStyle = if (showSshKeys) {
- CardStyle.Middle(dividerPadding = 56.dp)
- } else {
- CardStyle.Bottom
- },
+ cardStyle = CardStyle.Middle(dividerPadding = 56.dp),
modifier = Modifier
.fillMaxWidth()
.testTag("SecureNoteFilter")
@@ -204,22 +199,20 @@ fun VaultContent(
)
}
- if (showSshKeys) {
- item {
- BitwardenGroupItem(
- startIcon = rememberVectorPainter(id = R.drawable.ic_ssh_key),
- startIconTestTag = "SshKeyCipherIcon",
- label = stringResource(id = R.string.type_ssh_key),
- supportingLabel = state.sshKeyItemsCount.toString(),
- onClick = vaultHandlers.sshKeyGroupClick,
- showDivider = false,
- cardStyle = CardStyle.Bottom,
- modifier = Modifier
- .fillMaxWidth()
- .testTag("SshKeyFilter")
- .standardHorizontalMargin(),
- )
- }
+ item {
+ BitwardenGroupItem(
+ startIcon = rememberVectorPainter(id = R.drawable.ic_ssh_key),
+ startIconTestTag = "SshKeyCipherIcon",
+ label = stringResource(id = R.string.type_ssh_key),
+ supportingLabel = state.sshKeyItemsCount.toString(),
+ onClick = vaultHandlers.sshKeyGroupClick,
+ showDivider = false,
+ cardStyle = CardStyle.Bottom,
+ modifier = Modifier
+ .fillMaxWidth()
+ .testTag("SshKeyFilter")
+ .standardHorizontalMargin(),
+ )
}
item {
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt
index 5bbcbe6e3e0..91f52125a53 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt
@@ -352,7 +352,6 @@ private fun VaultScreenScaffold(
when (val viewState = state.viewState) {
is VaultState.ViewState.Content -> VaultContent(
state = viewState,
- showSshKeys = state.showSshKeys,
vaultHandlers = vaultHandlers,
onOverflowOptionClick = { masterPasswordRepromptAction = it },
modifier = Modifier.fillMaxSize(),
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt
index 9cfadc9a304..29f39f57a20 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt
@@ -98,7 +98,6 @@ class VaultViewModel @Inject constructor(
.any(),
)
val appBarTitle = vaultFilterData.toAppBarTitle()
- val showSshKeys = featureFlagManager.getFeatureFlag(FlagKey.SshKeyCipherItems)
VaultState(
appBarTitle = appBarTitle,
initials = activeAccountSummary.initials,
@@ -113,7 +112,6 @@ class VaultViewModel @Inject constructor(
hasMasterPassword = userState.activeAccount.hasMasterPassword,
isRefreshing = false,
showImportActionCard = false,
- showSshKeys = showSshKeys,
)
},
) {
@@ -141,15 +139,9 @@ class VaultViewModel @Inject constructor(
.onEach(::sendAction)
.launchIn(viewModelScope)
- combine(
- vaultRepository.vaultDataStateFlow,
- featureFlagManager.getFeatureFlagFlow(FlagKey.SshKeyCipherItems),
- ) { vaultData, sshKeyCipherItemsEnabled ->
- VaultAction.Internal.VaultDataReceive(
- vaultData = vaultData,
- showSshKeys = sshKeyCipherItemsEnabled,
- )
- }
+ vaultRepository
+ .vaultDataStateFlow
+ .map { VaultAction.Internal.VaultDataReceive(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)
@@ -266,7 +258,6 @@ class VaultViewModel @Inject constructor(
updateViewState(
vaultData = vaultRepository.vaultDataStateFlow.value,
- showSshKeys = state.showSshKeys,
)
}
@@ -405,7 +396,6 @@ class VaultViewModel @Inject constructor(
// Re-process the current vault data with the new filter
updateViewState(
vaultData = vaultRepository.vaultDataStateFlow.value,
- showSshKeys = state.showSshKeys,
)
}
@@ -694,22 +684,19 @@ class VaultViewModel @Inject constructor(
updateViewState(
vaultData = action.vaultData,
- showSshKeys = action.showSshKeys,
)
}
- private fun updateViewState(vaultData: DataState, showSshKeys: Boolean) {
+ private fun updateViewState(vaultData: DataState) {
when (vaultData) {
is DataState.Error -> vaultErrorReceive(vaultData = vaultData)
is DataState.Loaded -> vaultLoadedReceive(
vaultData = vaultData,
- showSshKeys = showSshKeys,
)
is DataState.Loading -> vaultLoadingReceive()
is DataState.NoNetwork -> vaultNoNetworkReceive(
vaultData = vaultData,
- showSshKeys = showSshKeys,
)
is DataState.Pending -> vaultPendingReceive(vaultData = vaultData)
@@ -730,7 +717,7 @@ class VaultViewModel @Inject constructor(
)
}
- private fun vaultLoadedReceive(vaultData: DataState.Loaded, showSshKeys: Boolean) {
+ private fun vaultLoadedReceive(vaultData: DataState.Loaded) {
if (state.dialog == VaultState.DialogState.Syncing) {
sendEvent(
VaultEvent.ShowToast(
@@ -738,12 +725,11 @@ class VaultViewModel @Inject constructor(
),
)
}
- updateVaultState(vaultData.data, showSshKeys)
+ updateVaultState(vaultData.data)
}
private fun updateVaultState(
vaultData: VaultData,
- showSshKeys: Boolean,
) {
mutableStateFlow.update {
it.copy(
@@ -753,11 +739,9 @@ class VaultViewModel @Inject constructor(
isPremium = state.isPremium,
hasMasterPassword = state.hasMasterPassword,
vaultFilterType = vaultFilterTypeOrDefault,
- showSshKeys = showSshKeys,
),
dialog = null,
isRefreshing = false,
- showSshKeys = showSshKeys,
)
}
}
@@ -768,7 +752,6 @@ class VaultViewModel @Inject constructor(
private fun vaultNoNetworkReceive(
vaultData: DataState.NoNetwork,
- showSshKeys: Boolean,
) {
val data = vaultData.data ?: VaultData(
cipherViewList = emptyList(),
@@ -778,7 +761,6 @@ class VaultViewModel @Inject constructor(
)
updateVaultState(
vaultData = data,
- showSshKeys = showSshKeys,
)
}
@@ -791,7 +773,6 @@ class VaultViewModel @Inject constructor(
isPremium = state.isPremium,
hasMasterPassword = state.hasMasterPassword,
vaultFilterType = vaultFilterTypeOrDefault,
- showSshKeys = state.showSshKeys,
),
)
}
@@ -862,7 +843,6 @@ data class VaultState(
val isIconLoadingDisabled: Boolean,
val isRefreshing: Boolean,
val showImportActionCard: Boolean,
- val showSshKeys: Boolean,
) : Parcelable {
/**
@@ -1486,7 +1466,6 @@ sealed class VaultAction {
*/
data class VaultDataReceive(
val vaultData: DataState,
- val showSshKeys: Boolean,
) : Internal()
/**
@@ -1527,7 +1506,6 @@ private fun MutableStateFlow.updateToErrorStateOrDialog(
hasMasterPassword = hasMasterPassword,
vaultFilterType = vaultFilterType,
isIconLoadingDisabled = isIconLoadingDisabled,
- showSshKeys = it.showSshKeys,
),
dialog = VaultState.DialogState.Error(
title = errorTitle,
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt
index 4cc2f950259..7949949423d 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt
@@ -39,7 +39,6 @@ fun VaultData.toViewState(
isIconLoadingDisabled: Boolean,
baseIconUrl: String,
vaultFilterType: VaultFilterType,
- showSshKeys: Boolean,
): VaultState.ViewState {
val filteredCipherViewListWithDeletedItems =
@@ -47,7 +46,6 @@ fun VaultData.toViewState(
val filteredCipherViewList = filteredCipherViewListWithDeletedItems
.filter { it.deletedDate == null }
- .filterSshKeysIfNecessary(showSshKeys)
val filteredFolderViewList = folderViewList
.toFilteredList(
@@ -63,12 +61,7 @@ fun VaultData.toViewState(
val noFolderItems = filteredCipherViewList
.filter { it.folderId.isNullOrBlank() }
- val itemTypesCount: Int = if (showSshKeys) {
- CipherType.entries
- } else {
- CipherType.entries.filterNot { it == CipherType.SSH_KEY }
- }
- .size
+ val itemTypesCount: Int = CipherType.entries.size
return if (filteredCipherViewListWithDeletedItems.isEmpty()) {
VaultState.ViewState.NoItems
@@ -355,16 +348,3 @@ fun List.toFilteredList(
}
}
}
-
-/**
- * Filters out all [CipherView]s that are of type [CipherType.SSH_KEY] if [showSshKeys] is false.
- *
- * @param showSshKeys Whether to show SSH keys in the vault.
- */
-@JvmName("filterSshKeysIfNecessary")
-fun List.filterSshKeysIfNecessary(showSshKeys: Boolean): List =
- if (showSshKeys) {
- this
- } else {
- filter { it.type != CipherType.SSH_KEY }
- }
diff --git a/app/src/main/res/drawable-night/img_authenticator.xml b/app/src/main/res/drawable-night/img_authenticator.xml
new file mode 100644
index 00000000000..64b35b183e3
--- /dev/null
+++ b/app/src/main/res/drawable-night/img_authenticator.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/img_authenticator.xml b/app/src/main/res/drawable/img_authenticator.xml
new file mode 100644
index 00000000000..18174ceadfe
--- /dev/null
+++ b/app/src/main/res/drawable/img_authenticator.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f90740df5f6..e35128786e1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1104,7 +1104,6 @@ Do you want to switch to this account?
Save the exported file somewhere on your computer you can find easily.
This is not a recognized Bitwarden server. You may need to check with your provider or update your server.
Syncing logins...
- SSH Key Cipher Item Types
Download the browser extension
Go to bitwarden.com/download to integrate Bitwarden into your favorite browser for a seamless experience.
Use the web app
@@ -1221,4 +1220,7 @@ Do you want to switch to this account?
Passkey operation failed because user verification attempts exceeded.
Passkey operation failed because no item was selected.
Self-host server URL
+ Use Chrome autofill integration
+ Use Chrome autofill integration (Beta)
+ Improves login filling for supported websites on Chrome. Once enabled, you’ll be directed to Chrome settings to enable third-party autofill.
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt
index a0a92d72a79..d1657d08588 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt
@@ -168,7 +168,7 @@ class IdentityServiceTest : BaseServiceTest() {
val result = identityService.register(registerRequestBody)
assertEquals(
RegisterResponseJson.Invalid(
- errorMessage = "Slow down! Too many requests. Try again soon.",
+ invalidMessage = "Slow down! Too many requests. Try again soon.",
validationErrors = null,
),
result.getOrThrow(),
@@ -287,7 +287,7 @@ class IdentityServiceTest : BaseServiceTest() {
captchaToken = null,
uniqueAppId = UNIQUE_APP_ID,
)
- assertEquals(LEGACY_INVALID_LOGIN.asSuccess(), result)
+ assertEquals(INVALID_LOGIN.asSuccess(), result)
}
@Suppress("MaxLineLength")
@@ -363,7 +363,7 @@ class IdentityServiceTest : BaseServiceTest() {
val result = identityService.registerFinish(registerFinishRequestBody)
assertEquals(
RegisterResponseJson.Invalid(
- errorMessage = "Slow down! Too many requests. Try again soon.",
+ invalidMessage = "Slow down! Too many requests. Try again soon.",
validationErrors = null,
),
result.getOrThrow(),
@@ -651,7 +651,7 @@ private const val INVALID_LOGIN_JSON = """
private const val LEGACY_INVALID_LOGIN_JSON = """
{
"errorModel": {
- "message": "Legacy-123"
+ "message": "123"
}
}
"""
@@ -688,14 +688,6 @@ private val INVALID_LOGIN = GetTokenResponseJson.Invalid(
errorModel = GetTokenResponseJson.Invalid.ErrorModel(
errorMessage = "123",
),
- legacyErrorModel = null,
-)
-
-private val LEGACY_INVALID_LOGIN = GetTokenResponseJson.Invalid(
- errorModel = null,
- legacyErrorModel = GetTokenResponseJson.Invalid.LegacyErrorModel(
- errorMessage = "Legacy-123",
- ),
)
private val SEND_VERIFICATION_EMAIL_REQUEST = SendVerificationEmailRequestJson(
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt
index b17531cb1c4..e37554a0aff 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt
@@ -1574,7 +1574,6 @@ class AuthRepositoryTest {
errorModel = GetTokenResponseJson.Invalid.ErrorModel(
errorMessage = "mock_error_message",
),
- legacyErrorModel = null,
)
.asSuccess()
@@ -1617,7 +1616,6 @@ class AuthRepositoryTest {
errorModel = GetTokenResponseJson.Invalid.ErrorModel(
errorMessage = "new device verification required",
),
- legacyErrorModel = null,
)
.asSuccess()
@@ -2401,7 +2399,6 @@ class AuthRepositoryTest {
errorModel = GetTokenResponseJson.Invalid.ErrorModel(
errorMessage = "mock_error_message",
),
- legacyErrorModel = null,
)
.asSuccess()
@@ -2870,7 +2867,6 @@ class AuthRepositoryTest {
errorModel = GetTokenResponseJson.Invalid.ErrorModel(
errorMessage = "mock_error_message",
),
- legacyErrorModel = null,
)
.asSuccess()
@@ -4454,6 +4450,7 @@ class AuthRepositoryTest {
every { name } returns "orgName"
every { permissions } returns mockk {
every { shouldManageResetPassword } returns false
+ every { shouldManagePolicies } returns false
}
every { shouldUseKeyConnector } returns true
every { type } returns OrganizationType.USER
@@ -4479,6 +4476,7 @@ class AuthRepositoryTest {
every { name } returns "orgName"
every { permissions } returns mockk {
every { shouldManageResetPassword } returns false
+ every { shouldManagePolicies } returns false
}
every { shouldUseKeyConnector } returns true
every { type } returns OrganizationType.USER
@@ -4515,6 +4513,7 @@ class AuthRepositoryTest {
every { name } returns "orgName"
every { permissions } returns mockk {
every { shouldManageResetPassword } returns false
+ every { shouldManagePolicies } returns false
}
every { shouldUseKeyConnector } returns true
every { type } returns OrganizationType.USER
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/AuthDiskSourceExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/AuthDiskSourceExtensionsTest.kt
index 5c2057461e9..22fd6e99ea1 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/AuthDiskSourceExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/AuthDiskSourceExtensionsTest.kt
@@ -194,6 +194,7 @@ class AuthDiskSourceExtensionsTest {
shouldManageResetPassword = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
+ shouldManagePolicies = false,
),
),
),
@@ -204,6 +205,7 @@ class AuthDiskSourceExtensionsTest {
id = "mockId-2",
name = "mockName-2",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -216,6 +218,7 @@ class AuthDiskSourceExtensionsTest {
id = "mockId-3",
name = "mockName-3",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -363,6 +366,7 @@ class AuthDiskSourceExtensionsTest {
id = "mockId-1",
name = "mockName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -394,6 +398,7 @@ class AuthDiskSourceExtensionsTest {
id = "mockId-1",
name = "mockName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -406,6 +411,7 @@ class AuthDiskSourceExtensionsTest {
id = "mockId-2",
name = "mockName-2",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt
index 4eed0b800bb..c09266428fd 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt
@@ -21,6 +21,7 @@ class SyncResponseJsonExtensionsTest {
id = "mockId-1",
name = "mockName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -36,6 +37,7 @@ class SyncResponseJsonExtensionsTest {
id = "mockId-1",
name = "mockName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = true,
role = OrganizationType.ADMIN,
),
@@ -43,6 +45,7 @@ class SyncResponseJsonExtensionsTest {
id = "mockId-2",
name = "mockName-2",
shouldManageResetPassword = true,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.USER,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt
index d0e8580c487..a4f48c0342a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensionsTest.kt
@@ -364,6 +364,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -428,6 +429,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -472,6 +474,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -532,6 +535,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -577,6 +581,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -645,6 +650,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -690,6 +696,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -758,6 +765,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -803,6 +811,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -871,6 +880,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -917,6 +927,7 @@ class UserStateJsonExtensionsTest {
// Key part of the result #1, this is true or the role is owner or
// admin
shouldManageResetPassword = true,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.USER,
),
@@ -988,6 +999,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = true,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.USER,
),
@@ -1192,6 +1204,7 @@ class UserStateJsonExtensionsTest {
// Key part of the result #1, this is true or the role is owner or
// admin
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.USER,
),
@@ -1262,6 +1275,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.USER,
),
@@ -1307,6 +1321,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -1377,6 +1392,7 @@ class UserStateJsonExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt
index 31a55b99401..f3c61ad8bb0 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt
@@ -26,7 +26,7 @@ class ColorExtensionsTest : BaseComposeTest() {
@Test
fun `toSafeOverlayColor for a dark color in light mode should use the surface color`() =
- runTestWithTheme(theme = AppTheme.LIGHT) {
+ setContent(theme = AppTheme.LIGHT) {
assertEquals(
BitwardenTheme.colorScheme.background.primary,
Color.Blue.toSafeOverlayColor(),
@@ -35,7 +35,7 @@ class ColorExtensionsTest : BaseComposeTest() {
@Test
fun `toSafeOverlayColor for a dark color in dark mode should use the onSurface color`() =
- runTestWithTheme(theme = AppTheme.DARK) {
+ setContent(theme = AppTheme.DARK) {
assertEquals(
BitwardenTheme.colorScheme.text.primary,
Color.Blue.toSafeOverlayColor(),
@@ -44,7 +44,7 @@ class ColorExtensionsTest : BaseComposeTest() {
@Test
fun `toSafeOverlayColor for a light color in light mode should use the onSurface color`() =
- runTestWithTheme(theme = AppTheme.LIGHT) {
+ setContent(theme = AppTheme.LIGHT) {
assertEquals(
BitwardenTheme.colorScheme.text.primary,
Color.Yellow.toSafeOverlayColor(),
@@ -53,7 +53,7 @@ class ColorExtensionsTest : BaseComposeTest() {
@Test
fun `toSafeOverlayColor for a light color in dark mode should use the surface color`() =
- runTestWithTheme(theme = AppTheme.DARK) {
+ setContent(theme = AppTheme.DARK) {
assertEquals(
BitwardenTheme.colorScheme.background.primary,
Color.Yellow.toSafeOverlayColor(),
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt
index 19d87d7ba2a..c22af73bc14 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt
@@ -29,10 +29,6 @@ class FlagKeyTest {
FlagKey.ImportLoginsFlow.keyName,
"import-logins-flow",
)
- assertEquals(
- FlagKey.SshKeyCipherItems.keyName,
- "ssh-key-vault-item",
- )
assertEquals(
FlagKey.VerifiedSsoDomainEndpoint.keyName,
"pm-12337-refactor-sso-details-endpoint",
@@ -96,7 +92,6 @@ class FlagKeyTest {
FlagKey.OnboardingCarousel,
FlagKey.OnboardingFlow,
FlagKey.ImportLoginsFlow,
- FlagKey.SshKeyCipherItems,
FlagKey.VerifiedSsoDomainEndpoint,
FlagKey.CredentialExchangeProtocolImport,
FlagKey.CredentialExchangeProtocolExport,
@@ -124,7 +119,6 @@ class FlagKeyTest {
FlagKey.OnboardingCarousel,
FlagKey.OnboardingFlow,
FlagKey.ImportLoginsFlow,
- FlagKey.SshKeyCipherItems,
FlagKey.VerifiedSsoDomainEndpoint,
FlagKey.CredentialExchangeProtocolImport,
FlagKey.CredentialExchangeProtocolExport,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreenTest.kt
index 805e984a707..55ccab043bc 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreenTest.kt
@@ -37,7 +37,7 @@ class SetupAutofillScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
SetupAutoFillScreen(
intentManager = intentManager,
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreenTest.kt
index ebcba94ced1..a5043e267d6 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreenTest.kt
@@ -15,7 +15,7 @@ class SetupCompleteScreenTest : BaseComposeTest() {
@Before
fun setup() {
- setContentWithBackDispatcher {
+ setContent {
SetupCompleteScreen(viewModel = viewModel)
}
}
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreenTest.kt
index 5426e46f4e9..50f3e89a80a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreenTest.kt
@@ -65,7 +65,7 @@ class SetupUnlockScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
SetupUnlockScreen(
viewModel = viewModel,
biometricsManager = biometricsManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreenTest.kt
index ed735099ede..3250505b437 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreenTest.kt
@@ -32,7 +32,7 @@ class CheckEmailScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
CheckEmailScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreenTest.kt
index 39a364044a5..eadf4d46070 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreenTest.kt
@@ -55,7 +55,7 @@ class CompleteRegistrationScreenTest : BaseComposeTest() {
@Before
fun setup() {
- setContentWithBackDispatcher {
+ setContent {
CompleteRegistrationScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToPasswordGuidance = { onNavigateToPasswordGuidanceCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/PasswordStrengthIndicatorTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/PasswordStrengthIndicatorTest.kt
index 0196f8771a2..510cf32121d 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/PasswordStrengthIndicatorTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/PasswordStrengthIndicatorTest.kt
@@ -10,7 +10,7 @@ class PasswordStrengthIndicatorTest : BaseComposeTest() {
@Suppress("MaxLineLength")
@Test
fun `PasswordStrengthIndicator with minimum character count met displays minimum character count`() {
- composeTestRule.setContent {
+ setContent {
PasswordStrengthIndicator(
state = PasswordStrengthState.WEAK_3,
currentCharacterCount = 12,
@@ -27,7 +27,7 @@ class PasswordStrengthIndicatorTest : BaseComposeTest() {
@Suppress("MaxLineLength")
@Test
fun `PasswordStrengthIndicator with no minimum character count met does not minimum character count`() {
- composeTestRule.setContent {
+ setContent {
PasswordStrengthIndicator(
state = PasswordStrengthState.WEAK_3,
currentCharacterCount = 12,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt
index f462735345b..cc8045ee654 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt
@@ -61,7 +61,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
CreateAccountScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToLogin = { _, _ -> onNavigateToLoginCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreenTest.kt
index f44acde739b..d5470ba0994 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreenTest.kt
@@ -47,7 +47,7 @@ class EnterpriseSignOnScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
EnterpriseSignOnScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToSetPassword = { onNavigateToSetPasswordCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreenTest.kt
index 71d12437b68..31ce1f3607d 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreenTest.kt
@@ -47,7 +47,7 @@ class EnvironmentScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
EnvironmentScreen(
onNavigateBack = { onNavigateBackCalled = true },
intentManager = mockIntentManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreenTest.kt
index e76a6f6ec2b..6bbc7c46b9a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreenTest.kt
@@ -25,7 +25,7 @@ class ExpiredRegistrationLinkScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- setContentWithBackDispatcher {
+ setContent {
ExpiredRegistrationLinkScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToLogin = { onNavigateToLoginCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt
index 6f6a99adb11..4bfda9ae12b 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt
@@ -59,7 +59,7 @@ class LandingScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
LandingScreen(
onNavigateToCreateAccount = { onNavigateToCreateAccountCalled = true },
onNavigateToLogin = { capturedEmail ->
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt
index 9ccbd8fb267..82a464cba19 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt
@@ -64,7 +64,7 @@ class LoginScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
LoginScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToMasterPasswordHint = { onNavigateToMasterPasswordHintCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreenTest.kt
index 6bac14babbc..ad7904f9cca 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreenTest.kt
@@ -47,7 +47,7 @@ class LoginWithDeviceScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
LoginWithDeviceScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToTwoFactorLogin = { onNavigateToTwoFactorLoginEmail = it },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreenTest.kt
index d60e333fec1..f8b635d009a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreenTest.kt
@@ -32,7 +32,7 @@ class MasterPasswordGeneratorScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
MasterPasswordGeneratorScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToPreventLockout = { onNavigateToPreventLockoutCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt
index 66a1913ee1f..d9d0d9cf583 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt
@@ -25,7 +25,7 @@ class MasterPasswordGuidanceScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
MasterPasswordGuidanceScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToGeneratePassword = { onNavigateToGeneratorCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreenTest.kt
index bcc71bfe657..6bf75442d2b 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreenTest.kt
@@ -28,7 +28,7 @@ class MasterPasswordHintScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
MasterPasswordHintScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeEmailAccessScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeEmailAccessScreenTest.kt
index ab5ee23522b..cb0c0e3e639 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeEmailAccessScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeEmailAccessScreenTest.kt
@@ -37,7 +37,7 @@ class NewDeviceNoticeEmailAccessScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
NewDeviceNoticeEmailAccessScreen(
onNavigateBackToVault = { onNavigateBackToVaultCalled = true },
onNavigateToTwoFactorOptions = { onNavigateToTwoFactorOptionsCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreenTest.kt
index b16a4c045e2..775c69b73f0 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreenTest.kt
@@ -40,7 +40,7 @@ class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
NewDeviceNoticeTwoFactorScreen(
onNavigateBackToVault = { onNavigateBackToVaultCalled = true },
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreenTest.kt
index 53565ed9a9d..f02e1d8979d 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreenTest.kt
@@ -20,7 +20,7 @@ class PreventAccountLockoutScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
PreventAccountLockoutScreen(
onNavigateBack = { onBackHasBeenInvoked = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreenTest.kt
index ee937be0b11..c6ba40b23fb 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreenTest.kt
@@ -32,7 +32,7 @@ class RemovePasswordScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
RemovePasswordScreen(
viewModel = viewModel,
)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModelTest.kt
index 4a1657070a8..a64b0084bb6 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModelTest.kt
@@ -159,6 +159,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
id = "orgId",
name = ORGANIZATION_NAME,
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = true,
role = OrganizationType.USER,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/resetPassword/ResetPasswordScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/resetPassword/ResetPasswordScreenTest.kt
index 109b4ebb35a..c32c076c740 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/resetPassword/ResetPasswordScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/resetPassword/ResetPasswordScreenTest.kt
@@ -43,7 +43,7 @@ class ResetPasswordScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
ResetPasswordScreen(
onNavigateToPreventAccountLockOut = {
onNavigateToLearnToPreventLockoutCalled = true
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreenTest.kt
index 96c71d3bb3f..555afa0b9ce 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreenTest.kt
@@ -31,7 +31,7 @@ class SetPasswordScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
SetPasswordScreen(
viewModel = viewModel,
)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreenTest.kt
index b0299f2ef9f..1a8897bba32 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreenTest.kt
@@ -54,7 +54,7 @@ class StartRegistrationScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
StartRegistrationScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToCompleteRegistration = { _, _ ->
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreenTest.kt
index 330839b2416..1c1fb77e44e 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreenTest.kt
@@ -39,7 +39,7 @@ class TrustedDeviceScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
TrustedDeviceScreen(
viewModel = viewModel,
onNavigateToAdminApproval = { onNavigateToAdminApprovalEmail = it },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreenTest.kt
index 5967bd9219b..ca5f341db88 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreenTest.kt
@@ -49,7 +49,7 @@ class TwoFactorLoginScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
TwoFactorLoginScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt
index ffe43b43b00..d7236a25757 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt
@@ -135,7 +135,7 @@ class TwoFactorAuthMethodExtensionTest {
@Test
fun `imageRes returns the expected value`() {
mapOf(
- TwoFactorAuthMethod.AUTHENTICATOR_APP to null,
+ TwoFactorAuthMethod.AUTHENTICATOR_APP to R.drawable.img_authenticator,
TwoFactorAuthMethod.EMAIL to R.drawable.img_new_device_verification,
TwoFactorAuthMethod.DUO to null,
TwoFactorAuthMethod.YUBI_KEY to R.drawable.yubi_key,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt
index f7be47f8978..e9eaa166112 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt
@@ -83,7 +83,7 @@ class VaultUnlockScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
VaultUnlockScreen(
viewModel = viewModel,
biometricsManager = biometricsManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreenTest.kt
index c6bcf8fc5f4..dcd27e09f5a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreenTest.kt
@@ -28,7 +28,7 @@ class WelcomeScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
WelcomeScreen(
onNavigateToCreateAccount = { onNavigateToCreateAccountCalled = true },
onNavigateToLogin = { onNavigateToLoginCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/BaseComposeTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/BaseComposeTest.kt
index 0f63c18bca5..194ee47d066 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/BaseComposeTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/BaseComposeTest.kt
@@ -1,7 +1,6 @@
package com.x8bit.bitwarden.ui.platform.base
import androidx.activity.OnBackPressedDispatcher
-import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.ExperimentalTestApi
@@ -25,41 +24,25 @@ abstract class BaseComposeTest : BaseRobolectricTest() {
val composeTestRule = createComposeRule(effectContext = dispatcher)
/**
- * instance of [OnBackPressedDispatcher] made available if testing using
- *
- * [setContentWithBackDispatcher] or [runTestWithTheme]
+ * instance of [OnBackPressedDispatcher] made available if testing using [setContent].
*/
var backDispatcher: OnBackPressedDispatcher? = null
private set
/**
- * Helper for testing a basic Composable function that only requires a Composable environment
- * with the [BitwardenTheme].
+ * Helper for testing a basic Composable function that only requires a [Composable]. The
+ * [AppTheme] is overridable and the [backDispatcher] is configured automatically.
*/
- protected fun runTestWithTheme(
- theme: AppTheme,
+ protected fun setContent(
+ theme: AppTheme = AppTheme.DEFAULT,
test: @Composable () -> Unit,
) {
composeTestRule.setContent {
+ backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
BitwardenTheme(
theme = theme,
- ) {
- backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
- test()
- }
- }
- }
-
- /**
- * Helper for testing a basic Composable function that provides access to a
- * [OnBackPressedDispatcher].
- *
- * Use if the [Composable] function being tested uses a [BackHandler]
- */
- protected fun setContentWithBackDispatcher(test: @Composable () -> Unit) {
- composeTestRule.setContent {
- backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
- test()
+ content = test,
+ )
}
}
}
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringRestExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringRestExtensionsTest.kt
index a452cabcb21..43bf9d963db 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringRestExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/util/StringRestExtensionsTest.kt
@@ -16,7 +16,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Test
fun `toAnnotatedString should add Clickable LinkAnnotation to highlighted string`() {
var textClickCalled = false
- composeTestRule.setContent {
+ setContent {
val annotatedString =
R.string.test_for_single_link_annotation.toAnnotatedString {
textClickCalled = true
@@ -32,7 +32,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Suppress("MaxLineLength")
@Test
fun `toAnnotatedString should add multiple Clickable LinkAnnotations to highlighted string`() {
- composeTestRule.setContent {
+ setContent {
val annotatedString =
R.string.test_for_multi_link_annotation.toAnnotatedString()
Text(text = annotatedString)
@@ -45,7 +45,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Test
fun `no link annotations should be applied to non annotated string resource`() {
- composeTestRule.setContent {
+ setContent {
Text(text = R.string.test_for_string_with_no_annotations.toAnnotatedString())
}
@@ -65,7 +65,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Test
fun `string with args should only use the arguments available in the string`() {
- composeTestRule.setContent {
+ setContent {
Text(
text =
R.string.test_for_string_with_annotation_and_arg_annotation
@@ -89,7 +89,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Test
fun `string with arg annotations but no passed in args should just append empty string`() {
- composeTestRule.setContent {
+ setContent {
Text(
text = R.string.test_for_string_with_annotation_and_arg_annotation
.toAnnotatedString(),
@@ -104,7 +104,7 @@ class StringRestExtensionsTest : BaseComposeTest() {
@Suppress("MaxLineLength")
@Test
fun `string with no annotations with args should just be handled as normal annotated string`() {
- composeTestRule.setContent {
+ setContent {
Text(
text = R.string.test_for_string_with_no_annotations_with_format_arg.toAnnotatedString(
args = arrayOf("this"),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreenTest.kt
index 1d54c58f6e3..be47ca9a7a2 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreenTest.kt
@@ -30,7 +30,7 @@ class DebugMenuScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
DebugMenuScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt
index 21f011caa8d..8f762181e9a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt
@@ -123,7 +123,6 @@ private val DEFAULT_MAP_VALUE: Map, Any> = mapOf(
FlagKey.OnboardingCarousel to true,
FlagKey.OnboardingFlow to true,
FlagKey.ImportLoginsFlow to true,
- FlagKey.SshKeyCipherItems to true,
FlagKey.VerifiedSsoDomainEndpoint to true,
FlagKey.CredentialExchangeProtocolImport to true,
FlagKey.CredentialExchangeProtocolExport to true,
@@ -145,7 +144,6 @@ private val UPDATED_MAP_VALUE: Map, Any> = mapOf(
FlagKey.OnboardingCarousel to true,
FlagKey.OnboardingFlow to false,
FlagKey.ImportLoginsFlow to false,
- FlagKey.SshKeyCipherItems to false,
FlagKey.VerifiedSsoDomainEndpoint to false,
FlagKey.CredentialExchangeProtocolImport to false,
FlagKey.CredentialExchangeProtocolExport to false,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavScreenTest.kt
index f5520654c03..c0a4ac9983e 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavScreenTest.kt
@@ -35,7 +35,7 @@ class RootNavScreenTest : BaseComposeTest() {
every { eventFlow } returns emptyFlow()
every { stateFlow } returns MutableStateFlow(RootNavState.Splash)
}
- composeTestRule.setContent {
+ setContent {
RootNavScreen(
viewModel = viewModel,
navController = fakeNavHostController,
@@ -54,7 +54,7 @@ class RootNavScreenTest : BaseComposeTest() {
every { stateFlow } returns rootNavStateFlow
}
var isSplashScreenRemoved = false
- composeTestRule.setContent {
+ setContent {
RootNavScreen(
viewModel = viewModel,
navController = fakeNavHostController,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModelTest.kt
index 6bca299bc49..f50db24daa6 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModelTest.kt
@@ -385,6 +385,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
id = "orgId",
name = "orgName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = true,
role = OrganizationType.USER,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreenTest.kt
index db2a374af1d..58e76697988 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreenTest.kt
@@ -70,7 +70,7 @@ class SearchScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
SearchScreen(
viewModel = viewModel,
intentManager = intentManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreenTest.kt
index b17ef5ead59..901568ee6f2 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreenTest.kt
@@ -28,7 +28,7 @@ class SettingsScreenTest : BaseComposeTest() {
fun `on about row click should emit SettingsClick`() {
every { viewModel.trySendAction(SettingsAction.SettingsClick(Settings.ABOUT)) } just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -48,7 +48,7 @@ class SettingsScreenTest : BaseComposeTest() {
every {
viewModel.trySendAction(SettingsAction.SettingsClick(Settings.ACCOUNT_SECURITY))
} just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -68,7 +68,7 @@ class SettingsScreenTest : BaseComposeTest() {
every {
viewModel.trySendAction(SettingsAction.SettingsClick(Settings.APPEARANCE))
} just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -89,7 +89,7 @@ class SettingsScreenTest : BaseComposeTest() {
every {
viewModel.trySendAction(SettingsAction.SettingsClick(Settings.AUTO_FILL))
} just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -108,7 +108,7 @@ class SettingsScreenTest : BaseComposeTest() {
fun `on other row click should emit SettingsClick`() {
every { viewModel.trySendAction(SettingsAction.SettingsClick(Settings.OTHER)) } just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -127,7 +127,7 @@ class SettingsScreenTest : BaseComposeTest() {
fun `on vault row click should emit SettingsClick`() {
every { viewModel.trySendAction(SettingsAction.SettingsClick(Settings.VAULT)) } just runs
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -145,7 +145,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAbout should call onNavigateToAbout`() {
var haveCalledNavigateToAbout = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = {
@@ -165,7 +165,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurity should call onNavigateToAccountSecurity`() {
var haveCalledNavigateToAccountSecurity = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -185,7 +185,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurity should call NavigateAppearance`() {
var haveCalledNavigateToAppearance = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -203,7 +203,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurity should call onNavigateToAutoFill`() {
var haveCalledNavigateToAutoFill = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -223,7 +223,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurity should call onNavigateToOther`() {
var haveCalledNavigateToOther = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -243,7 +243,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurity should call NavigateVault`() {
var haveCalledNavigateToVault = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -263,7 +263,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `on NavigateAccountSecurityShortcut should call onNavigateToAccountSecurity`() {
var haveCalledNavigateToAccountSecurity = false
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = { },
@@ -281,7 +281,7 @@ class SettingsScreenTest : BaseComposeTest() {
@Test
fun `Settings screen should show correct number of notification badges based on state`() {
- composeTestRule.setContent {
+ setContent {
SettingsScreen(
viewModel = viewModel,
onNavigateToAbout = {},
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt
index 762bcb9819a..941f50b7aa0 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt
@@ -57,7 +57,7 @@ class AboutScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
AboutScreen(
viewModel = viewModel,
intentManager = intentManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt
index cdf02bd8aab..4a210e2e11f 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt
@@ -83,7 +83,7 @@ class AccountSecurityScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
AccountSecurityScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToDeleteAccount = { onNavigateToDeleteAccountCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreenTest.kt
index 91371f19bd0..57880337e76 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreenTest.kt
@@ -38,7 +38,7 @@ class DeleteAccountScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
DeleteAccountScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToDeleteAccountConfirmation = {
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreenTest.kt
index 9352a07b01c..c2a6308ff6a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreenTest.kt
@@ -33,7 +33,7 @@ class DeleteAccountConfirmationScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
DeleteAccountConfirmationScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreenTest.kt
index 359ef2e533f..5de0ef227a8 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreenTest.kt
@@ -40,7 +40,7 @@ class LoginApprovalScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- setContentWithBackDispatcher {
+ setContent {
LoginApprovalScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreenTest.kt
index df33a0c95df..4eb9b7cb07b 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreenTest.kt
@@ -55,7 +55,7 @@ class PendingRequestsScreenTest : BaseComposeTest() {
mockkStatic(::isBuildVersionBelow)
every { isFdroid } returns false
every { isBuildVersionBelow(any()) } returns false
- composeTestRule.setContent {
+ setContent {
PendingRequestsScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToLoginApproval = { _ -> onNavigateToLoginApprovalCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt
index aefc6ce69ab..edad812cafa 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt
@@ -37,7 +37,7 @@ class AppearanceScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
AppearanceScreen(
onNavigateBack = { haveCalledNavigateBack = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreenTest.kt
index 73ba3a893db..957e947a500 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreenTest.kt
@@ -14,9 +14,11 @@ import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
+import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.model.ChromeAutofillSettingsOption
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import io.mockk.every
@@ -24,6 +26,7 @@ import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.verify
+import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import org.junit.Assert.assertTrue
@@ -47,11 +50,12 @@ class AutoFillScreenTest : BaseComposeTest() {
every { startSystemAutofillSettingsActivity() } answers { isSystemSettingsRequestSuccess }
every { startCredentialManagerSettings(any()) } just runs
every { startSystemAccessibilitySettingsActivity() } just runs
+ every { startChromeAutofillSettingsActivity(any()) } returns true
}
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
AutoFillScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToBlockAutoFillScreen = { onNavigateToBlockAutoFillScreenCalled = true },
@@ -487,7 +491,7 @@ class AutoFillScreenTest : BaseComposeTest() {
.performScrollTo()
.performClick()
- verify { viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick) }
+ verify { viewModel.trySendAction(AutoFillAction.AutofillActionCardCtaClick) }
}
@Test
@@ -505,6 +509,83 @@ class AutoFillScreenTest : BaseComposeTest() {
mutableEventFlow.tryEmit(AutoFillEvent.NavigateToSetupAutofill)
assertTrue(onNavigateToSetupAutoFillScreenCalled)
}
+
+ @Test
+ fun `ChromeAutofillSettingsCard is only displayed when there are options in the list`() {
+ val chromeAutofillSupportingText =
+ "Improves login filling for supported websites on Chrome. " +
+ "Once enabled, you’ll be directed to Chrome settings to enable " +
+ "third-party autofill."
+
+ composeTestRule
+ .onNodeWithText(chromeAutofillSupportingText)
+ .assertDoesNotExist()
+
+ mutableStateFlow.update {
+ it.copy(
+ chromeAutofillSettingsOptions = persistentListOf(
+ ChromeAutofillSettingsOption.Stable(enabled = true),
+ ),
+ )
+ }
+
+ composeTestRule
+ .onNodeWithText(chromeAutofillSupportingText)
+ .performScrollTo()
+ .assertIsDisplayed()
+ }
+
+ @Test
+ fun `when Chrome autofill options are clicked the correct action is sent`() {
+ mutableStateFlow.update {
+ it.copy(
+ isAutoFillServicesEnabled = true,
+ chromeAutofillSettingsOptions = persistentListOf(
+ ChromeAutofillSettingsOption.Stable(enabled = true),
+ ChromeAutofillSettingsOption.Beta(enabled = false),
+ ),
+ )
+ }
+
+ composeTestRule
+ .onNodeWithText("Use Chrome autofill integration")
+ .performScrollTo()
+ .performClick()
+
+ composeTestRule
+ .onNodeWithText("Use Chrome autofill integration (Beta)")
+ .performScrollTo()
+ .performClick()
+
+ verify(exactly = 1) {
+ viewModel.trySendAction(
+ AutoFillAction.ChromeAutofillSelected(ChromeReleaseChannel.BETA),
+ )
+ viewModel.trySendAction(
+ AutoFillAction.ChromeAutofillSelected(ChromeReleaseChannel.STABLE),
+ )
+ }
+ }
+
+ @Suppress("MaxLineLength")
+ @Test
+ fun `when NavigateToChromeAutofillSettings events are sent they invoke the intent manager with the correct release channel`() {
+ mutableEventFlow.tryEmit(
+ AutoFillEvent.NavigateToChromeAutofillSettings(
+ ChromeReleaseChannel.STABLE,
+ ),
+ )
+ mutableEventFlow.tryEmit(
+ AutoFillEvent.NavigateToChromeAutofillSettings(
+ ChromeReleaseChannel.BETA,
+ ),
+ )
+
+ verify(exactly = 1) {
+ intentManager.startChromeAutofillSettingsActivity(ChromeReleaseChannel.BETA)
+ intentManager.startChromeAutofillSettingsActivity(ChromeReleaseChannel.STABLE)
+ }
+ }
}
private val DEFAULT_STATE: AutoFillState = AutoFillState(
@@ -518,4 +599,5 @@ private val DEFAULT_STATE: AutoFillState = AutoFillState(
defaultUriMatchType = UriMatchType.DOMAIN,
showAutofillActionCard = false,
activeUserId = "activeUserId",
+ chromeAutofillSettingsOptions = persistentListOf(),
)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt
index 643ba5f93ca..d7ef45ceed2 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt
@@ -4,12 +4,17 @@ import android.os.Build
import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
+import com.x8bit.bitwarden.data.autofill.manager.chrome.ChromeThirdPartyAutofillEnabledManager
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeReleaseChannel
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeThirdPartyAutoFillData
+import com.x8bit.bitwarden.data.autofill.model.chrome.ChromeThirdPartyAutofillStatus
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
+import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.chrome.model.ChromeAutofillSettingsOption
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
@@ -17,6 +22,7 @@ import io.mockk.mockkStatic
import io.mockk.runs
import io.mockk.unmockkStatic
import io.mockk.verify
+import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest
@@ -40,6 +46,12 @@ class AutoFillViewModelTest : BaseViewModelTest() {
every { storeShowAutoFillSettingBadge(any()) } just runs
}
+ private val mutableChromeAutofillStatusFlow = MutableStateFlow(DEFAULT_AUTOFILL_STATUS)
+ private val chromeThirdPartyAutofillEnabledManager =
+ mockk {
+ every { chromeThirdPartyAutofillStatusFlow } returns mutableChromeAutofillStatusFlow
+ }
+
private val settingsRepository: SettingsRepository = mockk {
every { isInlineAutofillEnabled } returns true
every { isInlineAutofillEnabled = any() } just runs
@@ -330,7 +342,7 @@ class AutoFillViewModelTest : BaseViewModelTest() {
mutableFirstTimeStateFlow.update { it.copy(showSetupAutofillCard = true) }
val viewModel = createViewModel()
viewModel.eventFlow.test {
- viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick)
+ viewModel.trySendAction(AutoFillAction.AutofillActionCardCtaClick)
assertEquals(
AutoFillEvent.NavigateToSetupAutofill,
awaitItem(),
@@ -354,6 +366,55 @@ class AutoFillViewModelTest : BaseViewModelTest() {
}
}
+ @Suppress("MaxLineLength")
+ @Test
+ fun `when ChromeAutofillStatusReceive with updated information is processed state updates as expected`() =
+ runTest {
+ val viewModel = createViewModel()
+ viewModel.stateFlow.test {
+ assertEquals(
+ DEFAULT_STATE,
+ awaitItem(),
+ )
+ mutableChromeAutofillStatusFlow.update {
+ it.copy(
+ stableStatusData = DEFAULT_CHROME_AUTOFILL_DATA.copy(isAvailable = true),
+ )
+ }
+ assertEquals(
+ DEFAULT_STATE.copy(
+ chromeAutofillSettingsOptions = persistentListOf(
+ ChromeAutofillSettingsOption.Stable(enabled = false),
+ ),
+ ),
+ awaitItem(),
+ )
+ }
+ }
+
+ @Suppress("MaxLineLength")
+ @Test
+ fun `when ChromeAutofillSelected action is handled the correct NavigateToChromeAutofillSettings event is sent`() =
+ runTest {
+ val viewModel = createViewModel()
+ viewModel.eventFlow.test {
+ viewModel.trySendAction(
+ AutoFillAction.ChromeAutofillSelected(ChromeReleaseChannel.STABLE),
+ )
+ assertEquals(
+ AutoFillEvent.NavigateToChromeAutofillSettings(ChromeReleaseChannel.STABLE),
+ awaitItem(),
+ )
+ viewModel.trySendAction(
+ AutoFillAction.ChromeAutofillSelected(ChromeReleaseChannel.BETA),
+ )
+ assertEquals(
+ AutoFillEvent.NavigateToChromeAutofillSettings(ChromeReleaseChannel.BETA),
+ awaitItem(),
+ )
+ }
+ }
+
private fun createViewModel(
state: AutoFillState? = DEFAULT_STATE,
): AutoFillViewModel = AutoFillViewModel(
@@ -361,6 +422,7 @@ class AutoFillViewModelTest : BaseViewModelTest() {
settingsRepository = settingsRepository,
authRepository = authRepository,
firstTimeActionManager = firstTimeActionManager,
+ chromeThirdPartyAutofillEnabledManager = chromeThirdPartyAutofillEnabledManager,
)
}
@@ -375,4 +437,15 @@ private val DEFAULT_STATE: AutoFillState = AutoFillState(
defaultUriMatchType = UriMatchType.DOMAIN,
showAutofillActionCard = false,
activeUserId = "activeUserId",
+ chromeAutofillSettingsOptions = persistentListOf(),
+)
+
+private val DEFAULT_CHROME_AUTOFILL_DATA = ChromeThirdPartyAutoFillData(
+ isAvailable = false,
+ isThirdPartyEnabled = false,
+)
+
+private val DEFAULT_AUTOFILL_STATUS = ChromeThirdPartyAutofillStatus(
+ stableStatusData = DEFAULT_CHROME_AUTOFILL_DATA,
+ betaChannelStatusData = DEFAULT_CHROME_AUTOFILL_DATA,
)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt
index 8e9adf93ed0..0651b7381eb 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt
@@ -33,7 +33,7 @@ class BlockAutoFillScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
BlockAutoFillScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreenTest.kt
index 5350d6900e3..be29034588c 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreenTest.kt
@@ -45,7 +45,7 @@ class ExportVaultScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
ExportVaultScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreenTest.kt
index 2639160708b..d5cc08aeceb 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreenTest.kt
@@ -35,7 +35,7 @@ class FoldersScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
FoldersScreen(
viewModel = viewModel,
onNavigateToEditFolderScreen = { onNavigateToEditFolderScreenId = it },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreenTest.kt
index 1c49f515936..0b523f01288 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreenTest.kt
@@ -38,7 +38,7 @@ class FolderAddEditScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
FolderAddEditScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt
index 01ab88d3e96..4af1b2f8675 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt
@@ -38,7 +38,7 @@ class OtherScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
OtherScreen(
viewModel = viewModel,
onNavigateBack = { haveCalledNavigateBack = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt
index 090260451e5..6ff631bc343 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt
@@ -54,7 +54,7 @@ class VaultSettingsScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
VaultSettingsScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt
index 4e5db48c3c5..ec9bb5b39a5 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt
@@ -66,7 +66,7 @@ class GeneratorScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
GeneratorScreen(
viewModel = viewModel,
onNavigateToPasswordHistory = {
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreenTest.kt
index 9c5e12bd4b8..2138ed54b72 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreenTest.kt
@@ -41,7 +41,7 @@ class PasswordHistoryScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
PasswordHistoryScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt
index e0e6c056e79..6dcd39f61d3 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt
@@ -65,7 +65,7 @@ class SendScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
SendScreen(
viewModel = viewModel,
onNavigateToAddSend = { onNavigateToNewSendCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt
index 0d61aeb03fc..6090bb49aca 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt
@@ -66,7 +66,7 @@ class AddSendScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- setContentWithBackDispatcher {
+ setContent {
AddSendScreen(
viewModel = viewModel,
exitManager = exitManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt
index fa790f196d7..514d8aefb22 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt
@@ -117,7 +117,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
VaultAddEditScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToQrCodeScanScreen = { onNavigateQrCodeScanScreenCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditViewModelTest.kt
index 8983300972d..509f2cfe393 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditViewModelTest.kt
@@ -4598,6 +4598,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/util/CipherViewExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/util/CipherViewExtensionsTest.kt
index 036a88ed7e4..cbcaaad3444 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/util/CipherViewExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/addedit/util/CipherViewExtensionsTest.kt
@@ -562,6 +562,7 @@ class CipherViewExtensionsTest {
id = "mockOrganizationId-1",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreenTest.kt
index baea8e3b372..aca148a35f2 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreenTest.kt
@@ -46,7 +46,7 @@ class AttachmentsScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
AttachmentsScreen(
viewModel = viewModel,
intentManager = intentManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreenTest.kt
index fc5901cd326..a63fe8bd735 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreenTest.kt
@@ -53,7 +53,7 @@ class ImportLoginsScreenTest : BaseComposeTest() {
@Before
fun setup() {
- setContentWithBackDispatcher {
+ setContent {
ImportLoginsScreen(
onNavigateBack = { navigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt
index 41931942904..bbd069b463e 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt
@@ -77,7 +77,7 @@ class VaultItemScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
VaultItemScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt
index 2767a83e875..966951f0086 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt
@@ -117,7 +117,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
fun setUp() {
mockkStatic(String::toHostOrPathOrNull)
every { AUTOFILL_SELECTION_DATA.uri?.toHostOrPathOrNull() } returns "www.test.com"
- setContentWithBackDispatcher {
+ setContent {
VaultItemListingScreen(
viewModel = viewModel,
exitManager = exitManager,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt
index 9fcaff9bcda..a384448c2a0 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt
@@ -52,7 +52,7 @@ class ManualCodeEntryScreenTests : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
ManualCodeEntryScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreenTest.kt
index 31435b4aeda..5dd7b2375f8 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreenTest.kt
@@ -45,7 +45,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
VaultMoveToOrganizationScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationViewModelTest.kt
index abaad2e4de1..c81ed6c9cba 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationViewModelTest.kt
@@ -494,6 +494,7 @@ private val DEFAULT_USER_STATE = UserState(
id = "mockOrganizationId-1",
name = "mockOrganizationName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -501,6 +502,7 @@ private val DEFAULT_USER_STATE = UserState(
id = "mockOrganizationId-2",
name = "mockOrganizationName-2",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -508,6 +510,7 @@ private val DEFAULT_USER_STATE = UserState(
id = "mockOrganizationId-3",
name = "mockOrganizationName-3",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/util/VaultMoveToOrganizationExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/util/VaultMoveToOrganizationExtensionsTest.kt
index 900497733cd..4a2b33e6dda 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/util/VaultMoveToOrganizationExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/util/VaultMoveToOrganizationExtensionsTest.kt
@@ -106,6 +106,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
id = "mockOrganizationId-1",
name = "mockOrganizationName-1",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -113,6 +114,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
id = "mockOrganizationId-2",
name = "mockOrganizationName-2",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -120,6 +122,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
id = "mockOrganizationId-3",
name = "mockOrganizationName-3",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreenTest.kt
index 3ffe40381e4..7e4c9175583 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreenTest.kt
@@ -31,7 +31,7 @@ class QrCodeScanScreenTest : BaseComposeTest() {
@Before
fun setup() {
- composeTestRule.setContent {
+ setContent {
QrCodeScanScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt
index 7f1da9aad7f..fe197e5c8fd 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt
@@ -11,7 +11,6 @@ import androidx.compose.ui.test.hasScrollToNodeAction
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.isDialog
import androidx.compose.ui.test.isDisplayed
-import androidx.compose.ui.test.isNotDisplayed
import androidx.compose.ui.test.isPopup
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithContentDescription
@@ -99,7 +98,7 @@ class VaultScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
VaultScreen(
viewModel = viewModel,
onNavigateToVaultAddItemScreen = { onNavigateToVaultAddItemScreenCalled = true },
@@ -1276,7 +1275,6 @@ class VaultScreenTest : BaseComposeTest() {
// Verify SSH key group is displayed when showSshKeys is true
mutableStateFlow.update {
it.copy(
- showSshKeys = true,
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
sshKeyItemsCount = count,
),
@@ -1286,12 +1284,6 @@ class VaultScreenTest : BaseComposeTest() {
.onNodeWithText("SSH key")
.assertTextEquals("SSH key", count.toString())
.assertIsDisplayed()
-
- // Verify SSH key group is hidden when showSshKeys is false
- mutableStateFlow.update { it.copy(showSshKeys = false) }
- composeTestRule
- .onNodeWithText("SSH key")
- .assertIsNotDisplayed()
}
@Test
@@ -1299,7 +1291,6 @@ class VaultScreenTest : BaseComposeTest() {
// Verify SSH key vault items are displayed when showSshKeys is true
mutableStateFlow.update {
it.copy(
- showSshKeys = true,
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
noFolderItems = listOf(
VaultState.ViewState.VaultItem.SshKey(
@@ -1318,12 +1309,6 @@ class VaultScreenTest : BaseComposeTest() {
composeTestRule
.onNodeWithTextAfterScroll("mockSshKey")
.isDisplayed()
-
- // Verify SSH key vault items are hidden when showSshKeys is false
- mutableStateFlow.update { it.copy(showSshKeys = false) }
- composeTestRule
- .onNodeWithText("mockSshKey")
- .isNotDisplayed()
}
@Test
@@ -1440,7 +1425,6 @@ private val DEFAULT_STATE: VaultState = VaultState(
hasMasterPassword = true,
isRefreshing = false,
showImportActionCard = false,
- showSshKeys = false,
)
private val DEFAULT_CONTENT_VIEW_STATE: VaultState.ViewState.Content = VaultState.ViewState.Content(
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt
index d17f520b461..de8d9c3c954 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt
@@ -145,12 +145,6 @@ class VaultViewModelTest : BaseViewModelTest() {
every {
getFeatureFlagFlow(FlagKey.ImportLoginsFlow)
} returns mutableImportLoginsFeatureFlow
- every {
- getFeatureFlagFlow(FlagKey.SshKeyCipherItems)
- } returns mutableSshKeyVaultItemsEnabledFlow
- every {
- getFeatureFlag(FlagKey.SshKeyCipherItems)
- } returns mutableSshKeyVaultItemsEnabledFlow.value
}
private val reviewPromptManager: ReviewPromptManager = mockk()
@@ -246,6 +240,7 @@ class VaultViewModelTest : BaseViewModelTest() {
id = "organiationId",
name = "Test Organization",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -332,6 +327,7 @@ class VaultViewModelTest : BaseViewModelTest() {
id = "organizationId",
name = "Test Organization",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -563,6 +559,7 @@ class VaultViewModelTest : BaseViewModelTest() {
id = "testOrganizationId",
name = "Test Organization",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -579,7 +576,6 @@ class VaultViewModelTest : BaseViewModelTest() {
isIconLoadingDisabled = viewModel.stateFlow.value.isIconLoadingDisabled,
baseIconUrl = viewModel.stateFlow.value.baseIconUrl,
hasMasterPassword = true,
- showSshKeys = false,
),
)
.copy(
@@ -604,7 +600,6 @@ class VaultViewModelTest : BaseViewModelTest() {
isIconLoadingDisabled = viewModel.stateFlow.value.isIconLoadingDisabled,
baseIconUrl = viewModel.stateFlow.value.baseIconUrl,
hasMasterPassword = true,
- showSshKeys = false,
),
),
viewModel.stateFlow.value,
@@ -714,7 +709,6 @@ class VaultViewModelTest : BaseViewModelTest() {
itemTypesCount = CipherType.entries.size,
sshKeyItemsCount = 1,
),
- showSshKeys = true,
),
viewModel.stateFlow.value,
)
@@ -736,7 +730,7 @@ class VaultViewModelTest : BaseViewModelTest() {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
)
@@ -850,7 +844,7 @@ class VaultViewModelTest : BaseViewModelTest() {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
),
@@ -950,7 +944,7 @@ class VaultViewModelTest : BaseViewModelTest() {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
dialog = VaultState.DialogState.Error(
@@ -1048,7 +1042,7 @@ class VaultViewModelTest : BaseViewModelTest() {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
dialog = null,
@@ -1093,47 +1087,7 @@ class VaultViewModelTest : BaseViewModelTest() {
}
@Test
- fun `vaultDataStateFlow Loaded should exclude SSH key vault items when showSshKeys is false`() =
- runTest {
- mutableVaultDataStateFlow.tryEmit(
- value = DataState.Loaded(
- data = VaultData(
- cipherViewList = listOf(
- createMockCipherView(number = 1),
- createMockCipherView(number = 1, cipherType = CipherType.SSH_KEY),
- ),
- collectionViewList = listOf(),
- folderViewList = listOf(),
- sendViewList = listOf(),
- ),
- ),
- )
-
- val viewModel = createViewModel()
-
- assertEquals(
- createMockVaultState(
- viewState = VaultState.ViewState.Content(
- loginItemsCount = 1,
- cardItemsCount = 0,
- identityItemsCount = 0,
- secureNoteItemsCount = 0,
- favoriteItems = listOf(),
- folderItems = listOf(),
- collectionItems = listOf(),
- noFolderItems = listOf(),
- trashItemsCount = 0,
- totpItemsCount = 1,
- itemTypesCount = CipherType.entries.size - 1,
- sshKeyItemsCount = 0,
- ),
- ),
- viewModel.stateFlow.value,
- )
- }
-
- @Test
- fun `vaultDataStateFlow Loaded should include SSH key vault items when showSshKeys is true`() =
+ fun `vaultDataStateFlow Loaded should include SSH key vault items`() =
runTest {
mutableSshKeyVaultItemsEnabledFlow.value = true
mutableVaultDataStateFlow.tryEmit(
@@ -1168,7 +1122,6 @@ class VaultViewModelTest : BaseViewModelTest() {
itemTypesCount = CipherType.entries.size,
sshKeyItemsCount = 1,
),
- showSshKeys = true,
),
viewModel.stateFlow.value,
)
@@ -2096,7 +2049,6 @@ private val DEFAULT_USER_STATE = UserState(
private fun createMockVaultState(
viewState: VaultState.ViewState,
dialog: VaultState.DialogState? = null,
- showSshKeys: Boolean = false,
): VaultState =
VaultState(
appBarTitle = R.string.my_vault.asText(),
@@ -2134,5 +2086,4 @@ private fun createMockVaultState(
hasMasterPassword = true,
showImportActionCard = true,
isRefreshing = false,
- showSshKeys = showSshKeys,
)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/UserStateExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/UserStateExtensionsTest.kt
index 4f268160940..0b55258e30c 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/UserStateExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/UserStateExtensionsTest.kt
@@ -80,6 +80,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -107,6 +108,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -138,6 +140,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -169,6 +172,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -215,6 +219,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -259,6 +264,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -307,6 +313,7 @@ class UserStateExtensionsTest {
id = "organizationId",
name = "organizationName",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -386,12 +393,14 @@ class UserStateExtensionsTest {
name = "Organization B",
shouldUseKeyConnector = false,
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
role = OrganizationType.ADMIN,
),
Organization(
id = "organizationId-A",
name = "Organization A",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -443,6 +452,7 @@ class UserStateExtensionsTest {
id = "organizationId-B",
name = "Organization B",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
@@ -450,6 +460,7 @@ class UserStateExtensionsTest {
id = "organizationId-A",
name = "Organization A",
shouldManageResetPassword = false,
+ shouldManagePolicies = false,
shouldUseKeyConnector = false,
role = OrganizationType.ADMIN,
),
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensionsTest.kt
index 8219e957dd1..482204bda35 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensionsTest.kt
@@ -61,7 +61,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -99,7 +98,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -125,7 +124,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.MyVault,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -146,7 +144,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -181,7 +179,6 @@ class VaultDataExtensionsTest {
organizationName = "Mock Organization 1",
),
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -208,7 +205,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -230,7 +227,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -254,7 +250,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -279,7 +274,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -294,7 +288,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -317,7 +311,6 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -332,7 +325,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 0,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -355,7 +348,6 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -370,7 +362,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -395,7 +387,6 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -410,7 +401,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -619,7 +610,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -634,7 +624,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 2,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -659,7 +649,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -674,7 +663,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 2,
totpItemsCount = 0,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -702,7 +691,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -723,7 +711,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 100,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -758,7 +746,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
)
assertEquals(
@@ -801,7 +788,7 @@ class VaultDataExtensionsTest {
noFolderItems = listOf(),
trashItemsCount = 0,
totpItemsCount = 1,
- itemTypesCount = 4,
+ itemTypesCount = 5,
sshKeyItemsCount = 0,
),
actual,
@@ -809,7 +796,7 @@ class VaultDataExtensionsTest {
}
@Test
- fun `toViewState should exclude SSH keys if showSshKeys is false`() {
+ fun `toViewState should include SSH key vault items and type count`() {
val vaultData = VaultData(
cipherViewList = listOf(
createMockCipherView(number = 1),
@@ -827,50 +814,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = false,
- )
-
- assertEquals(
- VaultState.ViewState.Content(
- loginItemsCount = 1,
- cardItemsCount = 0,
- identityItemsCount = 0,
- secureNoteItemsCount = 0,
- // Verify SSH key vault items are not counted when showSshKeys is false.
- sshKeyItemsCount = 0,
- favoriteItems = listOf(),
- collectionItems = listOf(),
- folderItems = listOf(),
- noFolderItems = listOf(),
- trashItemsCount = 0,
- totpItemsCount = 1,
- // Verify item types count excludes CipherType.SSH_KEY when showSshKeys is false.
- itemTypesCount = 4,
- ),
- actual,
- )
- }
-
- @Test
- fun `toViewState should include SSH key vault items and type count if showSshKeys is true`() {
- val vaultData = VaultData(
- cipherViewList = listOf(
- createMockCipherView(number = 1),
- createMockCipherView(number = 2, cipherType = CipherType.SSH_KEY),
- ),
- collectionViewList = listOf(),
- folderViewList = listOf(),
- sendViewList = listOf(),
- fido2CredentialAutofillViewList = null,
- )
-
- val actual = vaultData.toViewState(
- isPremium = true,
- isIconLoadingDisabled = false,
- baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
- vaultFilterType = VaultFilterType.AllVaults,
- hasMasterPassword = true,
- showSshKeys = true,
)
assertEquals(
@@ -928,7 +871,6 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
- showSshKeys = true,
)
assertEquals(
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreenTest.kt
index 269f2dc1fc2..f9e728f931b 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreenTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreenTest.kt
@@ -48,7 +48,7 @@ class VerificationCodeScreenTest : BaseComposeTest() {
@Before
fun setUp() {
- composeTestRule.setContent {
+ setContent {
VerificationCodeScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index ef7fa81acfb..a60938ffa90 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -257,4 +257,129 @@ platform :android do
)
releaseNotes
end
+
+ # Authenticator
+ desc "Runs tests"
+ lane :checkAuthenticator do
+ gradle(tasks: ["authenticator:testDebug", "authenticator:lintDebug", "authenticator:detekt","authenticator:koverXmlReportDebug"])
+ end
+
+ desc "Apply build version information"
+ fastlane_require "time"
+ lane :setAuthenticatorBuildVersionInfo do |options|
+
+ # Read-in app build config file.
+ buildConfigPath = "../authenticator/build.gradle.kts"
+ buildConfigFile = File.open(buildConfigPath)
+ buildConfigText = buildConfigFile.read
+ buildConfigFile.close
+
+ currentVersionCode = buildConfigText.match(/versionCode = (\d+)/).captures[0]
+ currentVersionName = buildConfigText.match(/versionName = "(.+)"/).captures[0]
+
+ if options[:versionName].nil? or options[:versionName].to_s.empty?
+ puts "Fetching latest tags from origin..."
+ `git fetch --prune --no-recurse-submodules --filter=tree:0 --depth=1 --tags origin`
+ puts "Getting latest version name from previous git tag..."
+ latestTag = `git describe --tags $(git rev-list --tags --max-count=1)`.chomp()
+ puts "Using tag #{latestTag} to calculate version name..."
+ latestTag.slice!(0)
+ puts "Current version name resolved to #{latestTag}."
+
+ versionParts = latestTag.split(".")
+ currentMajor = versionParts[0]
+ currentMinor = versionParts[1]
+ currentRevision = versionParts[2]
+
+ currentDate = Time.new
+ major = currentDate.year.to_s
+ minor = currentDate.strftime "%-m"
+
+ revision = 0
+ if currentMajor == major and currentMinor == minor
+ revision = currentRevision.to_i + 1
+ end
+ nextVersionName = "#{major}.#{minor}.#{revision}"
+ else
+ nextVersionName = options[:versionName].to_s
+ end
+
+ # Replace version information.
+ puts "Setting version code to #{options[:versionCode]}."
+ buildConfigText.gsub!("versionCode = #{currentVersionCode}", "versionCode = #{options[:versionCode]}")
+ puts "Setting version name to #{nextVersionName}."
+ buildConfigText.gsub!("versionName = \"#{currentVersionName}\"", "versionName = \"#{nextVersionName}\"")
+
+ # Save changes
+ File.open(buildConfigPath, "w") { |buildConfigFile| buildConfigFile << buildConfigText }
+ end
+
+ desc "Assemble debug variants"
+ lane :buildAuthenticatorDebug do
+ gradle(
+ task: "authenticator:assemble",
+ build_type: "Debug",
+ print_command: false,
+ )
+ end
+
+ desc "Assemble and sign release APK"
+ lane :buildAuthenticatorRelease do |options|
+ gradle(
+ task: "authenticator:assemble",
+ build_type: "Release",
+ properties: {
+ "android.injected.signing.store.file" => options[:storeFile],
+ "android.injected.signing.store.password" => options[:storePassword],
+ "android.injected.signing.key.alias" => options[:keyAlias],
+ "android.injected.signing.key.password" => options[:keyPassword]
+ },
+ print_command: false,
+ )
+ end
+
+ desc "Bundle and sign release AAB"
+ lane :bundleAuthenticatorRelease do |options|
+ gradle(
+ task: "authenticator:bundle",
+ build_type: "Release",
+ properties: {
+ "android.injected.signing.store.file" => options[:storeFile],
+ "android.injected.signing.store.password" => options[:storePassword],
+ "android.injected.signing.key.alias" => options[:keyAlias],
+ "android.injected.signing.key.password" => options[:keyPassword]
+ },
+ print_command: false,
+ )
+ end
+
+ desc "Publish release AAB to Firebase"
+ lane :distributeAuthenticatorReleaseBundleToFirebase do |options|
+ release_notes = changelog_from_git_commits(
+ commits_count: 1,
+ pretty: "- %s"
+ )
+
+ puts "Release notes #{release_notes}"
+
+ firebase_app_distribution(
+ app: "1:867301491091:android:50b626dba42a361651e866",
+ android_artifact_type: "AAB",
+ android_artifact_path: "authenticator/build/outputs/bundle/release/com.bitwarden.authenticator.aab",
+ service_credentials_file: options[:serviceCredentialsFile],
+ groups: "internal-prod-group, livefront",
+ release_notes: release_notes,
+ )
+ end
+
+ desc "Publish release to Google Play Store"
+ lane :publishAuthenticatorReleaseToGooglePlayStore do |options|
+ upload_to_play_store(
+ package_name: "com.bitwarden.authenticator",
+ json_key: options[:serviceCredentialsFile],
+ track: "internal",
+ aab: "authenticator/build/outputs/bundle/release/com.bitwarden.authenticator.aab",
+ mapping: "authenticator/build/outputs/mapping/release/mapping.txt",
+ )
+ end
end
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index cb8c66c9564..ba3f0b9a9a1 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -5,6 +5,7 @@
compileSdk = "35"
targetSdk = "35"
minSdk = "29"
+minSdkBwa = "28"
# Dependency Versions
androidGradlePlugin = "8.8.1"
@@ -12,7 +13,7 @@ androidxActivity = "1.10.0"
androidXBiometrics = "1.2.0-alpha05"
androidxBrowser = "1.8.0"
androidxCamera = "1.4.1"
-androidxComposeBom = "2025.01.00"
+androidxComposeBom = "2025.02.00"
androidxCore = "1.15.0"
# Versions >= 1.5.0-alpha05 introduce breaking changes and bugs that are not suitable for
# production. Do not update until https://issuetracker.google.com/issues/355141766 is resolved.
@@ -23,26 +24,33 @@ androidxNavigation = "2.8.0"
androidxRoom = "2.6.1"
androidXSecurityCrypto = "1.1.0-alpha06"
androidxSplash = "1.1.0-rc01"
+androidxTest = "1.6.2"
+androidxTestRules = "1.6.1"
androidXAppCompat = "1.7.0"
androdixAutofill = "1.1.0"
androidxWork = "2.10.0"
bitwardenSdk = "1.0.0-20250213.181812-113"
-crashlytics = "3.0.2"
+crashlytics = "3.0.3"
detekt = "1.23.7"
-firebaseBom = "33.8.0"
+firebaseBom = "33.9.0"
+espresso = "3.6.1"
+fastlaneScreengrab = "2.1.1"
glide = "1.0.0-beta01"
+googleGuava = "33.4.0-jre"
+googleProtoBufJava = "4.29.3"
+googleProtoBufPlugin = "0.9.4"
googleServices = "4.4.2"
googleReview = "2.0.2"
-hilt = "2.53.1"
+hilt = "2.55"
junit5 = "5.11.3"
jvmTarget = "17"
# kotlin and ksp **must** use compatible versions, do not update either without the other.
-kotlin = "2.1.0"
+kotlin = "2.1.10"
kotlinxCollectionsImmutable = "0.3.8"
kotlinxCoroutines = "1.10.1"
kotlinxSerialization = "1.8.0"
kotlinxKover = "0.9.1"
-ksp = "2.1.0-1.0.29"
+ksp = "2.1.10-1.0.30"
mockk = "1.13.13"
okhttp = "4.12.0"
retrofitBom = "2.11.0"
@@ -52,6 +60,7 @@ timber = "5.0.1"
turbine = "1.2.0"
zxcvbn4j = "1.9.0"
zxing = "3.5.3"
+testng = "7.10.2"
[libraries]
# Format: -
@@ -86,18 +95,26 @@ androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidx
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "androidxRoom" }
androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "androidXSecurityCrypto" }
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidxSplash" }
+androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidxTest" }
+androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidxTestRules" }
+androidx-test-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "androidxWork" }
bitwarden-sdk = { module = "com.bitwarden:sdk-android-temp", version.ref = "bitwardenSdk" }
bumptech-glide = { module = "com.github.bumptech.glide:compose", version.ref = "glide" }
detekt-detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
detekt-detekt-rules = { module = "io.gitlab.arturbosch.detekt:detekt-rules-libraries", version.ref = "detekt" }
+fastlane-screengrab = { module = "tools.fastlane:screengrab", version.ref = "fastlaneScreengrab" }
google-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
google-firebase-cloud-messaging = { module = "com.google.firebase:firebase-messaging-ktx" }
google-firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" }
+google-guava = { module = "com.google.guava:guava", version.ref = "googleGuava" }
google-hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
google-hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" }
google-hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
-google-play-review = { module = "com.google.android.play:review", version.ref = "googleReview"}
+google-play-review = { module = "com.google.android.play:review", version.ref = "googleReview" }
+google-protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.ref = "googleProtoBufJava" }
+# Included so that Renovate tracks updates since protoc is not referenced directly in `dependency {}` blocks.
+google-protobuf-protoc = { module = "com.google.protobuf:protoc", version.ref = "googleProtoBufJava" }
junit-junit5 = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit5" }
junit-vintage = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5" }
kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinxCollectionsImmutable" }
@@ -105,6 +122,7 @@ kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutine
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
+mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" }
mockk-mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
nulab-zxcvbn4j = { module = "com.nulab-inc:zxcvbn", version.ref = "zxcvbn4j" }
robolectric-robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
@@ -117,12 +135,14 @@ square-retrofit-kotlinx-serialization = { module = "com.squareup.retrofit2:conve
square-turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
zxing-zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" }
+testng = { group = "org.testng", name = "testng", version.ref = "testng" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
+google-protobuf = { id = "com.google.protobuf", version.ref = "googleProtoBufPlugin" }
google-services = { id = "com.google.gms.google-services", version.ref = "googleServices" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }