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