OXYGENHUB
◆ main oxygenhub-android / app / src / test / java / io / oxygenhub / android / ui / WidgetDataTest.kt
6.3 KiB · last changed The widget: Needs you (the top review and newest assigned issue) and a Flow health strip of the last 30 runs; the mark in its own colours (closes #33) 3 days ago source blame history raw
1
package io.oxygenhub.android.ui
2
3
import io.oxygenhub.android.FakeHubApi
4
import io.oxygenhub.android.api.FlowRun
5
import io.oxygenhub.android.api.HubException
6
import io.oxygenhub.android.api.UserFlowRun
7
import io.oxygenhub.android.api.UserSky
8
import io.oxygenhub.android.api.IssueBrief
9
import io.oxygenhub.android.ui.nav.AccountRoute
10
import io.oxygenhub.android.ui.nav.DashboardRoute
11
import io.oxygenhub.android.ui.nav.InboxRoute
12
import io.oxygenhub.android.ui.nav.IssueRoute
13
import io.oxygenhub.android.ui.nav.ProposalRoute
14
import io.oxygenhub.android.widget.HealthStrip
15
import io.oxygenhub.android.widget.SkyBitmap
16
import io.oxygenhub.android.widget.WidgetData
17
import io.oxygenhub.android.widget.WidgetTaps
18
import io.oxygenhub.android.widget.runnerLine
19
import kotlinx.coroutines.test.runTest
20
import org.junit.Assert.assertEquals
21
import org.junit.Assert.assertFalse
22
import org.junit.Assert.assertNotEquals
23
import org.junit.Assert.assertNull
24
import org.junit.Assert.assertTrue
25
import org.junit.Test
26
27
class WidgetDataTest {
28
    @Test
29
    fun theWidgetShowsTheLatestRunsAndCountsAndAsksForASignInWithoutOne() = runTest {
30
        val api = FakeHubApi()
31
        api.userFlowRuns = { (1L..5L).map { UserFlowRun("andy/a", FlowRun(number = it, status = "passed")) } }
32
        val d = WidgetData.load(api)
33
        assertEquals(listOf(1L, 2L, 3L), d.runs.map { it.run.number })
34
        assertEquals(1, d.reviews)
35
        assertFalse(WidgetData.load(null).signedIn)
36
    }
37
38
    @Test
39
    fun aPartTheHubCannotGiveIsLeftOutNotTheWholeWidget() = runTest {
40
        val api = FakeHubApi()
41
        api.userFlowRuns = { throw HubException.Http(404, "no such API route") }
42
        val d = WidgetData.load(api)
43
        assertEquals(emptyList<UserFlowRun>(), d.runs)
44
        assertEquals(1, d.reviews)
45
        api.userProposals = { throw HubException.Http(500, "down") }
46
        assertNull(WidgetData.load(api).reviews)
47
    }
48
49
    @Test
50
    fun theWidgetFetchesYourSkyAndALostSkyLeavesThePlainSurface() = runTest {
51
        val api = FakeHubApi()
52
        val sky = UserSky(now = 10 * 86_400_000L, repos = listOf("andy/a"), events = listOf(listOf(0L, 0L, 9 * 86_400_000L, 3L)))
53
        api.userSky = { sky }
54
        assertEquals(sky, WidgetData.load(api).sky)
55
        api.userSky = { throw HubException.Http(404, "no such API route") }
56
        val d = WidgetData.load(api)
57
        assertNull(d.sky)
58
        assertEquals(1, d.reviews)
59
    }
60
61
    @Test
62
    fun onlyRealActivityIsDrawn() {
63
        assertFalse("nothing fetched", SkyBitmap.drawable(null))
64
        assertFalse("no repositories", SkyBitmap.drawable(UserSky()))
65
        assertFalse("repositories but no events", SkyBitmap.drawable(UserSky(repos = listOf("andy/a"))))
66
        assertFalse("only malformed events", SkyBitmap.drawable(UserSky(repos = listOf("andy/a"), events = listOf(listOf(7L, 0L, 0L, 1L)))))
67
        assertTrue(SkyBitmap.drawable(UserSky(now = 1, repos = listOf("andy/a"), events = listOf(listOf(0L, 4L, 0L, 1L)))))
68
    }
69
70
    @Test
71
    fun theSkysColoursFollowTheTheme() {
72
        val (light, dark) = SkyBitmap.colours(false) to SkyBitmap.colours(true)
73
        assertEquals(24, light.size)
74
        assertEquals(24, dark.size)
75
        assertNotEquals(light, dark)
76
        assertTrue("every channel is a fraction", (light + dark).all { it in 0f..1f })
77
    }
78
79
    @Test
80
    fun theCountsRowSaysWhatIsAssignedAndOneOfAKindOpensItself() = runTest {
81
        val api = FakeHubApi()
82
        val d = WidgetData.load(api)
83
        assertEquals(1, d.assigned)
84
        assertEquals(359L, d.onlyAssigned?.number)
85
        assertEquals(300L, d.onlyReview?.number)
86
        api.userIssues = { listOf(IssueBrief("andy/a", 1), IssueBrief("andy/a", 2)) }
87
        val two = WidgetData.load(api)
88
        assertEquals(2, two.assigned)
89
        assertNull("two open the dashboard, not one of them", two.onlyAssigned)
90
        api.userIssues = { throw HubException.Http(404, "no such API route") }
91
        val old = WidgetData.load(api)
92
        assertNull("a hub before /user/issues: the count is left out", old.assigned)
93
        assertEquals(1, old.reviews)
94
    }
95
96
    @Test
97
    fun theRunnerShowsOnlyWhileThePhoneServes() = runTest {
98
        val api = FakeHubApi()
99
        assertNull(WidgetData.load(api).runnerJobs)
100
        assertEquals(listOf("andy/a #7 test"), WidgetData.load(api, listOf("andy/a #7 test")).runnerJobs)
101
        assertEquals("Waiting for jobs", runnerLine(emptyList()))
102
        assertEquals("andy/a #7 test", runnerLine(listOf("andy/a #7 test")))
103
        assertEquals("2 jobs", runnerLine(listOf("andy/a #7 test", "andy/b #2 build")))
104
    }
105
106
    @Test
107
    fun aTapOnACountOpensItsScreen() {
108
        assertEquals(InboxRoute, WidgetTaps.route("inbox", "", 0))
109
        assertEquals(DashboardRoute, WidgetTaps.route("dashboard", "", 0))
110
        assertEquals(AccountRoute, WidgetTaps.route("account", "", 0))
111
        assertEquals(ProposalRoute("andy", "a", 3), WidgetTaps.route("proposal", "andy/a", 3))
112
        assertEquals(IssueRoute("andy", "a", 4), WidgetTaps.route("issue", "andy/a", 4))
113
        assertEquals("a broken reference falls back to the dashboard", DashboardRoute, WidgetTaps.route("issue", "nonsense", 4))
114
        assertNull("not from the widget", WidgetTaps.route(null, null, 0))
115
    }
116
117
    @Test
118
    fun needsYouAndTheHealthStripComeFromWhatTheWidgetFetches() = runTest {
119
        val api = FakeHubApi()
120
        val statuses = listOf("running", "passed", "failed", "cancelled", "passed", "passed")
121
        api.userFlowRuns = { statuses.mapIndexed { i, st -> UserFlowRun("andy/a", FlowRun(number = 10L - i, status = st)) } }
122
        val d = WidgetData.load(api)
123
        assertEquals(300L, d.topReview?.number)
124
        assertEquals(359L, d.topAssigned?.number)
125
        assertEquals("all the runs fetched, not just the three shown", statuses, d.health)
126
        assertEquals(3, d.runs.size)
127
    }
128
129
    @Test
130
    fun theHealthSummaryCountsFinishedRunsOnly() {
131
        assertEquals("75% of the last 4 finished runs passed", HealthStrip.summary(listOf("running", "passed", "failed", "cancelled", "passed", "passed")))
132
        assertEquals("100% of the last finished run passed", HealthStrip.summary(listOf("passed", "queued")))
133
        assertNull("nothing finished", HealthStrip.summary(listOf("running", "cancelled")))
134
        assertNull(HealthStrip.summary(emptyList()))
135
        assertEquals(HealthStrip.Kind.Failed, HealthStrip.kind("error"))
136
    }
137
}