OXYGENHUB
# 797eca1a3e64 oxygenhub-android / app / src / test / java / io / oxygenhub / android / ui / ProposalViewModelTest.kt
4.5 KiB · last changed Review a proposal from the phone: approve, request changes or comment from its Reviews section (refs #4) 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.MainDispatcherRule
5
import io.oxygenhub.android.api.HubException
6
import io.oxygenhub.android.api.ProposalState
7
import io.oxygenhub.android.auth.Session
8
import io.oxygenhub.android.ui.common.Load
9
import io.oxygenhub.android.ui.proposals.LandAction
10
import io.oxygenhub.android.ui.proposals.ProposalPage
11
import io.oxygenhub.android.ui.proposals.ProposalViewModel
12
import io.oxygenhub.android.ui.proposals.ProposalsViewModel
13
import org.junit.Assert.assertEquals
14
import org.junit.Assert.assertFalse
15
import org.junit.Assert.assertNull
16
import org.junit.Assert.assertTrue
17
import org.junit.Rule
18
import org.junit.Test
19
20
class ProposalViewModelTest {
21
    @get:Rule val main = MainDispatcherRule()
22
23
    private val api = FakeHubApi()
24
25
    private fun page(vm: ProposalViewModel): ProposalPage = (vm.state.value as Load.Ready).value
26
27
    @Test
28
    fun listsOpenProposalsNewestFirstAndTheLandedOnAsked() {
29
        val vm = ProposalsViewModel(api, "andymccall", "oxygenhub")
30
        assertEquals(listOf(301L, 300L), (vm.state.value as Load.Ready).value.map { it.number })
31
        vm.setFilter(ProposalState.Landed)
32
        assertEquals(listOf(264L), (vm.state.value as Load.Ready).value.map { it.number })
33
        assertTrue("proposals andymccall/oxygenhub landed" in api.calls)
34
    }
35
36
    @Test
37
    fun showsAProposalWithItsChecks() {
38
        val p = page(ProposalViewModel(api, "andymccall", "oxygenhub", 300))
39
        assertTrue(p.proposal.landable)
40
        assertEquals(5, p.checks?.size)
41
    }
42
43
    @Test
44
    fun withoutItsChecksTheProposalStillShows() {
45
        api.checks = { throw HubException.Http(500, "down") }
46
        val p = page(ProposalViewModel(api, "andymccall", "oxygenhub", 300))
47
        assertNull(p.checks)
48
        assertEquals(300L, p.proposal.number)
49
    }
50
51
    @Test
52
    fun landingSaysSoAndShowsItLanded() {
53
        val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300)
54
        // The hub's answer after landing, as the refresh will read it.
55
        val landed = api.land(300)
56
        api.proposal = { landed }
57
        vm.land()
58
        assertEquals(LandAction.Done("Landed #300 into main."), vm.action.value)
59
        assertEquals("landed", page(vm).proposal.state)
60
        assertTrue("land 300" in api.calls)
61
    }
62
63
    @Test
64
    fun aReviewIsSentAndSaysSo() {
65
        val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300)
66
        vm.review("changes", "  Needs a test  ")
67
        assertTrue("review changes Needs a test" in api.calls)
68
        assertEquals(LandAction.Done("Asked for changes on #300."), vm.action.value)
69
        vm.dismiss()
70
        vm.review("approve", "")
71
        assertEquals(LandAction.Done("Approved #300."), vm.action.value)
72
    }
73
74
    @Test
75
    fun aRefusalShowsTheHubsReason() {
76
        api.land = { throw HubException.Http(409, "required checks not passed on the projected state: test") }
77
        val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300)
78
        vm.land()
79
        assertEquals(LandAction.Failed("required checks not passed on the projected state: test"), vm.action.value)
80
        assertEquals("open", page(vm).proposal.state)
81
        vm.dismiss()
82
        assertEquals(LandAction.Idle, vm.action.value)
83
    }
84
85
    @Test
86
    fun aReadOnlyTokenIsAskedToSignInAgain() {
87
        api.land = { throw HubException.Http(403, "this token lacks the repo:write scope") }
88
        val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300)
89
        vm.land()
90
        val f = vm.action.value as LandAction.Failed
91
        assertTrue(f.needsWrite)
92
        // Another 403 is not about the scope.
93
        assertFalse(ProposalViewModel.failure(HubException.Http(403, "only maintainers may land over checks")).needsWrite)
94
    }
95
96
    @Test
97
    fun autoLandIsSetAndCleared() {
98
        val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 301)
99
        assertEquals("andymccall", page(vm).proposal.autoLand)
100
        val cleared = api.autoLand(301, false)
101
        api.proposal = { cleared }
102
        vm.setAutoLand(false)
103
        assertEquals(LandAction.Done("#301 will not land by itself."), vm.action.value)
104
        assertNull(page(vm).proposal.autoLand)
105
        assertTrue("auto-land 301 false" in api.calls)
106
    }
107
108
    @Test
109
    fun aSessionMayWriteOnlyWithTheScope() {
110
        assertTrue(Session("h", "u", "t", listOf("repo:read", "repo:write")).canWrite)
111
        assertFalse(Session("h", "u", "t", listOf("repo:read", "user:read")).canWrite)
112
        // The hub did not say: let it decide.
113
        assertTrue(Session("h", "u", "t").canWrite)
114
    }
115
}