OXYGENHUB
# 1823bc12eda1 oxygenhub-android / app / src / test / java / io / oxygenhub / android / ui / CodeBrowserTest.kt
5.0 KiB · last changed Diffs on a change, natively 10 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.ChangeDetail
6
import io.oxygenhub.android.api.ChangeSummary
7
import io.oxygenhub.android.api.FileChange
8
import io.oxygenhub.android.api.HubJson
9
import io.oxygenhub.android.api.History
10
import io.oxygenhub.android.api.TreeEntry
11
import io.oxygenhub.android.ui.code.CodeViewModel
12
import io.oxygenhub.android.ui.code.HistoryViewModel
13
import io.oxygenhub.android.ui.code.languageOf
14
import io.oxygenhub.android.ui.code.openByDefault
15
import io.oxygenhub.android.ui.common.Load
16
import dev.snipme.highlights.model.SyntaxLanguage
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 CodeBrowserTest {
25
    @get:Rule val main = MainDispatcherRule()
26
27
    private val api = FakeHubApi()
28
29
    private fun <T> ready(load: Load<T>): T = (load as Load.Ready).value
30
31
    private val top = listOf(
32
        TreeEntry("src", "src", "dir"),
33
        TreeEntry("README.md", "README.md", "file", size = 12),
34
        TreeEntry("Cargo.toml", "Cargo.toml", "file"),
35
        TreeEntry("assets", "assets", "dir"),
36
    )
37
38
    @Test
39
    fun startsAtTheDefaultBookmarkFoldersFirstWithTheReadme() {
40
        api.repository = api.repository.copy(defaultBookmark = "trunk")
41
        api.tree = { _, path -> if (path.isEmpty()) top else listOf(TreeEntry("main.rs", "src/main.rs")) }
42
        api.files = mapOf("README.md" to "# Demo")
43
        val vm = CodeViewModel(api, "andymccall", "demo")
44
        val dir = ready(vm.state.value)
45
        assertEquals("trunk", vm.ref.value)
46
        assertEquals(listOf("assets", "src", "Cargo.toml", "README.md"), dir.entries.map { it.name })
47
        assertEquals("# Demo", dir.readme?.text)
48
        assertTrue("tree trunk:" in api.calls)
49
50
        vm.open("src")
51
        assertEquals(listOf("main.rs"), ready(vm.state.value).entries.map { it.name })
52
        assertNull("no README here", ready(vm.state.value).readme)
53
        assertTrue(vm.up())
54
        assertEquals("", vm.path.value)
55
        assertFalse("already at the top", vm.up())
56
    }
57
58
    @Test
59
    fun aReadmeThatWillNotLoadIsLeftOut() {
60
        api.tree = { _, _ -> top }
61
        val dir = ready(CodeViewModel(api, "andymccall", "demo", "main").state.value)
62
        assertNull(dir.readme)
63
        assertEquals(4, dir.entries.size)
64
    }
65
66
    @Test
67
    fun anotherBookmarkOrTagIsBrowsedFromItsTop() {
68
        api.tree = { ref, _ -> if (ref == "v1.0") listOf(TreeEntry("OLD", "OLD")) else top }
69
        api.refs = listOf("main", "develop") to listOf("v1.0")
70
        val vm = CodeViewModel(api, "andymccall", "demo", "main")
71
        vm.loadRefs()
72
        assertEquals(listOf("main", "develop") to listOf("v1.0"), ready(vm.refs.value))
73
        vm.setRef("v1.0")
74
        assertEquals(listOf("OLD"), ready(vm.state.value).entries.map { it.name })
75
    }
76
77
    @Test
78
    fun historyComesAPageAtATime() {
79
        val c = { n: Int -> ChangeSummary("%064x".format(n), "change $n\n\nbody") }
80
        api.history = History("main", total = 3, changes = listOf(c(1), c(2)))
81
        val vm = HistoryViewModel(api, "andymccall", "demo", "main", "src/main.rs")
82
        assertEquals(listOf("change 1", "change 2"), ready(vm.state.value).changes.map { it.subject })
83
        assertTrue(ready(vm.state.value).hasMore)
84
        assertTrue("history main:src/main.rs" in api.calls)
85
        api.history = History("main", total = 3, offset = 2, changes = listOf(c(3)))
86
        vm.more()
87
        assertEquals(3, ready(vm.state.value).changes.size)
88
        assertFalse(ready(vm.state.value).hasMore)
89
    }
90
91
    @Test
92
    fun filesAreHighlightedByTheirNames() {
93
        assertEquals(SyntaxLanguage.RUST, languageOf("crates/hub/src/main.rs"))
94
        assertEquals(SyntaxLanguage.KOTLIN, languageOf("app/build.gradle.kts"))
95
        assertEquals(SyntaxLanguage.SHELL, languageOf("Makefile"))
96
        assertEquals(SyntaxLanguage.DEFAULT, languageOf("pipeline.kdl"))
97
    }
98
99
    @Test
100
    fun aChangeCarriesItsDiffAndSmallOnesOpen() {
101
        val json = """{"change":{"hash":"ab","message":"grow a"},"files":[{"path":"a.txt","kind":"modified","added":1,"removed":1,
102
            "lines":[{"kind":"context","old":1,"new":1,"text":"a"},{"kind":"del","old":2,"text":"b"},{"kind":"add","new":2,"text":"c"},{"kind":"gap"}]}]}"""
103
        val d = HubJson.decodeFromString(ChangeDetail.serializer(), json)
104
        val f = d.files.single()
105
        assertEquals(listOf("context", "del", "add", "gap"), f.lines.map { it.kind })
106
        assertEquals(2 to null, f.lines[1].old to f.lines[1].new)
107
        assertFalse(f.truncated)
108
        assertEquals(setOf("a.txt"), openByDefault(d.files))
109
        val many = (1..6).map { FileChange("f$it") }
110
        assertTrue("a change of many files starts folded", openByDefault(many).isEmpty())
111
        val old = HubJson.decodeFromString(ChangeDetail.serializer(), """{"change":{"hash":"ab"},"files":[{"path":"a.txt"}]}""")
112
        assertTrue("a hub before #320 sends no lines", old.files.single().lines.isEmpty())
113
    }
114
}