gitbayTests/MarkdownTests.swift

v1.6.0
gitbay-ios/gitbayTests/MarkdownTests.swift history · blame · raw

137 lines · 4560 bytes

  1import Foundation
  2import OrgSwift
  3import Testing
  4@testable import gitbay
  5
  6@MainActor
  7struct MarkdownTableTests {
  8
  9    private func blocks(_ markdown: String) -> [MarkdownView.Block] {
 10        MarkdownView(markdown: markdown).blocks
 11    }
 12
 13    @Test func headerSeparatorAndBodyBecomeATable() {
 14        let parsed = blocks("""
 15            | Add | Documented in |
 16            |---|---|
 17            | An RSS feed | [Collections](https://orgo.krz.sh/) |
 18            """)
 19        #expect(parsed == [.table(MarkdownView.Table(
 20            header: ["Add", "Documented in"],
 21            rows: [["An RSS feed", "[Collections](https://orgo.krz.sh/)"]],
 22            alignments: [.leading, .leading]
 23        ))])
 24    }
 25
 26    @Test func alignmentComesFromTheSeparatorRow() {
 27        let parsed = blocks("""
 28            | l | c | r |
 29            |:--|:-:|--:|
 30            | a | b | c |
 31            """)
 32        guard case .table(let table) = parsed.first else {
 33            Issue.record("expected a table, got \(parsed)")
 34            return
 35        }
 36        #expect(table.alignments == [.leading, .center, .trailing])
 37    }
 38
 39    @Test func outerPipesAreOptionalAndEscapedPipesStayInTheCell() {
 40        let parsed = blocks("""
 41            a | b
 42            --- | ---
 43            x \\| y | z
 44            """)
 45        guard case .table(let table) = parsed.first else {
 46            Issue.record("expected a table, got \(parsed)")
 47            return
 48        }
 49        #expect(table.header == ["a", "b"])
 50        #expect(table.rows == [["x \\| y", "z"]])
 51    }
 52
 53    @Test func raggedRowsArePaddedToTheHeaderWidth() {
 54        let parsed = blocks("""
 55            | a | b | c |
 56            |---|---|---|
 57            | 1 |
 58            | 1 | 2 | 3 | 4 |
 59            """)
 60        guard case .table(let table) = parsed.first else {
 61            Issue.record("expected a table, got \(parsed)")
 62            return
 63        }
 64        #expect(table.rows == [["1", "", ""], ["1", "2", "3"]])
 65    }
 66
 67    @Test func aTableEndsAtABlankLineAndTheTextAfterItIsAParagraph() {
 68        let parsed = blocks("""
 69            | a |
 70            |---|
 71            | 1 |
 72
 73            After the table.
 74            """)
 75        #expect(parsed.count == 2)
 76        #expect(parsed.last == .paragraph("After the table."))
 77    }
 78
 79    @Test func aTableInterruptsThePrecedingParagraph() {
 80        let parsed = blocks("""
 81            Each of these has a page in the guide:
 82            | a |
 83            |---|
 84            | 1 |
 85            """)
 86        #expect(parsed.first == .paragraph("Each of these has a page in the guide:"))
 87        #expect(parsed.count == 2)
 88    }
 89
 90    @Test func aPipeInProseIsNotATable() {
 91        let parsed = blocks("Run `a | b` to pipe.\nIt is not a table.")
 92        #expect(parsed == [.paragraph("Run `a | b` to pipe. It is not a table.")])
 93    }
 94}
 95
 96@MainActor
 97struct MarkdownLinkTests {
 98
 99    private let options = OrgRenderOptions(
100        host: "gitbay.org",
101        owner: "krz",
102        repositoryName: "org-swift",
103        ref: "HEAD",
104        readmePath: "README.md",
105        imagePathSegment: "raw",
106        linkPathSegment: "blob"
107    )
108
109    private func links(_ markdown: String, options: OrgRenderOptions?) -> [String] {
110        MarkdownView.attributed(markdown, linkOptions: options)
111            .runs.compactMap { $0.link?.absoluteString }
112    }
113
114    /// A relative target resolves to the repository's file page. Left alone it is a
115    /// scheme-less URL, which renders styled and does nothing when tapped.
116    @Test func relativeTargetsResolveAgainstTheRepository() {
117        #expect(links("See [ARCHITECTURE.md](ARCHITECTURE.md).", options: options)
118            == ["https://gitbay.org/krz/org-swift/blob/HEAD/ARCHITECTURE.md"])
119        #expect(links("[gaps](./GAPS.md)", options: options)
120            == ["https://gitbay.org/krz/org-swift/blob/HEAD/GAPS.md"])
121        #expect(links("[corpus](../org-conformance)", options: options)
122            == ["https://gitbay.org/krz/org-swift/blob/HEAD/org-conformance"])
123        #expect(links("[docs](/docs/x.md)", options: options)
124            == ["https://gitbay.org/krz/org-swift/blob/HEAD/docs/x.md"])
125    }
126
127    @Test func absoluteTargetsAreUntouched() {
128        #expect(links("[home](https://example.com/a)", options: options)
129            == ["https://example.com/a"])
130    }
131
132    /// A body with no file to be relative to keeps its targets as authored.
133    @Test func withoutOptionsTargetsAreLeftAlone() {
134        #expect(links("See [ARCHITECTURE.md](ARCHITECTURE.md).", options: nil)
135            == ["ARCHITECTURE.md"])
136    }
137}