fix: address final review findings for provider migration
- Add SessionCoordinator regression test covering switch from an authenticated ABox profile to Local experience: remote session is logged out and cleared, only Local is the active/observable session, credentials are cleared, auto-login disabled, and gateway state stays isolated (verified to fail when switch cleanup is removed). - Replace if/else provider dispatch with exhaustive when over ProviderType in all three routing gateways so future enum additions fail compilation. - Silence the known ExperimentalCoroutinesApi opt-in warning in ProviderSelectionViewModelTest with a class-level @OptIn.
This commit is contained in:
+12
-6
@@ -71,8 +71,10 @@ internal class RoutingSocketGateway(
|
|||||||
is DomainResult.Success -> delegate(provider.value).setPower(profileId, deviceName, powerState)
|
is DomainResult.Success -> delegate(provider.value).setPower(profileId, deviceName, powerState)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun delegate(type: ProviderType): SocketGateway =
|
private fun delegate(type: ProviderType): SocketGateway = when (type) {
|
||||||
if (type == ProviderType.ABOX) real else simulation
|
ProviderType.ABOX -> real
|
||||||
|
ProviderType.LOCAL_EXPERIENCE -> simulation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Routes temperature/humidity operations by active provider, mirroring [RoutingSocketGateway]. */
|
/** Routes temperature/humidity operations by active provider, mirroring [RoutingSocketGateway]. */
|
||||||
@@ -91,8 +93,10 @@ internal class RoutingTemperatureHumidityGateway(
|
|||||||
is DomainResult.Success -> delegate(provider.value).getReading(profileId, deviceName)
|
is DomainResult.Success -> delegate(provider.value).getReading(profileId, deviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun delegate(type: ProviderType): TemperatureHumidityGateway =
|
private fun delegate(type: ProviderType): TemperatureHumidityGateway = when (type) {
|
||||||
if (type == ProviderType.ABOX) real else simulation
|
ProviderType.ABOX -> real
|
||||||
|
ProviderType.LOCAL_EXPERIENCE -> simulation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Routes infrared operations by active provider, mirroring [RoutingSocketGateway]. */
|
/** Routes infrared operations by active provider, mirroring [RoutingSocketGateway]. */
|
||||||
@@ -129,6 +133,8 @@ internal class RoutingInfraredGateway(
|
|||||||
is DomainResult.Success -> delegate(provider.value).downloadCodes(profileId, codes)
|
is DomainResult.Success -> delegate(provider.value).downloadCodes(profileId, codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun delegate(type: ProviderType): InfraredGateway =
|
private fun delegate(type: ProviderType): InfraredGateway = when (type) {
|
||||||
if (type == ProviderType.ABOX) real else simulation
|
ProviderType.ABOX -> real
|
||||||
|
ProviderType.LOCAL_EXPERIENCE -> simulation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -7,6 +7,7 @@ import com.flagship.abox.manager.testing.fakes.FakeCredentialStore
|
|||||||
import com.flagship.abox.manager.testing.fakes.FakeLocalSessionGateway
|
import com.flagship.abox.manager.testing.fakes.FakeLocalSessionGateway
|
||||||
import com.flagship.abox.manager.testing.fakes.FakeProviderProfileStore
|
import com.flagship.abox.manager.testing.fakes.FakeProviderProfileStore
|
||||||
import com.flagship.abox.manager.testing.fakes.FakeSessionGateway
|
import com.flagship.abox.manager.testing.fakes.FakeSessionGateway
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
@@ -14,6 +15,7 @@ import org.junit.Assert.assertEquals
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class ProviderSelectionViewModelTest {
|
class ProviderSelectionViewModelTest {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val mainDispatcherRule = MainDispatcherRule()
|
val mainDispatcherRule = MainDispatcherRule()
|
||||||
|
|||||||
+37
-1
@@ -153,11 +153,47 @@ class SessionCoordinatorTest {
|
|||||||
assertTrue(!fixture.profiles.loginPreferences(remoteProfile.id).autoLoginEnabled)
|
assertTrue(!fixture.profiles.loginPreferences(remoteProfile.id).autoLoginEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun switchingFromAuthenticatedAboxToLocalClearsRemoteSessionAndIsolatesState() = runTest {
|
||||||
|
val fixture = Fixture()
|
||||||
|
fixture.coordinator.selectProvider(remoteProfile)
|
||||||
|
val loginResult = fixture.coordinator.login(
|
||||||
|
remoteProfile.id,
|
||||||
|
credentials,
|
||||||
|
rememberUsername = true,
|
||||||
|
autoLogin = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
val switchResult = fixture.coordinator.selectProvider(localProfile)
|
||||||
|
|
||||||
|
assertTrue(loginResult is DomainResult.Success)
|
||||||
|
assertTrue(switchResult is DomainResult.Success)
|
||||||
|
assertEquals(
|
||||||
|
localProfile.id,
|
||||||
|
(switchResult as DomainResult.Success).value?.profileId,
|
||||||
|
)
|
||||||
|
assertEquals(localProfile.id, fixture.profiles.activeProfile()?.id)
|
||||||
|
assertEquals(
|
||||||
|
localProfile.id,
|
||||||
|
fixture.coordinator.observeActiveSession().first()?.profileId,
|
||||||
|
)
|
||||||
|
assertNull(fixture.remote.observeSession(remoteProfile.id).first())
|
||||||
|
assertNull(fixture.remote.observeSession(localProfile.id).first())
|
||||||
|
assertEquals(
|
||||||
|
localProfile.id,
|
||||||
|
fixture.local.observeSession(localProfile.id).first()?.profileId,
|
||||||
|
)
|
||||||
|
assertNull(
|
||||||
|
(fixture.credentials.loadCredentials(remoteProfile.id) as DomainResult.Success).value,
|
||||||
|
)
|
||||||
|
assertTrue(!fixture.profiles.loginPreferences(remoteProfile.id).autoLoginEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
private class Fixture {
|
private class Fixture {
|
||||||
val profiles = FakeProviderProfileStore()
|
val profiles = FakeProviderProfileStore()
|
||||||
val credentials = FakeCredentialStore()
|
val credentials = FakeCredentialStore()
|
||||||
val remote = FakeSessionGateway()
|
val remote = FakeSessionGateway()
|
||||||
private val local = FakeLocalSessionGateway()
|
val local = FakeLocalSessionGateway()
|
||||||
val coordinator = SessionCoordinator(profiles, credentials, remote, local)
|
val coordinator = SessionCoordinator(profiles, credentials, remote, local)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user