Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.simprints.feature.dashboard.logout.usecase

import com.simprints.infra.authlogic.AuthManager
import com.simprints.infra.enrolment.records.repository.local.migration.RealmToRoomMigrationFlagsStore
import com.simprints.infra.sync.SyncOrchestrator
import kotlinx.coroutines.runBlocking
import javax.inject.Inject

internal class LogoutUseCase @Inject constructor(
private val syncOrchestrator: SyncOrchestrator,
private val authManager: AuthManager,
private val flagsStore: RealmToRoomMigrationFlagsStore,
) {
operator fun invoke() = runBlocking {
// Cancel all background sync
syncOrchestrator.cancelBackgroundWork()
syncOrchestrator.deleteEventSyncInfo()
// sign out the user
authManager.signOut()
// Reset migration flags
flagsStore.clearMigrationFlags()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.simprints.feature.dashboard.logout.usecase

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.simprints.infra.authlogic.AuthManager
import com.simprints.infra.enrolment.records.repository.local.migration.RealmToRoomMigrationFlagsStore
import com.simprints.infra.sync.SyncOrchestrator
import com.simprints.testtools.common.coroutines.TestCoroutineRule
import io.mockk.MockKAnnotations
Expand All @@ -25,6 +26,9 @@ class LogoutUseCaseTest {
@MockK
private lateinit var authManager: AuthManager

@MockK
private lateinit var flagsStore: RealmToRoomMigrationFlagsStore

private lateinit var useCase: LogoutUseCase

@Before
Expand All @@ -34,6 +38,7 @@ class LogoutUseCaseTest {
useCase = LogoutUseCase(
syncOrchestrator = syncOrchestrator,
authManager = authManager,
flagsStore = flagsStore,
)
}

Expand All @@ -45,6 +50,7 @@ class LogoutUseCaseTest {
syncOrchestrator.cancelBackgroundWork()
syncOrchestrator.deleteEventSyncInfo()
authManager.signOut()
flagsStore.clearMigrationFlags()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.simprints.feature.dashboard.tools.di

import android.content.Context
import androidx.work.WorkManager
import com.simprints.core.AppScope
import com.simprints.core.AvailableProcessors
import com.simprints.core.CoreModule
Expand All @@ -17,6 +19,7 @@ import com.simprints.core.tools.utils.StringTokenizer
import com.simprints.testtools.unit.EncodingUtilsImplForTests
import dagger.Module
import dagger.Provides
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dagger.hilt.testing.TestInstallIn
import io.mockk.mockk
Expand Down Expand Up @@ -88,4 +91,9 @@ object FakeCoreModule {
@Provides
@Singleton
fun provideEncodingUtils(): EncodingUtils = EncodingUtilsImplForTests

@Provides
fun provideWorkManager(
@ApplicationContext context: Context,
): WorkManager = WorkManager.getInstance(context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.simprints.infra.config.store.models.Project
import com.simprints.infra.config.store.models.ProjectConfiguration
import com.simprints.infra.config.store.models.ProjectWithConfig
import com.simprints.infra.enrolment.records.repository.EnrolmentRecordRepository
import com.simprints.infra.enrolment.records.repository.local.migration.RealmToRoomMigrationScheduler
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onStart
import javax.inject.Inject
Expand All @@ -16,15 +17,17 @@ class ConfigManager @Inject constructor(
private val configRepository: ConfigRepository,
private val enrolmentRecordRepository: EnrolmentRecordRepository,
private val configSyncCache: ConfigSyncCache,
private val realmToRoomMigrationScheduler: RealmToRoomMigrationScheduler,
) {
suspend fun refreshProject(projectId: String): ProjectWithConfig = configRepository.refreshProject(projectId).also {
enrolmentRecordRepository.tokenizeExistingRecords(it.project)
configSyncCache.saveUpdateTime()
realmToRoomMigrationScheduler.scheduleMigrationWorkerIfNeeded()
}

suspend fun getProject(projectId: String): Project = try {
configRepository.getProject()
} catch (e: NoSuchElementException) {
} catch (_: NoSuchElementException) {
refreshProject(projectId).project
}

Expand All @@ -35,7 +38,7 @@ class ConfigManager @Inject constructor(
try {
// Try to refresh it with logged in projectId (if any)
refreshProject(configRepository.getProject().id).configuration
} catch (e: Exception) {
} catch (_: Exception) {
// If not logged in the above will fail. However we still depend on the 'default'
// configuration to create the session when login is attempted. Possibly in other
// places, too.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.simprints.infra.config.sync

import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.*
import com.simprints.infra.config.store.ConfigRepository
import com.simprints.infra.config.store.models.DeviceConfiguration
import com.simprints.infra.config.store.models.Project
import com.simprints.infra.config.store.models.ProjectConfiguration
import com.simprints.infra.config.store.models.ProjectWithConfig
import com.simprints.infra.enrolment.records.repository.EnrolmentRecordRepository
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import com.simprints.infra.enrolment.records.repository.local.migration.RealmToRoomMigrationScheduler
import io.mockk.*
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -43,6 +41,9 @@ class ConfigManagerTest {
@MockK
private lateinit var deviceConfiguration: DeviceConfiguration

@MockK
private lateinit var realmToRoomMigrationScheduler: RealmToRoomMigrationScheduler

@MockK
private lateinit var project: Project

Expand All @@ -53,6 +54,7 @@ class ConfigManagerTest {
configRepository = configRepository,
enrolmentRecordRepository = enrolmentRecordRepository,
configSyncCache = configSyncCache,
realmToRoomMigrationScheduler = realmToRoomMigrationScheduler,
)
}

Expand All @@ -64,6 +66,7 @@ class ConfigManagerTest {
assertThat(refreshedProject).isEqualTo(projectWithConfig)

coVerify { configSyncCache.saveUpdateTime() }
coVerify { realmToRoomMigrationScheduler.scheduleMigrationWorkerIfNeeded() }
}

@Test
Expand All @@ -74,6 +77,14 @@ class ConfigManagerTest {
assertThat(gottenProject).isEqualTo(project)
}

@Test
fun `getProject should call the refresh method when cannot get from local`() = runTest {
coEvery { configRepository.getProject() } throws NoSuchElementException()

configManager.getProject(PROJECT_ID)
coVerify(exactly = 1) { configRepository.refreshProject(PROJECT_ID) }
}

@Test
fun `getProjectConfiguration should call the correct method`() = runTest {
coEvery { configRepository.getProjectConfiguration() } returns projectConfiguration
Expand All @@ -83,6 +94,16 @@ class ConfigManagerTest {
assertThat(gottenProjectConfiguration).isEqualTo(projectConfiguration)
}

@Test
fun `getProjectConfiguration return default config if not logged in`() = runTest {
every { projectConfiguration.projectId } returns ""
coEvery { configRepository.getProjectConfiguration() } returns projectConfiguration
coEvery { configRepository.refreshProject(any()) } throws Exception()

val gottenProjectConfiguration = configManager.getProjectConfiguration()
assertThat(gottenProjectConfiguration).isEqualTo(projectConfiguration)
}

@Test
fun `refreshProjectConfiguration should call the correct method`() = runTest {
coEvery { configRepository.refreshProject(PROJECT_ID) } returns projectWithConfig
Expand Down Expand Up @@ -120,7 +141,7 @@ class ConfigManagerTest {
configManager.getPrivacyNotice(PROJECT_ID, LANGUAGE)
coVerify(exactly = 1) { configRepository.getPrivacyNotice(PROJECT_ID, LANGUAGE) }
}

@Test
fun `watchProjectConfiguration should emit values from the local data source`() = runTest {
val config1 = projectConfiguration.copy(projectId = "project1")
Expand Down
6 changes: 6 additions & 0 deletions infra/core/src/main/java/com/simprints/core/CoreModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.simprints.core

import android.content.Context
import androidx.work.WorkManager
import com.lyft.kronos.AndroidClockFactory
import com.simprints.core.tools.exceptions.AppCoroutineExceptionHandler
import com.simprints.core.tools.extentions.deviceHardwareId
Expand Down Expand Up @@ -134,6 +135,11 @@ object CoreModule {
): CoroutineScope = CoroutineScope(
SupervisorJob() + dispatcherMain + AppCoroutineExceptionHandler(),
)

@Provides
fun provideWorkManager(
@ApplicationContext context: Context,
): WorkManager = WorkManager.getInstance(context)
}

@Qualifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,12 @@ class RealmToRoomMigrationFlagsStore @Inject constructor(
$KEY_DOWN_SYNC_STATUS: $downSync
""".trimIndent()
}

/**
* Clears all migration-related keys from the store.
*/
fun clearMigrationFlags() {
prefs.edit { clear() }
Simber.i("[RealmToRoomMigrationFlagsStore] Migration flags cleared", tag = REALM_DB_MIGRATION)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,14 @@ class RealmToRoomMigrationFlagsStoreTest {
verify { editor.putBoolean(RealmToRoomMigrationFlagsStore.KEY_DOWN_SYNC_STATUS, false) }
verify { editor.apply() }
}

@Test
fun `clearMigrationFlags should remove all migration-related keys`() {
// Given
every { editor.clear() } returns editor
// When
store.clearMigrationFlags()
// Then
verify { editor.clear() }
}
}
15 changes: 1 addition & 14 deletions infra/sync/src/main/java/com/simprints/infra/sync/SyncModule.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
package com.simprints.infra.sync

import android.content.Context
import androidx.work.WorkManager
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object SyncModule {
@Provides
fun provideWorkManager(
@ApplicationContext context: Context,
): WorkManager = WorkManager.getInstance(context)
}

@Module
@InstallIn(SingletonComponent::class)
abstract class SyncOrchestratorModule {
abstract class SyncModule {
@Binds
internal abstract fun provideSyncOrchestrator(syncOrchestratorImpl: SyncOrchestratorImpl): SyncOrchestrator
}