/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.util

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher
import org.junit.runner.Description

/**
 * Swaps `Dispatchers.Main` (which `viewModelScope` dispatches on) for a test
 * dispatcher for the duration of a test, so ViewModel coroutines run on the test
 * scheduler instead of a real Android main looper.
 *
 * Defaults to an [UnconfinedTestDispatcher] so work launched from a ViewModel's
 * `init {}` runs eagerly to its first real suspension — with fakes that never
 * truly suspend, that means the final state is settled by the time the constructor
 * returns, and a test can assert `state.value` directly without advancing time.
 */
@OptIn(ExperimentalCoroutinesApi::class)
class MainDispatcherRule(
    val dispatcher: TestDispatcher = UnconfinedTestDispatcher(),
) : TestWatcher() {
    override fun starting(description: Description) = Dispatchers.setMain(dispatcher)
    override fun finished(description: Description) = Dispatchers.resetMain()
}
