| 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 aRefusalShowsTheHubsReason() { |
| 65 |
api.land = { throw HubException.Http(409, "required checks not passed on the projected state: test") } |
| 66 |
val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300) |
| 67 |
vm.land() |
| 68 |
assertEquals(LandAction.Failed("required checks not passed on the projected state: test"), vm.action.value) |
| 69 |
assertEquals("open", page(vm).proposal.state) |
| 70 |
vm.dismiss() |
| 71 |
assertEquals(LandAction.Idle, vm.action.value) |
| 72 |
} |
| 73 |
|
| 74 |
@Test |
| 75 |
fun aReadOnlyTokenIsAskedToSignInAgain() { |
| 76 |
api.land = { throw HubException.Http(403, "this token lacks the repo:write scope") } |
| 77 |
val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 300) |
| 78 |
vm.land() |
| 79 |
val f = vm.action.value as LandAction.Failed |
| 80 |
assertTrue(f.needsWrite) |
| 81 |
// Another 403 is not about the scope. |
| 82 |
assertFalse(ProposalViewModel.failure(HubException.Http(403, "only maintainers may land over checks")).needsWrite) |
| 83 |
} |
| 84 |
|
| 85 |
@Test |
| 86 |
fun autoLandIsSetAndCleared() { |
| 87 |
val vm = ProposalViewModel(api, "andymccall", "oxygenhub", 301) |
| 88 |
assertEquals("andymccall", page(vm).proposal.autoLand) |
| 89 |
val cleared = api.autoLand(301, false) |
| 90 |
api.proposal = { cleared } |
| 91 |
vm.setAutoLand(false) |
| 92 |
assertEquals(LandAction.Done("#301 will not land by itself."), vm.action.value) |
| 93 |
assertNull(page(vm).proposal.autoLand) |
| 94 |
assertTrue("auto-land 301 false" in api.calls) |
| 95 |
} |
| 96 |
|
| 97 |
@Test |
| 98 |
fun aSessionMayWriteOnlyWithTheScope() { |
| 99 |
assertTrue(Session("h", "u", "t", listOf("repo:read", "repo:write")).canWrite) |
| 100 |
assertFalse(Session("h", "u", "t", listOf("repo:read", "user:read")).canWrite) |
| 101 |
// The hub did not say: let it decide. |
| 102 |
assertTrue(Session("h", "u", "t").canWrite) |
| 103 |
} |
| 104 |
} |