Add AccountAutoDiscoveryStateMapper and propagate to other view models

This commit is contained in:
Wolf-Martell Montwé 2023-06-16 13:45:11 +02:00
parent d2685dbede
commit b826961287
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
4 changed files with 295 additions and 1 deletions

View file

@ -7,6 +7,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep
import app.k9mail.feature.account.setup.ui.AccountSetupContract.State
import app.k9mail.feature.account.setup.ui.AccountSetupContract.ViewModel
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.common.mapper.toIncomingConfigState
import app.k9mail.feature.account.setup.ui.common.mapper.toOptionsState
import app.k9mail.feature.account.setup.ui.common.mapper.toOutgoingConfigState
class AccountSetupViewModel(
initialState: State = State(),
@ -21,7 +24,9 @@ class AccountSetupViewModel(
}
private fun handleAutoDiscoveryFinished(autoDiscoveryState: AccountAutoDiscoveryContract.State) {
// TODO emmit effect to update ViewModels
emitEffect(Effect.UpdateIncomingConfig(autoDiscoveryState.toIncomingConfigState()))
emitEffect(Effect.UpdateOutgoingConfig(autoDiscoveryState.toOutgoingConfigState()))
emitEffect(Effect.UpdateOptions(autoDiscoveryState.toOptionsState()))
onNext()
}

View file

@ -0,0 +1,76 @@
package app.k9mail.feature.account.setup.ui.common.mapper
import app.k9mail.autodiscovery.api.ImapServerSettings
import app.k9mail.autodiscovery.api.SmtpServerSettings
import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort
import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort
import app.k9mail.feature.account.setup.domain.input.NumberInputField
import app.k9mail.feature.account.setup.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
internal fun AccountAutoDiscoveryContract.State.toIncomingConfigState(): AccountIncomingConfigContract.State {
val incomingSettings = autoDiscoverySettings?.incomingServerSettings as? ImapServerSettings?
return AccountIncomingConfigContract.State(
protocolType = incomingSettings?.toIncomingProtocolType() ?: IncomingProtocolType.DEFAULT,
server = StringInputField(
value = prefillServer(
hostname = incomingSettings?.hostname?.value,
),
),
security = incomingSettings?.connectionSecurity?.toConnectionSecurity() ?: ConnectionSecurity.DEFAULT,
port = NumberInputField(
value = incomingSettings?.port?.value?.toLong() ?: ConnectionSecurity.DEFAULT.toImapDefaultPort(),
),
username = StringInputField(
value = prefillUserName(
emailAddress = emailAddress.value,
username = incomingSettings?.username,
),
),
password = StringInputField(value = password.value),
)
}
internal fun AccountAutoDiscoveryContract.State.toOutgoingConfigState(): AccountOutgoingConfigContract.State {
val outgoingSettings = autoDiscoverySettings?.outgoingServerSettings as? SmtpServerSettings?
return AccountOutgoingConfigContract.State(
server = StringInputField(
value = prefillServer(
hostname = outgoingSettings?.hostname?.value,
),
),
security = outgoingSettings?.connectionSecurity?.toConnectionSecurity() ?: ConnectionSecurity.DEFAULT,
port = NumberInputField(
value = outgoingSettings?.port?.value?.toLong() ?: ConnectionSecurity.DEFAULT.toSmtpDefaultPort(),
),
username = StringInputField(
value = prefillUserName(
emailAddress = emailAddress.value,
username = outgoingSettings?.username,
),
),
password = StringInputField(value = password.value),
)
}
private fun prefillServer(hostname: String?) = hostname.orEmpty()
internal fun prefillUserName(
emailAddress: String,
username: String?,
): String {
return username.takeUnless { it.isNullOrEmpty() } ?: emailAddress
}
internal fun AccountAutoDiscoveryContract.State.toOptionsState(): AccountOptionsContract.State {
return AccountOptionsContract.State(
accountName = StringInputField(value = emailAddress.value),
)
}

View file

@ -5,6 +5,11 @@ import app.k9mail.core.ui.compose.testing.MainDispatcherRule
import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect
import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep
import app.k9mail.feature.account.setup.ui.AccountSetupContract.State
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import assertk.assertThat
import assertk.assertions.assertThatAndTurbinesConsumed
import assertk.assertions.isEqualTo
import assertk.assertions.prop
@ -34,6 +39,15 @@ class AccountSetupViewModelTest {
viewModel.event(AccountSetupContract.Event.OnAutoDiscoveryFinished(AccountAutoDiscoveryContract.State()))
assertThat(effectTurbine.awaitItem())
.isEqualTo(Effect.UpdateIncomingConfig(AccountIncomingConfigContract.State()))
assertThat(effectTurbine.awaitItem())
.isEqualTo(Effect.UpdateOutgoingConfig(AccountOutgoingConfigContract.State()))
assertThat(effectTurbine.awaitItem())
.isEqualTo(Effect.UpdateOptions(AccountOptionsContract.State()))
assertThatAndTurbinesConsumed(
actual = stateTurbine.awaitItem(),
turbines = turbines,

View file

@ -0,0 +1,199 @@
package app.k9mail.feature.account.setup.ui.common.mapper
import app.k9mail.autodiscovery.api.AutoDiscoveryResult
import app.k9mail.autodiscovery.api.ImapServerSettings
import app.k9mail.autodiscovery.api.SmtpServerSettings
import app.k9mail.core.common.net.toHostname
import app.k9mail.core.common.net.toPort
import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType
import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity
import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType
import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity
import app.k9mail.feature.account.setup.domain.input.NumberInputField
import app.k9mail.feature.account.setup.domain.input.StringInputField
import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract
import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract
import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract
import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract
import assertk.assertThat
import assertk.assertions.isEqualTo
import org.junit.Test
class AccountAutoDiscoveryStateMapperKtTest {
@Test
fun `should map to default IncomingConfigState when empty`() {
val incomingConfigState = EMPTY_STATE.toIncomingConfigState()
assertThat(incomingConfigState).isEqualTo(AccountIncomingConfigContract.State())
}
@Test
fun `should map to IncomingConfigState when no AutoDiscovery`() {
val incomingConfigState = EMAIL_PASSWORD_STATE.toIncomingConfigState()
assertThat(incomingConfigState).isEqualTo(
AccountIncomingConfigContract.State(
username = StringInputField(value = EMAIL_ADDRESS),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to IncomingConfigState when AutoDiscovery`() {
val incomingConfigState = AUTO_DISCOVERY_STATE.toIncomingConfigState()
assertThat(incomingConfigState).isEqualTo(
AccountIncomingConfigContract.State(
protocolType = IncomingProtocolType.IMAP,
server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value),
security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(),
port = NumberInputField(value = AUTO_DISCOVERY_PORT_IMAP.value.toLong()),
username = StringInputField(value = AUTO_DISCOVERY_USERNAME),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to email username IncomingConfigState when AutoDiscovery empty username`() {
val incomingConfigState = AUTO_DISCOVERY_STATE_USERNAME_EMPTY.toIncomingConfigState()
assertThat(incomingConfigState).isEqualTo(
AccountIncomingConfigContract.State(
protocolType = IncomingProtocolType.IMAP,
server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value),
security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(),
port = NumberInputField(value = AUTO_DISCOVERY_PORT_IMAP.value.toLong()),
username = StringInputField(value = EMAIL_ADDRESS),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to OutgoingConfigState when empty`() {
val outgoingConfigState = EMPTY_STATE.toOutgoingConfigState()
assertThat(outgoingConfigState).isEqualTo(AccountOutgoingConfigContract.State())
}
@Test
fun `should map to OutgoingConfigState when no AutoDiscovery`() {
val outgoingConfigState = EMAIL_PASSWORD_STATE.toOutgoingConfigState()
assertThat(outgoingConfigState).isEqualTo(
AccountOutgoingConfigContract.State(
username = StringInputField(value = EMAIL_ADDRESS),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to OutgoingConfigState when AutoDiscovery`() {
val outgoingConfigState = AUTO_DISCOVERY_STATE.toOutgoingConfigState()
assertThat(outgoingConfigState).isEqualTo(
AccountOutgoingConfigContract.State(
server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value),
security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(),
port = NumberInputField(value = AUTO_DISCOVERY_PORT_SMTP.value.toLong()),
username = StringInputField(value = AUTO_DISCOVERY_USERNAME),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to email username OutgoingConfigState when AutoDiscovery empty username`() {
val outgoingConfigState = AUTO_DISCOVERY_STATE_USERNAME_EMPTY.toOutgoingConfigState()
assertThat(outgoingConfigState).isEqualTo(
AccountOutgoingConfigContract.State(
server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value),
security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(),
port = NumberInputField(value = AUTO_DISCOVERY_PORT_SMTP.value.toLong()),
username = StringInputField(value = EMAIL_ADDRESS),
password = StringInputField(value = PASSWORD),
),
)
}
@Test
fun `should map to OptionsState when empty`() {
val optionsState = EMPTY_STATE.toOptionsState()
assertThat(optionsState).isEqualTo(AccountOptionsContract.State())
}
@Test
fun `should map to OptionsState when email and password set`() {
val optionsState = EMAIL_PASSWORD_STATE.toOptionsState()
assertThat(optionsState).isEqualTo(
AccountOptionsContract.State(
accountName = StringInputField(value = EMAIL_ADDRESS),
),
)
}
private companion object {
const val EMAIL_ADDRESS = "test@example.com"
const val PASSWORD = "password"
const val SERVER_IMAP = "imap.example.com"
const val SERVER_SMTP = "smtp.example.com"
val AUTO_DISCOVERY_HOSTNAME = "incoming.example.com".toHostname()
val AUTO_DISCOVERY_PORT_IMAP = 143.toPort()
val AUTO_DISCOVERY_PORT_SMTP = 587.toPort()
val AUTO_DISCOVERY_SECURITY = AutoDiscoveryConnectionSecurity.StartTLS
val AUTO_DISCOVERY_AUTHENTICATION = AutoDiscoveryAuthenticationType.PasswordEncrypted
const val AUTO_DISCOVERY_USERNAME = "username"
val EMPTY_STATE = AccountAutoDiscoveryContract.State()
val EMAIL_PASSWORD_STATE = AccountAutoDiscoveryContract.State(
emailAddress = StringInputField(value = EMAIL_ADDRESS),
password = StringInputField(value = PASSWORD),
)
val AUTO_DISCOVERY_STATE = EMAIL_PASSWORD_STATE.copy(
autoDiscoverySettings = AutoDiscoveryResult.Settings(
incomingServerSettings = ImapServerSettings(
hostname = AUTO_DISCOVERY_HOSTNAME,
port = AUTO_DISCOVERY_PORT_IMAP,
connectionSecurity = AUTO_DISCOVERY_SECURITY,
authenticationType = AUTO_DISCOVERY_AUTHENTICATION,
username = AUTO_DISCOVERY_USERNAME,
),
outgoingServerSettings = SmtpServerSettings(
hostname = AUTO_DISCOVERY_HOSTNAME,
port = AUTO_DISCOVERY_PORT_SMTP,
connectionSecurity = AUTO_DISCOVERY_SECURITY,
authenticationType = AUTO_DISCOVERY_AUTHENTICATION,
username = AUTO_DISCOVERY_USERNAME,
),
isTrusted = true,
),
)
val AUTO_DISCOVERY_STATE_USERNAME_EMPTY = AUTO_DISCOVERY_STATE.copy(
autoDiscoverySettings = AUTO_DISCOVERY_STATE.autoDiscoverySettings?.copy(
incomingServerSettings = (
AUTO_DISCOVERY_STATE.autoDiscoverySettings
?.incomingServerSettings as ImapServerSettings
).copy(
username = "",
),
outgoingServerSettings = (
AUTO_DISCOVERY_STATE.autoDiscoverySettings
?.outgoingServerSettings as SmtpServerSettings
).copy(
username = "",
),
),
)
}
}