BIT-712: Adding UI for the FastMail service (#459)

This commit is contained in:
joshua-livefront 2023-12-29 15:23:11 -05:00 committed by Álison Fernandes
parent c94b303abc
commit ab03c83cb3
4 changed files with 187 additions and 1 deletions

View file

@ -868,7 +868,14 @@ private fun ColumnScope.ForwardedEmailAliasTypeContent(
} }
is ServiceType.FastMail -> { is ServiceType.FastMail -> {
// TODO: FastMail Service Implementation (BIT-712) BitwardenPasswordField(
label = stringResource(id = R.string.api_key_required_parenthesis),
value = usernameTypeState.selectedServiceType.apiKey,
onValueChange = forwardedEmailAliasHandlers.onFastMailApiKeyTextChange,
modifier = Modifier
.padding(horizontal = 16.dp)
.fillMaxWidth(),
)
} }
is ServiceType.FirefoxRelay -> { is ServiceType.FirefoxRelay -> {
@ -1207,6 +1214,7 @@ private class ForwardedEmailAliasHandlers(
val onAddyIoAccessTokenTextChange: (String) -> Unit, val onAddyIoAccessTokenTextChange: (String) -> Unit,
val onAddyIoDomainNameTextChange: (String) -> Unit, val onAddyIoDomainNameTextChange: (String) -> Unit,
val onDuckDuckGoApiKeyTextChange: (String) -> Unit, val onDuckDuckGoApiKeyTextChange: (String) -> Unit,
val onFastMailApiKeyTextChange: (String) -> Unit,
val onFirefoxRelayAccessTokenTextChange: (String) -> Unit, val onFirefoxRelayAccessTokenTextChange: (String) -> Unit,
) { ) {
companion object { companion object {
@ -1264,6 +1272,19 @@ private class ForwardedEmailAliasHandlers(
), ),
) )
}, },
onFastMailApiKeyTextChange = { newApiKey ->
viewModel.trySendAction(
GeneratorAction
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.FastMail
.ApiKeyTextChange(
apiKey = newApiKey,
),
)
},
onFirefoxRelayAccessTokenTextChange = { newAccessToken -> onFirefoxRelayAccessTokenTextChange = { newAccessToken ->
viewModel.trySendAction( viewModel.trySendAction(
GeneratorAction GeneratorAction

View file

@ -126,6 +126,10 @@ class GeneratorViewModel @Inject constructor(
handleDuckDuckGoTextInputChange(action) handleDuckDuckGoTextInputChange(action)
} }
is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.FastMail.ApiKeyTextChange -> {
handleFastMailTextInputChange(action)
}
is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.FirefoxRelay.AccessTokenTextChange -> { is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.FirefoxRelay.AccessTokenTextChange -> {
handleFirefoxRelayTextInputChange(action) handleFirefoxRelayTextInputChange(action)
} }
@ -692,6 +696,25 @@ class GeneratorViewModel @Inject constructor(
//endregion DuckDuckGo Service Specific Handlers //endregion DuckDuckGo Service Specific Handlers
//region FastMail Service Specific Handlers
private fun handleFastMailTextInputChange(
action: GeneratorAction
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.FastMail
.ApiKeyTextChange,
) {
updateFastMailServiceType { fastMailServiceType ->
val newApiKey = action.apiKey
fastMailServiceType.copy(apiKey = newApiKey)
}
}
//endregion FastMail Service Specific Handlers
//region FirefoxRelay Service Specific Handlers //region FirefoxRelay Service Specific Handlers
private fun handleFirefoxRelayTextInputChange( private fun handleFirefoxRelayTextInputChange(
@ -917,6 +940,30 @@ class GeneratorViewModel @Inject constructor(
} }
} }
private inline fun updateFastMailServiceType(
crossinline block: (FastMail) -> FastMail,
) {
updateGeneratorMainTypeUsername { currentUsernameType ->
if (currentUsernameType.selectedType !is ForwardedEmailAlias) {
return@updateGeneratorMainTypeUsername currentUsernameType
}
val currentServiceType = (currentUsernameType.selectedType).selectedServiceType
if (currentServiceType !is FastMail) {
return@updateGeneratorMainTypeUsername currentUsernameType
}
val updatedServiceType = block(currentServiceType)
currentUsernameType.copy(
selectedType = ForwardedEmailAlias(
selectedServiceType = updatedServiceType,
obfuscatedText = currentUsernameType.selectedType.obfuscatedText,
),
)
}
}
private inline fun updateFirefoxRelayServiceType( private inline fun updateFirefoxRelayServiceType(
crossinline block: (FirefoxRelay) -> FirefoxRelay, crossinline block: (FirefoxRelay) -> FirefoxRelay,
) { ) {
@ -1624,6 +1671,19 @@ sealed class GeneratorAction {
data class ApiKeyTextChange(val apiKey: String) : DuckDuckGo() data class ApiKeyTextChange(val apiKey: String) : DuckDuckGo()
} }
/**
* Represents actions specifically related to the FastMail service.
*/
sealed class FastMail : ForwardedEmailAlias() {
/**
* Fired when the api key input text is changed.
*
* @property apiKey The new api key text.
*/
data class ApiKeyTextChange(val apiKey: String) : FastMail()
}
/** /**
* Represents actions specifically related to the FirefoxRelay service. * Represents actions specifically related to the FirefoxRelay service.
*/ */

View file

@ -1055,6 +1055,46 @@ class GeneratorScreenTest : BaseComposeTest() {
//endregion DuckDuckGo Service Type Tests //endregion DuckDuckGo Service Type Tests
//region FastMail Service Type Tests
@Suppress("MaxLineLength")
@Test
fun `in Username_ForwardedEmailAlias_FastMail state, updating api key text input should send ApiKeyTextChange action`() {
updateState(
GeneratorState(
generatedText = "Placeholder",
selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FastMail(),
),
),
),
)
val newApiKey = "apiKey"
composeTestRule
.onNodeWithText("API key (required)")
.performScrollTo()
.performTextInput(newApiKey)
verify {
viewModel.trySendAction(
GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.FastMail.ApiKeyTextChange(
apiKey = newApiKey,
),
)
}
}
//endregion FastMail Service Type Tests
//region FirefoxRelay Service Type Tests //region FirefoxRelay Service Type Tests
@Suppress("MaxLineLength") @Suppress("MaxLineLength")

View file

@ -37,6 +37,9 @@ class GeneratorViewModelTest : BaseViewModelTest() {
private val initialDuckDuckGoState = createDuckDuckGoState() private val initialDuckDuckGoState = createDuckDuckGoState()
private val duckDuckGoSavedStateHandle = createSavedStateHandleWithState(initialDuckDuckGoState) private val duckDuckGoSavedStateHandle = createSavedStateHandleWithState(initialDuckDuckGoState)
private val initialFastMailState = createFastMailState()
private val fastMailSavedStateHandle = createSavedStateHandleWithState(initialFastMailState)
private val initialFirefoxRelay = createFirefoxRelayState() private val initialFirefoxRelay = createFirefoxRelayState()
private val firefoxRelaySavedStateHandle = createSavedStateHandleWithState(initialFirefoxRelay) private val firefoxRelaySavedStateHandle = createSavedStateHandleWithState(initialFirefoxRelay)
@ -1083,6 +1086,50 @@ class GeneratorViewModelTest : BaseViewModelTest() {
} }
} }
@Nested
inner class FastMailActions {
private val defaultFastMailState = createFastMailState()
private lateinit var viewModel: GeneratorViewModel
@BeforeEach
fun setup() {
viewModel = GeneratorViewModel(fastMailSavedStateHandle, fakeGeneratorRepository)
}
@Test
fun `ApiKeyTextChange should update api key text correctly`() = runTest {
val newApiKey = "newApiKey"
val action = GeneratorAction
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.FastMail.ApiKeyTextChange(
apiKey = newApiKey,
)
viewModel.actionChannel.trySend(action)
val expectedState = defaultFastMailState.copy(
selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FastMail(
apiKey = newApiKey,
),
),
),
)
assertEquals(expectedState, viewModel.stateFlow.value)
}
}
@Nested @Nested
inner class FirefoxRelayActions { inner class FirefoxRelayActions {
private val defaultFirefoxRelayState = createFirefoxRelayState() private val defaultFirefoxRelayState = createFirefoxRelayState()
@ -1371,6 +1418,24 @@ class GeneratorViewModelTest : BaseViewModelTest() {
), ),
) )
private fun createFastMailState(
generatedText: String = "defaultFastMail",
): GeneratorState =
GeneratorState(
generatedText = generatedText,
selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FastMail(),
),
),
)
private fun createFirefoxRelayState( private fun createFirefoxRelayState(
generatedText: String = "defaultFirefoxRelay", generatedText: String = "defaultFirefoxRelay",
): GeneratorState = ): GeneratorState =