OXYGENHUB
# cccf06468345 oxygenhub-android / app / src / test / java / io / oxygenhub / android / ui / DashboardViewModelTest.kt
5.8 KiB · last changed A repository's screen opens on a band of its own sky (refs #23) 8 days ago source blame history raw
1
package io.oxygenhub.android.ui
2
3
import io.oxygenhub.android.FakeHubApi
4
import io.oxygenhub.android.Fixtures
5
import io.oxygenhub.android.MainDispatcherRule
6
import io.oxygenhub.android.api.Avatar
7
import io.oxygenhub.android.api.HubException
8
import io.oxygenhub.android.api.UserSky
9
import io.oxygenhub.android.auth.Session
10
import io.oxygenhub.android.ui.backdrop.Frame
11
import io.oxygenhub.android.ui.backdrop.repoSkyOrNull
12
import io.oxygenhub.android.ui.backdrop.skyEvents
13
import io.oxygenhub.android.ui.backdrop.straight
14
import io.oxygenhub.android.ui.common.Load
15
import io.oxygenhub.android.ui.dashboard.Dashboard
16
import io.oxygenhub.android.ui.dashboard.DashboardViewModel
17
import org.junit.Assert.assertEquals
18
import org.junit.Assert.assertFalse
19
import org.junit.Assert.assertNull
20
import org.junit.Assert.assertTrue
21
import org.junit.Rule
22
import org.junit.Test
23
24
class DashboardViewModelTest {
25
    @get:Rule val main = MainDispatcherRule()
26
27
    private val api = FakeHubApi()
28
    private val session = Session("https://oxygenhub.io", "andymccall", "t")
29
30
    private fun ready(vm: DashboardViewModel): Dashboard = (vm.state.value as Load.Ready).value
31
32
    @Test
33
    fun greetsAndListsTheUsersRecentRepositories() {
34
        val d = ready(DashboardViewModel(api, session) { 9 })
35
        assertEquals("Good morning, Andy McCall", d.greeting)
36
        assertTrue(d.recentAreYours)
37
        assertEquals(listOf("andymccall/oxygenflow", "andymccall/secret-plans"), d.recent.map { it.slug })
38
        assertEquals(2, d.repositoryCount)
39
    }
40
41
    @Test
42
    fun showsTheAccountsAvatarAndKeepsItWhenTheHubFails() {
43
        val mine = Avatar.Identicon(196, setOf(3 to 3))
44
        api.avatar = { if (it == "andymccall") mine else null }
45
        val vm = DashboardViewModel(api, session) { 9 }
46
        assertEquals(mine, ready(vm).avatar)
47
        assertEquals("andymccall", ready(vm).username)
48
        // A failed fetch keeps the one before; the page still loads.
49
        api.avatar = { throw HubException.Http(500, "down") }
50
        vm.refresh()
51
        assertEquals(mine, ready(vm).avatar)
52
    }
53
54
    @Test
55
    fun drawsYourSkyFromTheHubAndTheFieldWithoutIt() {
56
        val vm = DashboardViewModel(api, session) { 9 }
57
        val sky = ready(vm).sky!!
58
        val events = skyEvents(sky)
59
        assertEquals(1, events.size)
60
        assertEquals(1f, events[0].ageDays, 0.001f)
61
        assertEquals(3u, events[0].n)
62
        // A hub before /user/sky: the dashboard loads, with no sky.
63
        api.userSky = { throw HubException.Http(404, "no such endpoint") }
64
        vm.refresh()
65
        assertNull(ready(vm).sky)
66
        assertEquals(2, ready(vm).repositoryCount)
67
    }
68
69
    @Test
70
    fun aRepositorysSkyIsNothingFromAHubWithoutIt() = kotlinx.coroutines.test.runTest {
71
        assertEquals(listOf("andymccall/oxygen"), repoSkyOrNull(api, "andymccall", "oxygen")?.repos)
72
        api.userSky = { throw HubException.Http(404, "no such endpoint") }
73
        assertNull(repoSkyOrNull(api, "andymccall", "oxygen"))
74
    }
75
76
    @Test
77
    fun leavesOutMalformedSkyEvents() {
78
        val sky = UserSky(now = 0, repos = listOf("a/b"), events = listOf(listOf(0L, 9L, 0L, 1L), listOf(3L, 0L, 0L, 1L), listOf(0L), listOf(0L, 4L, 5L, 0L)))
79
        val events = skyEvents(sky)
80
        assertEquals(1, events.size)
81
        assertEquals(4u, events[0].kind)
82
        assertEquals(0f, events[0].ageDays)
83
        assertEquals("at least one mark", 1u, events[0].n)
84
    }
85
86
    @Test
87
    fun decodesAFrameAndUnpremultipliesItsColours() {
88
        val bytes = java.nio.ByteBuffer.allocate(8).order(java.nio.ByteOrder.LITTLE_ENDIAN).putFloat(1.5f).putFloat(-2f).array()
89
        assertTrue(Frame.floats(bytes).contentEquals(floatArrayOf(1.5f, -2f)))
90
        val c = straight(0.25f, 0f, 0.5f, 0.5f)
91
        assertEquals(0.5f, c.red, 0.01f)
92
        assertEquals(1f, c.blue, 0.01f)
93
        assertEquals(0.5f, c.alpha, 0.01f)
94
        assertEquals(0f, straight(0.1f, 0.1f, 0.1f, 0f).alpha)
95
    }
96
97
    @Test
98
    fun showsProposalsToReviewAndNoneFromAHubWithoutTheCall() {
99
        val vm = DashboardViewModel(api, session) { 9 }
100
        assertEquals(listOf(300L), ready(vm).proposals?.review?.map { it.number })
101
        assertEquals("andymccall" to "oxygenhub", ready(vm).proposals!!.review[0].let { it.owner to it.name })
102
        api.userProposals = { throw HubException.Http(404, "no such endpoint") }
103
        vm.refresh()
104
        assertNull(ready(vm).proposals)
105
        assertEquals(2, ready(vm).repositoryCount)
106
    }
107
108
    @Test
109
    fun withNoRepositoriesOfTheirOwnShowsTheHubs() {
110
        val d = ready(DashboardViewModel(api, session.copy(username = "newcomer")) { 14 }.also {
111
            api.user = { Fixtures.user.copy(username = "newcomer", displayName = "") }
112
            it.refresh()
113
        })
114
        assertEquals("Good afternoon, newcomer", d.greeting)
115
        assertFalse(d.recentAreYours)
116
        assertEquals("doomsdayone/tetris", d.recent.first().slug)
117
    }
118
119
    @Test
120
    fun withoutUserReadGreetsByTheSessionsName() {
121
        api.user = { throw HubException.Http(403, "this token lacks the user:read scope") }
122
        val d = ready(DashboardViewModel(api, session) { 22 })
123
        assertEquals("Good evening, andymccall", d.greeting)
124
        assertNull(d.user)
125
    }
126
127
    @Test
128
    fun aFailureAndARetry() {
129
        api.repositories = { throw HubException.Http(503, "down") }
130
        val vm = DashboardViewModel(api, session) { 9 }
131
        assertTrue(vm.state.value is Load.Failed)
132
        api.repositories = { Fixtures.repos }
133
        vm.refresh()
134
        assertTrue(vm.state.value is Load.Ready)
135
    }
136
137
    @Test
138
    fun greetings() {
139
        assertEquals("Good evening, a", DashboardViewModel.greeting(4, "a"))
140
        assertEquals("Good morning, a", DashboardViewModel.greeting(5, "a"))
141
        assertEquals("Good afternoon, a", DashboardViewModel.greeting(12, "a"))
142
        assertEquals("Good evening, a", DashboardViewModel.greeting(18, "a"))
143
    }
144
}