Adding suggestions

This commit is contained in:
ifernandezdiaz
2025-07-22 16:52:53 -03:00
parent b6e90e487b
commit b1a74c6fae
12 changed files with 39 additions and 28 deletions

View File

@@ -113,8 +113,8 @@ jobs:
strategy:
fail-fast: false
matrix:
variant: [ "prod", "dev" ]
artifact: [ "apk", "aab" ]
variant: ["prod", "dev"]
artifact: ["apk", "aab"]
steps:
- name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -658,11 +658,6 @@ jobs:
run: |
npm i -g saucectl
- name: Log in to Azure
uses: Azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
env:
ACCOUNT_NAME: bitwardenci
@@ -676,7 +671,7 @@ jobs:
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name google-services.json --file ${{ github.workspace }}/app/src/standardRelease/google-services.json --output none
- name: Log in to Azure (Bitwarden)
- name: Log in to Azure
uses: bitwarden/gh-actions/azure-login@main
with:
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

View File

@@ -248,6 +248,27 @@ The following is a list of additional third-party dependencies used as part of t
- Purpose: A small testing library for kotlinx.coroutine's Flow.
- License: Apache 2.0
- **AndroidX Espresso Core**
- https://developer.android.com/jetpack/androidx/releases/espresso
- Purpose: UI testing framework for Android.
- License: Apache 2.0
- **AndroidX JUnit KTX**
- https://developer.android.com/jetpack/androidx/releases/junit
- Purpose: Kotlin extensions for JUnit-based Android tests.
- License: Apache 2.0
- **AndroidX UIAutomator**
- https://developer.android.com/training/testing/other-components/ui-automator
- Purpose: UI testing across multiple apps.
- License: Apache 2.0
- **AndroidX Compose UI Test JUnit4 (Android)**
- https://developer.android.com/jetpack/androidx/releases/compose-ui
- Purpose: Compose UI testing for Android using JUnit4.
- License: Apache 2.0
### CI/CD Dependencies
The following is a list of additional third-party dependencies used as part of the CI/CD workflows. These are not present in the final packaged application.

View File

@@ -47,6 +47,7 @@ android {
namespace = "com.x8bit.bitwarden"
compileSdk = libs.versions.compileSdk.get().toInt()
// Required for SauceLabs integration
testBuildType = "release"
room {
@@ -299,11 +300,11 @@ dependencies {
testImplementation(libs.mockk.mockk)
testImplementation(libs.robolectric.robolectric)
testImplementation(libs.square.turbine)
androidTestImplementation(libs.androidx.uiautomator)
androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.androidx.junit.ktx)
androidTestImplementation(libs.androidx.ui.test.junit4.android)
androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(libs.androidx.uiautomator)
}
tasks {

View File

@@ -7,13 +7,13 @@ import java.nio.charset.StandardCharsets
object TestDataReader {
fun getTestData(fileName: String): TestData {
val context = InstrumentationRegistry.getInstrumentation().context.assets
val inputStream: InputStream = context.open(fileName)
val size = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
inputStream.close()
val jsonString = String(buffer, StandardCharsets.UTF_8)
val assets = InstrumentationRegistry.getInstrumentation().context.assets
val jsonString = assets
.open(fileName)
.use { inputStream ->
inputStream.bufferedReader(StandardCharsets.UTF_8)
.readText()
}
return Json.decodeFromString<TestData>(jsonString)
}
}

View File

@@ -27,7 +27,7 @@ abstract class Page(protected val composeTestRule: ComposeTestRule) {
*/
protected fun getElement(testTag: String): SemanticsNodeInteraction {
waitForIdle()
waitUntil(TIMEOUT_MILLIS) {
waitUntil() {
try {
composeTestRule.onNodeWithTag(testTag).assertExists()
true
@@ -40,7 +40,7 @@ abstract class Page(protected val composeTestRule: ComposeTestRule) {
protected fun getElementByText(text: String): SemanticsNodeInteraction {
waitForIdle()
waitUntil(TIMEOUT_MILLIS) {
waitUntil() {
try {
composeTestRule.onNodeWithText(text).assertExists()
true
@@ -65,7 +65,7 @@ abstract class Page(protected val composeTestRule: ComposeTestRule) {
* @param condition The condition to wait for
*/
protected fun waitUntil(
timeoutMillis: Long,
timeoutMillis: Long = TIMEOUT_MILLIS,
condition: () -> Boolean,
) {
composeTestRule.waitUntil(timeoutMillis) { condition() }

View File

@@ -8,11 +8,11 @@ import e2e.pageObjects.Page
class EnvironmentSettingsPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
private val serverURLField by lazy { getElement("ServerUrlEntry") }
private val serverUrlField by lazy { getElement("ServerUrlEntry") }
private val saveButton by lazy { getElement("SaveButton") }
fun setupEnvironment(url: String): LoginPage {
serverURLField
serverUrlField
.performClick()
.performTextInput(url)
saveButton.performClick()

View File

@@ -13,7 +13,6 @@ import e2e.pageObjects.vault.VaultPage
*/
class LoginPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val emailField by lazy { getElement("EmailAddressEntry") }
private val masterPasswordField by lazy { getElement("MasterPasswordEntry") }
private val continueButton by lazy { getElement("ContinueButton") }

View File

@@ -7,7 +7,6 @@ import e2e.pageObjects.Page
class MainPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val loginButton by lazy { getElement("ChooseLoginButton") }
private val createAccountButton by lazy { getElement("ChooseAccountCreationButton") }

View File

@@ -7,7 +7,6 @@ import e2e.pageObjects.settings.accountSecurity.AccountSecurityPage
class SettingsPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val accountSecurityButton by lazy { getElement("AccountSecuritySettingsButton") }
/**

View File

@@ -13,7 +13,6 @@ import e2e.pageObjects.vault.UnlockVaultPage
*/
class AccountSecurityPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val lockNowLabel by lazy { getElement("LockNowLabel") }
/**

View File

@@ -8,7 +8,6 @@ import e2e.pageObjects.Page
class UnlockVaultPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val passwordEntryTag by lazy { getElement("MasterPasswordEntry") }
private val unlockVaultButtonTag by lazy { getElement("UnlockVaultButton") }

View File

@@ -8,7 +8,6 @@ import e2e.pageObjects.settings.SettingsPage
class VaultPage(composeTestRule: ComposeTestRule) : Page(composeTestRule) {
// UI Elements
private val settingsMenuButton by lazy { getElement("SettingsTab") }
private val addItemButton by lazy { getElement("AddItemButton") }