feat: add AuthViewModel, ScheduleViewModel, and EventDetailViewModel with StateFlow
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
package ch.parano.myice.viewmodel
|
||||
|
||||
import ch.parano.myice.cache.ScheduleCache
|
||||
import ch.parano.myice.filter.TypeFilter
|
||||
import ch.parano.myice.models.Account
|
||||
import ch.parano.myice.models.Event
|
||||
import ch.parano.myice.network.ApiService
|
||||
import com.russhwolf.settings.MapSettings
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.mock.MockEngine
|
||||
import io.ktor.client.engine.mock.MockEngineConfig
|
||||
import io.ktor.client.engine.mock.respond
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.headersOf
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlin.test.AfterTest
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
|
||||
class ScheduleViewModelTest {
|
||||
|
||||
@BeforeTest
|
||||
fun setUpDispatcher() {
|
||||
Dispatchers.setMain(UnconfinedTestDispatcher())
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
fun tearDownDispatcher() {
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
|
||||
private fun mockApi(accountsJson: String, scheduleJson: String): ApiService {
|
||||
val config = MockEngineConfig().apply {
|
||||
addHandler { request ->
|
||||
val path = request.url.encodedPath
|
||||
val response = when {
|
||||
path == "/accounts" -> accountsJson
|
||||
path == "/schedule" -> scheduleJson
|
||||
else -> "[]"
|
||||
}
|
||||
respond(
|
||||
content = response,
|
||||
status = HttpStatusCode.OK,
|
||||
headers = headersOf(HttpHeaders.ContentType, "application/json"),
|
||||
)
|
||||
}
|
||||
dispatcher = Dispatchers.Unconfined
|
||||
}
|
||||
val client = HttpClient(MockEngine(config)) {
|
||||
install(ContentNegotiation) { json(json) }
|
||||
}
|
||||
return ApiService(client)
|
||||
}
|
||||
|
||||
private fun sampleEvent(
|
||||
id: String = "1",
|
||||
agegroup: String = "U13 (Elite)",
|
||||
name: String = "U13 Elite - HC Ajoie",
|
||||
eventType: String = "Jeu",
|
||||
) = Event(
|
||||
idEvent = id, agegroup = agegroup, name = name, title = "Title",
|
||||
opponent = "Opp", place = "Place", start = "2024-11-10T14:00:00",
|
||||
end = "2024-11-10T16:15:00", color = "#e4222e", eventType = eventType,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testLoadAccounts() = runTest {
|
||||
val api = mockApi(
|
||||
"""[{"name":"default","label":"Default"}]""",
|
||||
"[]",
|
||||
)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
|
||||
assertEquals(1, vm.state.value.accounts.size)
|
||||
assertEquals("default", vm.state.value.selectedAccount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRefreshScheduleStoresEvents() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U13 (Elite)","name":"U13 Elite - HC Ajoie","title":"T","opponent":"O","place":"P","start":"2024-11-10T14:00:00","end":"2024-11-10T16:15:00","color":"#e4222e","event":"Jeu"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
|
||||
assertEquals(1, vm.state.value.events.size)
|
||||
assertEquals("1", vm.state.value.events[0].idEvent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilteredEventsDefaultGamesOnly() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U13","name":"U13 - A","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"},
|
||||
{"id_event":"2","agegroup":"U13","name":"U13 - B","title":"T","opponent":"","place":"P","start":"s","end":"e"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
|
||||
assertEquals(2, vm.state.value.events.size)
|
||||
assertEquals(1, vm.state.value.filteredEvents.size)
|
||||
assertEquals("1", vm.state.value.filteredEvents[0].idEvent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetTypeFilterAll() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U13","name":"U13 - A","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"},
|
||||
{"id_event":"2","agegroup":"U13","name":"U13 - B","title":"T","opponent":"","place":"P","start":"s","end":"e"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
vm.setTypeFilter(TypeFilter.ALL)
|
||||
|
||||
assertEquals(2, vm.state.value.filteredEvents.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetAgegroup() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U13","name":"U13 - A","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"},
|
||||
{"id_event":"2","agegroup":"U15","name":"U15 - B","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
vm.setAgegroup("U15")
|
||||
|
||||
assertEquals(1, vm.state.value.filteredEvents.size)
|
||||
assertEquals("2", vm.state.value.filteredEvents[0].idEvent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetSubgroup() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U13","name":"U13 Elite - HC Ajoie","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"},
|
||||
{"id_event":"2","agegroup":"U13","name":"U13 Top - HC Geneva","title":"T","opponent":"O","place":"P","start":"s","end":"e","event":"Jeu"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
vm.setSubgroup("U13 Elite")
|
||||
|
||||
assertEquals(1, vm.state.value.filteredEvents.size)
|
||||
assertEquals("1", vm.state.value.filteredEvents[0].idEvent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCacheLoadOnLoadCachedSchedule() = runTest {
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", "[]")
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
cache.saveEvents("default", listOf(sampleEvent("1")))
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.loadCachedSchedule()
|
||||
|
||||
assertEquals(1, vm.state.value.events.size)
|
||||
assertFalse(vm.state.value.isLoading)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAgegroupsComputed() = runTest {
|
||||
val scheduleJson = """
|
||||
[{"id_event":"1","agegroup":"U15","name":"N","title":"T","opponent":"","place":"P","start":"s","end":"e","event":"Jeu"},
|
||||
{"id_event":"2","agegroup":"U13","name":"N","title":"T","opponent":"","place":"P","start":"s","end":"e","event":"Jeu"}]
|
||||
""".trimIndent()
|
||||
val api = mockApi("""[{"name":"default","label":"Default"}]""", scheduleJson)
|
||||
val cache = ScheduleCache(MapSettings())
|
||||
val vm = ScheduleViewModel(api, cache)
|
||||
|
||||
vm.loadAccounts()
|
||||
vm.refreshSchedule()
|
||||
|
||||
assertEquals(listOf("U13", "U15"), vm.state.value.agegroups)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user