a native ios client for gitbay

client ios swift

https://gitbay.org

gitbayTests/WikiTests.swift

110 lines · 3896 bytes

  1import Foundation
  2import Testing
  3@testable import gitbay
  4
  5private func makeClient() throws -> (GitbayClient, StubProtocol.Box) {
  6    let box = StubProtocol.box()
  7    let client = GitbayClient(
  8        instance: try GitbayInstance(url: "https://gitbay.org"),
  9        token: "test-token",
 10        session: box.session()
 11    )
 12    return (client, box)
 13}
 14
 15private let listingJSON = """
 16    {"protocol_version":1,"data":{"path":"krz/gitbay","home":"Home",\
 17    "pages":["API","Admin","Home","Parity"]},"exit_code":0}
 18    """
 19
 20@MainActor
 21struct WikiViewModelTests {
 22
 23    @Test func listsPagesAndNamesTheLandingPage() async throws {
 24        let (client, stub) = try makeClient()
 25        stub.enqueue(.init(status: 200, json: listingJSON))
 26        let model = WikiViewModel(client: client, repoPath: "krz/gitbay")
 27
 28        await model.load()
 29
 30        let listing = try #require(model.state.value)
 31        #expect(listing.home == "Home")
 32        #expect(listing.pages == ["API", "Admin", "Home", "Parity"])
 33        #expect(stub.seen.first?.url.query() == "argv=wiki&argv=list&argv=krz/gitbay")
 34    }
 35
 36    @Test func aRepoWithoutAWikiIsAnEmptyState() async throws {
 37        let (client, stub) = try makeClient()
 38        stub.enqueue(.init(status: 404, json:
 39            #"{"protocol_version":1,"error":"krz/quiet has no wiki","exit_code":3}"#))
 40        let model = WikiViewModel(client: client, repoPath: "krz/quiet")
 41
 42        await model.load()
 43
 44        guard case .empty(let message) = model.state else {
 45            Issue.record("expected .empty, got \(model.state)")
 46            return
 47        }
 48        #expect(message.contains("no wiki"))
 49    }
 50
 51    @Test func anEmptyWikiIsAnEmptyStateNotAList() async throws {
 52        let (client, stub) = try makeClient()
 53        stub.enqueue(.init(status: 200, json:
 54            #"{"protocol_version":1,"data":{"path":"krz/gitbay","pages":[]},"exit_code":0}"#))
 55        let model = WikiViewModel(client: client, repoPath: "krz/gitbay")
 56
 57        await model.load()
 58
 59        guard case .empty = model.state else {
 60            Issue.record("expected .empty, got \(model.state)")
 61            return
 62        }
 63    }
 64}
 65
 66@MainActor
 67struct WikiPageViewModelTests {
 68
 69    @Test func loadsAPageAndKeepsItsFileName() async throws {
 70        let (client, stub) = try makeClient()
 71        stub.enqueue(.init(status: 200, json: """
 72            {"protocol_version":1,"data":{"path":"krz/gitbay","page":"Parity",\
 73            "file":"Parity.org","size":11,"content":"#+title: x"},"exit_code":0}
 74            """))
 75        let model = WikiPageViewModel(client: client, repoPath: "krz/gitbay", page: "Parity")
 76
 77        await model.load()
 78
 79        let page = try #require(model.state.value)
 80        // The file name is what picks the renderer, so it must survive.
 81        #expect(page.file == "Parity.org")
 82        #expect(page.content == "#+title: x")
 83        #expect(stub.seen.first?.url.query() ==
 84            "argv=wiki&argv=show&argv=krz/gitbay&argv=Parity")
 85    }
 86
 87    @Test func aMissingPageIsAnEmptyState() async throws {
 88        let (client, stub) = try makeClient()
 89        stub.enqueue(.init(status: 404, json:
 90            #"{"protocol_version":1,"error":"no wiki page \"Nope\" in krz/gitbay","exit_code":3}"#))
 91        let model = WikiPageViewModel(client: client, repoPath: "krz/gitbay", page: "Nope")
 92
 93        await model.load()
 94
 95        guard case .empty = model.state else {
 96            Issue.record("expected .empty, got \(model.state)")
 97            return
 98        }
 99    }
100}
101
102struct WikiRenderingTests {
103
104    @Test func orgPagesGetTheOrgRendererAndMarkdownPagesDoNot() {
105        // Wiki pages here are .org as often as .md; the file name decides.
106        #expect(ReadmeView(name: "Parity.org", content: "* x").isOrg)
107        #expect(!ReadmeView(name: "Home.md", content: "# x").isOrg)
108        #expect(!ReadmeView(name: "Notes.markdown", content: "# x").isOrg)
109    }
110}