gitbayTests/DefinitionLinkTests.swift

v1.14.0
gitbay-ios/gitbayTests/DefinitionLinkTests.swift history · blame · raw

99 lines · 4199 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 func argv(_ url: URL) -> [String] {
16    URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.compactMap(\.value) ?? []
17}
18
19struct DefinitionLinkTests {
20
21    private let defs: [String: Definition] = [
22        "Parse": Definition(name: "Parse", count: 1, path: "lib.go", line: 3),
23        "Run": Definition(name: "Run", count: 2, path: "lib.go", line: 4),
24    ]
25
26    @Test func definedNamesLinkAndOthersStayPlain() {
27        let line = Definition.link(AttributedString("\tParse(); Parser(); Run(x)"), definitions: defs)
28
29        let linked = line.runs.compactMap { run -> String? in
30            run.link.map { _ in String(line[run.range].characters) }
31        }
32        // Parser is a different name, not Parse with a tail.
33        #expect(linked == ["Parse", "Run"])
34        #expect(line.runs.compactMap(\.link).map { Definition.name(in: $0) } == ["Parse", "Run"])
35    }
36
37    @Test func aLineWithNoDefinitionsIsUnchanged() {
38        let text = AttributedString("// nothing here")
39        #expect(Definition.link(text, definitions: defs) == text)
40        #expect(Definition.link(AttributedString("Parse"), definitions: [:]) == AttributedString("Parse"))
41    }
42
43    @Test func aDefinitionURLIsOnlyOurs() {
44        #expect(Definition.name(in: URL(string: "https://gitbay.org/x")!) == nil)
45    }
46}
47
48@MainActor
49struct FileDefinitionsTests {
50
51    @Test func theFileReadsTheDefinitionsItUses() async throws {
52        let (client, stub) = try makeClient()
53        stub.enqueue(.init(status: 200, json: """
54            {"protocol_version":1,"data":{"path":"krz/app","ref":"main","file":"use.go","size":10,\
55            "binary":false,"content":"Parse()\\n"},"exit_code":0}
56            """, match: "argv=cat"))
57        stub.enqueue(.init(status: 200, json: """
58            {"protocol_version":1,"data":[{"name":"Parse","count":1,"path":"lib.go","line":3}],"exit_code":0}
59            """, match: "argv=definitions"))
60        let model = FileViewModel(client: client, repoPath: "krz/app", filePath: "use.go", ref: "main")
61
62        await model.load()
63
64        let read = try #require(stub.seen.first { $0.url.absoluteString.contains("argv=definitions") })
65        #expect(argv(read.url) == ["repo", "definitions", "krz/app", "use.go", "--ref", "main"])
66        #expect(model.definitions["Parse"]?.line == 3)
67    }
68
69    /// A server without the command, or a ref that is not indexed, leaves
70    /// the file plain rather than failing it.
71    @Test func noDefinitionsLeaveTheFileReadable() async throws {
72        let (client, stub) = try makeClient()
73        stub.enqueue(.init(status: 200, json: """
74            {"protocol_version":1,"data":{"path":"krz/app","ref":"dev","file":"use.go","size":10,\
75            "binary":false,"content":"Parse()\\n"},"exit_code":0}
76            """, match: "argv=cat"))
77        stub.enqueue(.init(status: 404, json: #"{"protocol_version":1,"error":"only the default branch is indexed","exit_code":3}"#, match: "argv=definitions"))
78        let model = FileViewModel(client: client, repoPath: "krz/app", filePath: "use.go", ref: "dev")
79
80        await model.load()
81
82        #expect(model.state.value?.content == "Parse()\n")
83        #expect(model.definitions.isEmpty)
84    }
85
86    @Test func proseFilesAreNotLinked() async throws {
87        let (client, stub) = try makeClient()
88        stub.enqueue(.init(status: 200, json: """
89            {"protocol_version":1,"data":{"path":"krz/app","ref":"main","file":"README.md","size":10,\
90            "binary":false,"content":"# Parse\\n"},"exit_code":0}
91            """, match: "argv=cat"))
92        let model = FileViewModel(client: client, repoPath: "krz/app", filePath: "README.md", ref: "main")
93
94        await model.load()
95
96        #expect(model.state.value != nil)
97        #expect(!stub.seen.contains { $0.url.absoluteString.contains("argv=definitions") })
98    }
99}