Repository: bitwarden/android
Pull request #5216: [PM-21354] Migrate ColorExtensions and its tests to ui module 
Author: login: SaintPatrck
Created: 2025-05-16T19:38:02Z | Merged: 2025-05-20T15:28:50Z

## 🎟️ Tracking

PM-21354

## 📔 Objective

This commit moves the `ColorExtensions.kt` file and its corresponding test file `ColorExtensionsTest.kt` from the `app` module to the `ui` module.

## ⏰ Reminders before review

- Contributor guidelines followed
- All formatters and local linters executed and passed
- Written new unit and / or integration tests where applicable
- Protected functional changes with optionality (feature flags)
- Used internationalization (i18n) for all UI strings
- CI builds passed
- Communicated to DevOps any deployment requirements
- Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

## 🦮 Reviewer guidelines

<!-- Suggested interactions but feel free to use (or not) as you desire! -->

- 👍 (`:+1:`) or similar for great changes
- 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info
- ❓ (`:question:`) for questions
- 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
- 🎨 (`:art:`) for suggestions / improvements
- ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention
- 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt
- ⛏ (`:pick:`) for minor or nitpick changes



Diff:
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountActionItem.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountActionItem.kt
index c9c7768ddc8..3e6a58822db 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountActionItem.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountActionItem.kt
@@ -14,10 +14,10 @@ import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
+import com.bitwarden.ui.platform.base.util.toSafeOverlayColor
 import com.bitwarden.ui.platform.base.util.toUnscaledTextUnit
 import com.bitwarden.ui.platform.theme.BitwardenTheme
 import com.x8bit.bitwarden.R
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
 import com.x8bit.bitwarden.ui.platform.components.button.color.bitwardenStandardIconButtonColors
 import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
 
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt
index 6ee6bd7eb9a..cef679bcd8e 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt
@@ -51,10 +51,10 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.bitwarden.ui.platform.base.util.lowercaseWithCurrentLocal
 import com.bitwarden.ui.platform.base.util.scrolledContainerBackground
+import com.bitwarden.ui.platform.base.util.toSafeOverlayColor
 import com.bitwarden.ui.platform.base.util.toUnscaledTextUnit
 import com.bitwarden.ui.platform.theme.BitwardenTheme
 import com.x8bit.bitwarden.R
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
 import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLogoutConfirmationDialog
 import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenRemovalConfirmationDialog
 import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog
diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts
index 3fb766f8661..587d1643527 100644
--- a/ui/build.gradle.kts
+++ b/ui/build.gradle.kts
@@ -30,6 +30,11 @@ android {
         sourceCompatibility(libs.versions.jvmTarget.get())
         targetCompatibility(libs.versions.jvmTarget.get())
     }
+    testOptions {
+        // Required for Robolectric
+        unitTests.isIncludeAndroidResources = true
+        unitTests.isReturnDefaultValues = true
+    }
     kotlinOptions {
         jvmTarget = libs.versions.jvmTarget.get()
     }
