mirror of
https://github.com/bitwarden/android.git
synced 2026-10-22 11:02:51 -05:00
PM-37232: Bug: Update error states for the Send and VaultAddEdit Screens (#7098)
This commit is contained in:
1 parent
b6a0838dba
commit
141ec500b8
4 files changed
+149
-88
No files matched your search
@@ -265,11 +265,19 @@ class SendViewModel @Inject constructor(
|
||||
private fun handleSendDataReceive(action: SendAction.Internal.SendDataReceive) {
|
||||
when (val dataState = action.sendDataState) {
|
||||
is DataState.Error -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = SendState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
mutableStateFlow.update { state ->
|
||||
state.copy(
|
||||
viewState = dataState
|
||||
.data
|
||||
?.toViewState(
|
||||
baseWebSendUrl = environmentRepo
|
||||
.environment
|
||||
.environmentUrlData
|
||||
.baseWebSendUrl,
|
||||
)
|
||||
?: SendState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
dialogState = null,
|
||||
isRefreshing = false,
|
||||
)
|
||||
@@ -279,9 +287,7 @@ class SendViewModel @Inject constructor(
|
||||
is DataState.NoNetwork,
|
||||
is DataState.Loaded,
|
||||
-> {
|
||||
val data = dataState
|
||||
.data
|
||||
?: SendData(sendViewList = emptyList())
|
||||
val data = dataState.data ?: SendData(sendViewList = emptyList())
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = data.toViewState(
|
||||
|
||||
+28
-35
@@ -2164,26 +2164,29 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
private fun handleVaultDataReceive(action: VaultAddEditAction.Internal.VaultDataReceive) {
|
||||
when (val vaultDataState = action.vaultData) {
|
||||
is DataState.Error -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = VaultAddEditState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is DataState.Loaded -> {
|
||||
viewModelScope.launch {
|
||||
sendAction(
|
||||
VaultAddEditAction.Internal.DetermineContentStateResultReceive(
|
||||
vaultAddEditState = state.determineContentState(
|
||||
vaultData = vaultDataState.data,
|
||||
userData = action.userData,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
vaultDataState
|
||||
.data?.let {
|
||||
viewModelScope.launch {
|
||||
sendAction(
|
||||
VaultAddEditAction.Internal.DetermineContentStateResultReceive(
|
||||
vaultAddEditState = state.determineContentState(
|
||||
vaultData = it,
|
||||
userData = action.userData,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
?: run {
|
||||
// No data to display, so let's just show the error state
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = VaultAddEditState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataState.Loading -> {
|
||||
@@ -2196,24 +2199,14 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
is DataState.NoNetwork -> {
|
||||
is DataState.NoNetwork,
|
||||
is DataState.Pending,
|
||||
is DataState.Loaded,
|
||||
-> {
|
||||
viewModelScope.launch {
|
||||
sendAction(
|
||||
VaultAddEditAction.Internal.DetermineContentStateResultReceive(
|
||||
state.determineContentState(
|
||||
vaultData = vaultDataState.data,
|
||||
userData = action.userData,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is DataState.Pending -> {
|
||||
viewModelScope.launch {
|
||||
sendAction(
|
||||
VaultAddEditAction.Internal.DetermineContentStateResultReceive(
|
||||
state.determineContentState(
|
||||
vaultAddEditState = state.determineContentState(
|
||||
vaultData = vaultDataState.data,
|
||||
userData = action.userData,
|
||||
),
|
||||
|
||||
+50
-17
@@ -48,6 +48,7 @@ import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@Suppress("LargeClass")
|
||||
class SendViewModelTest : BaseViewModelTest() {
|
||||
@@ -550,26 +551,58 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
assertEquals(initialState.copy(dialogState = null), viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `VaultRepository SendData Error should update view state to Error`() = runTest {
|
||||
val dialogState = SendState.DialogState.Loading(BitwardenString.syncing.asText())
|
||||
val viewModel = createViewModel(state = DEFAULT_STATE.copy(dialogState = dialogState))
|
||||
fun `VaultRepository SendData Error should update view state to Error when there is no data`() =
|
||||
runTest {
|
||||
val dialogState = SendState.DialogState.Loading(BitwardenString.syncing.asText())
|
||||
val viewModel = createViewModel(state = DEFAULT_STATE.copy(dialogState = dialogState))
|
||||
|
||||
viewModel.eventFlow.test {
|
||||
mutableSendDataFlow.value = DataState.Error(Throwable("Fail"))
|
||||
viewModel.eventFlow.test {
|
||||
mutableSendDataFlow.value = DataState.Error(Throwable("Fail"))
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
viewState = SendState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
dialogState = null,
|
||||
isRefreshing = false,
|
||||
),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
viewState = SendState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `VaultRepository SendData Error should update view state to data view state when there is data`() =
|
||||
runTest {
|
||||
val dialogState = SendState.DialogState.Loading(BitwardenString.syncing.asText())
|
||||
val viewModel = createViewModel(state = DEFAULT_STATE.copy(dialogState = dialogState))
|
||||
val viewState = mockk<SendState.ViewState.Content>()
|
||||
val sendData = mockk<SendData> {
|
||||
every {
|
||||
toViewState(Environment.Us.environmentUrlData.baseWebSendUrl)
|
||||
} returns viewState
|
||||
}
|
||||
|
||||
viewModel.eventFlow.test {
|
||||
mutableSendDataFlow.value = DataState.Error(
|
||||
error = Throwable("Fail"),
|
||||
data = sendData,
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
viewState = viewState,
|
||||
dialogState = null,
|
||||
isRefreshing = false,
|
||||
),
|
||||
dialogState = null,
|
||||
isRefreshing = false,
|
||||
),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `VaultRepository SendData Loaded should update view state`() = runTest {
|
||||
@@ -656,7 +689,7 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.trySendAction(SendAction.RefreshPull)
|
||||
advanceTimeBy(300)
|
||||
advanceTimeBy(300.milliseconds)
|
||||
verify(exactly = 1) {
|
||||
vaultRepo.sync(forced = false)
|
||||
}
|
||||
@@ -671,7 +704,7 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
} returns false
|
||||
|
||||
viewModel.trySendAction(SendAction.RefreshPull)
|
||||
advanceTimeBy(300)
|
||||
advanceTimeBy(300.milliseconds)
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
isRefreshing = false,
|
||||
|
||||
+57
-28
@@ -545,6 +545,40 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vault data Error with data should determine the content state from the available data`() =
|
||||
runTest {
|
||||
val stateWithName = createVaultAddItemState(
|
||||
commonContentViewState = createCommonContentViewState(name = "mockName-1"),
|
||||
)
|
||||
mutableVaultDataFlow.value = DataState.Error(
|
||||
error = Throwable("Fail"),
|
||||
data = createVaultData(),
|
||||
)
|
||||
val viewModel = createAddVaultItemViewModel(
|
||||
createSavedStateHandleWithState(
|
||||
state = stateWithName,
|
||||
vaultAddEditType = VaultAddEditType.AddItem,
|
||||
vaultItemCipherType = VaultItemCipherType.LOGIN,
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(stateWithName, viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vault data Error without data should update view state to Error`() = runTest {
|
||||
mutableVaultDataFlow.value = DataState.Error(error = Throwable("Fail"))
|
||||
val viewModel = createAddVaultItemViewModel()
|
||||
|
||||
assertEquals(
|
||||
VaultAddEditState.ViewState.Error(
|
||||
message = BitwardenString.generic_error_message.asText(),
|
||||
),
|
||||
viewModel.stateFlow.value.viewState,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `CloseClick should emit NavigateBack`() = runTest {
|
||||
val viewModel = createAddVaultItemViewModel()
|
||||
@@ -6526,40 +6560,36 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
initialState: VaultAddEditState,
|
||||
type: CustomFieldType,
|
||||
) {
|
||||
lateinit var expectedCustomField: VaultAddEditState.Custom
|
||||
lateinit var action: VaultAddEditAction.Common
|
||||
lateinit var expectedState: VaultAddEditState.ViewState.Content
|
||||
|
||||
when (type) {
|
||||
val expectedCustomField: VaultAddEditState.Custom = when (type) {
|
||||
CustomFieldType.LINKED -> {
|
||||
expectedCustomField = VaultAddEditState.Custom.LinkedField(
|
||||
"TestId 4",
|
||||
"Linked Field",
|
||||
VaultLinkedFieldType.PASSWORD,
|
||||
VaultAddEditState.Custom.LinkedField(
|
||||
itemId = "TestId 4",
|
||||
name = "Linked Field",
|
||||
vaultLinkedFieldType = VaultLinkedFieldType.PASSWORD,
|
||||
)
|
||||
}
|
||||
|
||||
CustomFieldType.HIDDEN -> {
|
||||
expectedCustomField = VaultAddEditState.Custom.HiddenField(
|
||||
"TestId 2",
|
||||
"Test Hidden",
|
||||
"Updated Test Text",
|
||||
VaultAddEditState.Custom.HiddenField(
|
||||
itemId = "TestId 2",
|
||||
name = "Test Hidden",
|
||||
value = "Updated Test Text",
|
||||
)
|
||||
}
|
||||
|
||||
CustomFieldType.BOOLEAN -> {
|
||||
expectedCustomField = VaultAddEditState.Custom.BooleanField(
|
||||
"TestId 3",
|
||||
"Boolean Field",
|
||||
false,
|
||||
VaultAddEditState.Custom.BooleanField(
|
||||
itemId = "TestId 3",
|
||||
name = "Boolean Field",
|
||||
value = false,
|
||||
)
|
||||
}
|
||||
|
||||
CustomFieldType.TEXT -> {
|
||||
expectedCustomField = VaultAddEditState.Custom.TextField(
|
||||
"TestId 1",
|
||||
"Test Text",
|
||||
"Updated Test Text",
|
||||
VaultAddEditState.Custom.TextField(
|
||||
itemId = "TestId 1",
|
||||
name = "Test Text",
|
||||
value = "Updated Test Text",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6574,13 +6604,12 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
|
||||
val currentContentState =
|
||||
(viewModel.stateFlow.value.viewState as VaultAddEditState.ViewState.Content)
|
||||
action = VaultAddEditAction.Common.CustomFieldValueChange(expectedCustomField)
|
||||
expectedState = currentContentState
|
||||
.copy(
|
||||
common = currentContentState.common.copy(
|
||||
customFieldData = listOf(expectedCustomField),
|
||||
),
|
||||
)
|
||||
val action = VaultAddEditAction.Common.CustomFieldValueChange(expectedCustomField)
|
||||
val expectedState = currentContentState.copy(
|
||||
common = currentContentState.common.copy(
|
||||
customFieldData = listOf(expectedCustomField),
|
||||
),
|
||||
)
|
||||
|
||||
viewModel.trySendAction(action)
|
||||
|
||||
|
||||
Reference in new issue
Block a user