Updated copy on about page to include bitwarden copyright information (#847)

This commit is contained in:
Joshua Queen 2024-01-29 14:39:50 -05:00 committed by Álison Fernandes
parent 8cb28fc90e
commit 1ffd233e7e
4 changed files with 76 additions and 17 deletions

View file

@ -203,7 +203,7 @@ private fun ContentColumn(
) {
Text(
modifier = Modifier.padding(end = 16.dp),
text = "© Bitwarden Inc. 2015-2023",
text = state.copyrightInfo.invoke(),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface,
)

View file

@ -15,6 +15,8 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.parcelize.Parcelize
import java.time.Clock
import java.time.Year
import javax.inject.Inject
private const val KEY_STATE = "state"
@ -26,8 +28,9 @@ private const val KEY_STATE = "state"
class AboutViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
private val clipboardManager: BitwardenClipboardManager,
private val clock: Clock,
) : BaseViewModel<AboutState, AboutEvent, AboutAction>(
initialState = savedStateHandle[KEY_STATE] ?: INITIAL_STATE,
initialState = savedStateHandle[KEY_STATE] ?: createInitialState(clock = clock),
) {
init {
stateFlow
@ -68,7 +71,9 @@ class AboutViewModel @Inject constructor(
}
private fun handleVersionClick() {
clipboardManager.setText(text = state.version)
clipboardManager.setText(
text = state.copyrightInfo.concat("\n\n".asText()).concat(state.version),
)
}
private fun handleWebVaultClick() {
@ -76,12 +81,21 @@ class AboutViewModel @Inject constructor(
}
companion object {
private val INITIAL_STATE: AboutState = AboutState(
version = R.string.version
.asText()
.concat(": ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})".asText()),
isSubmitCrashLogsEnabled = false,
)
/**
* Create initial state for the About View model.
*/
fun createInitialState(clock: Clock): AboutState {
val currentYear = Year.now(clock).value
val copyrightInfo = "© Bitwarden Inc. 2015-$currentYear".asText()
return AboutState(
version = R.string.version
.asText()
.concat(": ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})".asText()),
isSubmitCrashLogsEnabled = false,
copyrightInfo = copyrightInfo,
)
}
}
}
@ -92,6 +106,7 @@ class AboutViewModel @Inject constructor(
data class AboutState(
val version: Text,
val isSubmitCrashLogsEnabled: Boolean,
val copyrightInfo: Text,
) : Parcelable
/**

View file

@ -10,6 +10,7 @@ import androidx.compose.ui.test.onAllNodesWithText
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 androidx.core.net.toUri
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
@ -26,6 +27,10 @@ import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import java.time.Clock
import java.time.Instant
import java.time.Year
import java.time.ZoneOffset
class AboutScreenTest : BaseComposeTest() {
private var haveCalledNavigateBack = false
@ -34,6 +39,7 @@ class AboutScreenTest : BaseComposeTest() {
AboutState(
version = "Version: 1.0.0 (1)".asText(),
isSubmitCrashLogsEnabled = false,
copyrightInfo = "".asText(),
),
)
private val mutableEventFlow = bufferedMutableSharedFlow<AboutEvent>()
@ -199,4 +205,18 @@ class AboutScreenTest : BaseComposeTest() {
composeTestRule.onNodeWithText("Version: 1.1.0 (2)").assertIsDisplayed()
}
@Test
fun `copyright info should update according to the state`() = runTest {
val fixedClock = Clock.fixed(Instant.parse("2024-01-25T00:00:00Z"), ZoneOffset.UTC)
val currentYear = Year.now(fixedClock).value
mutableStateFlow.update {
it.copy(copyrightInfo = "© Bitwarden Inc. 2015-$currentYear".asText())
}
composeTestRule.onNodeWithText("© Bitwarden Inc. 2015-$currentYear")
.performScrollTo()
.assertIsDisplayed()
}
}

View file

@ -2,9 +2,11 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.about
import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import com.x8bit.bitwarden.BuildConfig
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.concat
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
@ -15,6 +17,10 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.time.Clock
import java.time.Instant
import java.time.Year
import java.time.ZoneId
class AboutViewModelTest : BaseViewModelTest() {
@ -22,7 +28,7 @@ class AboutViewModelTest : BaseViewModelTest() {
@Test
fun `on BackClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(AboutAction.BackClick)
assertEquals(AboutEvent.NavigateBack, awaitItem())
@ -66,14 +72,24 @@ class AboutViewModelTest : BaseViewModelTest() {
}
@Test
fun `on VersionClick should call setText on the ClipboardManager`() {
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
every { clipboardManager.setText(text = "0".asText()) } just runs
fun `on VersionClick should call setText on the ClipboardManager with specific Text`() {
val versionName = BuildConfig.VERSION_NAME
val versionCode = BuildConfig.VERSION_CODE
val expectedText = "© Bitwarden Inc. 2015-"
.asText()
.concat(Year.now(fixedClock).value.toString().asText())
.concat("\n\n".asText())
.concat(
"Version: $versionName ($versionCode)".asText(),
)
every { clipboardManager.setText(expectedText, true, null) } just runs
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
viewModel.trySendAction(AboutAction.VersionClick)
verify(exactly = 1) {
clipboardManager.setText(text = "0".asText())
clipboardManager.setText(expectedText, true, null)
}
}
@ -91,10 +107,18 @@ class AboutViewModelTest : BaseViewModelTest() {
): AboutViewModel = AboutViewModel(
savedStateHandle = SavedStateHandle().apply { set("state", state) },
clipboardManager = clipboardManager,
clock = fixedClock,
)
}
private val DEFAULT_ABOUT_STATE: AboutState = AboutState(
version = "0".asText(),
isSubmitCrashLogsEnabled = false,
private val fixedClock = Clock.fixed(
Instant.parse("2024-01-25T10:15:30.00Z"),
ZoneId.systemDefault(),
)
private val DEFAULT_ABOUT_STATE: AboutState = AboutState(
version = "Version: 1.0.0 (1)".asText(),
isSubmitCrashLogsEnabled = false,
copyrightInfo = "© Bitwarden Inc. 2015-"
.asText()
.concat(Year.now(fixedClock).value.toString().asText()),
)