@@ -57,11 +62,16 @@ dependencies {
     implementation(libs.kotlinx.serialization)
     implementation(libs.kotlinx.coroutines.core)
 
+    // For now we are restricted to running Compose tests for debug builds only
+    debugImplementation(libs.androidx.compose.ui.test.manifest)
+    debugImplementation(libs.androidx.compose.ui.tooling)
+
     testImplementation(platform(libs.junit.bom))
     testImplementation(libs.junit.junit5)
     testRuntimeOnly(libs.junit.platform.launcher)
     testImplementation(libs.junit.vintage)
     testImplementation(libs.mockk.mockk)
+    testImplementation(libs.robolectric.robolectric)
 
     testFixturesImplementation(libs.androidx.activity.compose)
     testFixturesImplementation(libs.androidx.compose.ui.test)
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ColorExtensions.kt b/ui/src/main/java/com/bitwarden/ui/platform/base/util/ColorExtensions.kt
similarity index 97%
rename from app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ColorExtensions.kt
rename to ui/src/main/java/com/bitwarden/ui/platform/base/util/ColorExtensions.kt
index a99db51c7d9..f02dd88c845 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ColorExtensions.kt
+++ b/ui/src/main/java/com/bitwarden/ui/platform/base/util/ColorExtensions.kt
@@ -1,4 +1,4 @@
-package com.x8bit.bitwarden.ui.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt b/ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
similarity index 58%
rename from app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt
rename to ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
index 6b2e74c371b..05617f27259 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/util/ColorExtensionsTest.kt
+++ b/ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
@@ -1,62 +1,73 @@
-package com.x8bit.bitwarden.data.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import com.bitwarden.ui.platform.base.BaseComposeTest
 import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
 import com.bitwarden.ui.platform.theme.BitwardenTheme
-import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
-import com.x8bit.bitwarden.ui.platform.base.util.isLightOverlayRequired
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 
-class ColorExtensionsTest : BitwardenComposeTest() {
+class ColorExtensionsTest : BaseComposeTest() {
+
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance below the light threshold should return true`() {
-        assertTrue(Color.Blue.isLightOverlayRequired)
+        Assert.assertTrue(Color.Companion.Blue.isLightOverlayRequired)
     }
 
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance above the light threshold should return false`() {
-        assertFalse(Color.Yellow.isLightOverlayRequired)
+        Assert.assertFalse(Color.Companion.Yellow.isLightOverlayRequired)
     }
 
     @Test
     fun `toSafeOverlayColor for a dark color in light mode should use the surface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a dark color in dark mode should use the onSurface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in light mode should use the onSurface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in dark mode should use the surface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
+
+    @Suppress("LongParameterList")
+    fun setContent(
+        theme: AppTheme = AppTheme.DEFAULT,
+        test: @Composable () -> Unit,
+    ) {
+        setTestContent {
+            BitwardenTheme(
+                theme = theme,
+                content = test,
+            )
+        }
+    }
 }


Reviews:
user: login: david-livefront
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-19T21:40:37Z
user: login: david-livefront
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-19T21:47:48Z
user: login: SaintPatrck
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T21:52:48Z
user: login: SaintPatrck
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T13:40:29Z
user: login: david-livefront
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:15:49Z

Review comments:
diff_hunk: @@ -1,62 +1,73 @@
-package com.x8bit.bitwarden.data.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import com.bitwarden.ui.platform.base.BaseComposeTest
 import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
 import com.bitwarden.ui.platform.theme.BitwardenTheme
-import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
-import com.x8bit.bitwarden.ui.platform.base.util.isLightOverlayRequired
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 
-class ColorExtensionsTest : BitwardenComposeTest() {
+class ColorExtensionsTest : BaseComposeTest() {
+
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance below the light threshold should return true`() {
-        assertTrue(Color.Blue.isLightOverlayRequired)
+        Assert.assertTrue(Color.Companion.Blue.isLightOverlayRequired)
path: ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
user: login: david-livefront
body: Was this something the IDE did?
created_at: 2025-05-19T21:40:37Z
author_association: COLLABORATOR
diff_hunk: @@ -1,62 +1,73 @@
-package com.x8bit.bitwarden.data.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import com.bitwarden.ui.platform.base.BaseComposeTest
 import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
 import com.bitwarden.ui.platform.theme.BitwardenTheme
-import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
-import com.x8bit.bitwarden.ui.platform.base.util.isLightOverlayRequired
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 
-class ColorExtensionsTest : BitwardenComposeTest() {
+class ColorExtensionsTest : BaseComposeTest() {
+
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance below the light threshold should return true`() {
-        assertTrue(Color.Blue.isLightOverlayRequired)
+        Assert.assertTrue(Color.Companion.Blue.isLightOverlayRequired)
     }
 
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance above the light threshold should return false`() {
-        assertFalse(Color.Yellow.isLightOverlayRequired)
+        Assert.assertFalse(Color.Companion.Yellow.isLightOverlayRequired)
     }
 
     @Test
     fun `toSafeOverlayColor for a dark color in light mode should use the surface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a dark color in dark mode should use the onSurface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in light mode should use the onSurface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in dark mode should use the surface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
+
+    @Suppress("LongParameterList")
+    fun setContent(
+        theme: AppTheme = AppTheme.DEFAULT,
path: ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
user: login: david-livefront
body: Now that the `BitwardenTheme` is in the UI package, can we move the theme stuff lower in the test classes and place the `BitwardenTheme` inside `BaseComposeTest`?
created_at: 2025-05-19T21:47:48Z
author_association: COLLABORATOR
diff_hunk: @@ -1,62 +1,73 @@
-package com.x8bit.bitwarden.data.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import com.bitwarden.ui.platform.base.BaseComposeTest
 import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
 import com.bitwarden.ui.platform.theme.BitwardenTheme
-import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
-import com.x8bit.bitwarden.ui.platform.base.util.isLightOverlayRequired
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 
-class ColorExtensionsTest : BitwardenComposeTest() {
+class ColorExtensionsTest : BaseComposeTest() {
+
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance below the light threshold should return true`() {
-        assertTrue(Color.Blue.isLightOverlayRequired)
+        Assert.assertTrue(Color.Companion.Blue.isLightOverlayRequired)
path: ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
user: login: SaintPatrck
body: Yes. It doesn't this randomly when tests are moved. Does something similar to Kdoc too. 😞 
created_at: 2025-05-19T21:52:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,62 +1,73 @@
-package com.x8bit.bitwarden.data.platform.base.util
+package com.bitwarden.ui.platform.base.util
 
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import com.bitwarden.ui.platform.base.BaseComposeTest
 import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
 import com.bitwarden.ui.platform.theme.BitwardenTheme
-import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
-import com.x8bit.bitwarden.ui.platform.base.util.isLightOverlayRequired
-import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 
-class ColorExtensionsTest : BitwardenComposeTest() {
+class ColorExtensionsTest : BaseComposeTest() {
+
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance below the light threshold should return true`() {
-        assertTrue(Color.Blue.isLightOverlayRequired)
+        Assert.assertTrue(Color.Companion.Blue.isLightOverlayRequired)
     }
 
     @Suppress("MaxLineLength")
     @Test
     fun `isLightOverlayRequired for a color with luminance above the light threshold should return false`() {
-        assertFalse(Color.Yellow.isLightOverlayRequired)
+        Assert.assertFalse(Color.Companion.Yellow.isLightOverlayRequired)
     }
 
     @Test
     fun `toSafeOverlayColor for a dark color in light mode should use the surface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a dark color in dark mode should use the onSurface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Blue.toSafeOverlayColor(),
+                Color.Companion.Blue.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in light mode should use the onSurface color`() =
         setContent(theme = AppTheme.LIGHT) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.text.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
 
     @Test
     fun `toSafeOverlayColor for a light color in dark mode should use the surface color`() =
         setContent(theme = AppTheme.DARK) {
-            assertEquals(
+            Assert.assertEquals(
                 BitwardenTheme.colorScheme.background.primary,
-                Color.Yellow.toSafeOverlayColor(),
+                Color.Companion.Yellow.toSafeOverlayColor(),
             )
         }
+
+    @Suppress("LongParameterList")
+    fun setContent(
+        theme: AppTheme = AppTheme.DEFAULT,
path: ui/src/test/kotlin/com/bitwarden/ui/platform/base/util/ColorExtensionsTest.kt
user: login: SaintPatrck
body: Yup. That'll be in an upcoming PR. 🚀 
created_at: 2025-05-20T13:40:29Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-16T19:44:12Z
body: ![Logo](https://cdn.ast.checkmarx.net/integrations/logo/Checkmarx.png)
**Checkmarx One – Scan Summary & Details** – [70ede47a\-b00c\-4406\-b0ec\-8988539dac16](https://ast.checkmarx.net/projects/7b48c130-9c07-4ac2-a6dd-15ed4933d967/scans?id=70ede47a-b00c-4406-b0ec-8988539dac16&branch=ui-module%2Fcolor-extensions)
### Great job, no security vulnerabilities found in this Pull Request

author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-05-16T20:07:41Z
body: ## [Codecov](https://app.codecov.io/gh/bitwarden/android/pull/5216?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=bitwarden) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 82.45%. Comparing base [(`4895f2a`)](https://app.codecov.io/gh/bitwarden/android/commit/4895f2a18a8a97fd9831633df5eddb837754c933?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=bitwarden) to head [(`f7b1f20`)](https://app.codecov.io/gh/bitwarden/android/commit/f7b1f20737999f9e6660c9a89ff7261f96f17e18?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=bitwarden).
> Report is 2 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #5216      +/-   ##
==========================================
- Coverage   82.53%   82.45%   -0.09%     
==========================================
  Files         688      693       +5     
  Lines       51207    51412     +205     
  Branches     6931     6931              
==========================================
+ Hits        42264    42390     +126     
- Misses       6635     6714      +79     
  Partials     2308     2308              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/bitwarden/android/pull/5216?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=bitwarden).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=bitwarden).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE