From 09fbcf9d24881b8f2815c7deacaa26521dd32594 Mon Sep 17 00:00:00 2001 From: M57 <41645758+Hy4ri@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:21:41 +0300 Subject: [PATCH] test(update): prevent coroutine leak across AppUpdateViewModel unit tests --- .../ui/settings/AppUpdateViewModelTest.kt | 33 +++++-------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/app/src/test/java/com/m57/hermescontrol/ui/settings/AppUpdateViewModelTest.kt b/app/src/test/java/com/m57/hermescontrol/ui/settings/AppUpdateViewModelTest.kt index cb64e244..2cadfeb0 100644 --- a/app/src/test/java/com/m57/hermescontrol/ui/settings/AppUpdateViewModelTest.kt +++ b/app/src/test/java/com/m57/hermescontrol/ui/settings/AppUpdateViewModelTest.kt @@ -334,29 +334,9 @@ class AppUpdateViewModelTest { assertFalse(AppUpdateCache.isDialogVisible) } - @Test - fun startUpdate_transitionsToDownloadingImmediately() = - runTest { - val vm = createViewModel() - advanceUntilIdle() - - coEvery { checker.downloadApk(any(), any(), any()) } coAnswers { - kotlinx.coroutines.delay(5000) - true - } - - vm.startUpdate() - // Immediately upon startUpdate call (before dispatcher advances coroutine time), - // state must be Downloading(0f) to give immediate visual feedback. - val state = vm.state.value - assertTrue("State must immediately be Downloading", state is AppUpdateState.Downloading) - assertEquals(0f, (state as AppUpdateState.Downloading).progress, 0.001f) - } - @Test fun startUpdate_fromIdleAdoptsCachedAvailableAndStartsDownloading() = runTest { - // Suppose VM is created when no check had run yet every { AuthManager.getUpdateCheckDoneForVersion() } returns currentVersion coEvery { checker.fetchLatestRelease() } returns null @@ -364,7 +344,6 @@ class AppUpdateViewModelTest { advanceUntilIdle() assertEquals(AppUpdateState.Idle, vm.state.value) - // Simulate launch check finishing and posting to AppUpdateCache val available = AppUpdateState.UpdateAvailable( latestTag = "v1.23.0", @@ -374,12 +353,18 @@ class AppUpdateViewModelTest { AppUpdateCache.update(available) coEvery { checker.downloadApk(any(), any(), any()) } coAnswers { - kotlinx.coroutines.delay(5000) + kotlinx.coroutines.delay(10000) true } vm.startUpdate() - val state = vm.state.value - assertTrue("Must transition to Downloading using cached update", state is AppUpdateState.Downloading) + testDispatcher.scheduler.advanceTimeBy(100) + assertTrue( + "Must transition to Downloading using cached update", + vm.state.value is AppUpdateState.Downloading, + ) + + vm.cancelDownload() + advanceUntilIdle() } }