krz/org-swift

A dependency-free Swift library that renders org-mode to sanitized HTML. html library org-mode swift

Tests/OrgSwiftUITests/OrgMathLayoutTests.swift

v0.9.0
org-swift/Tests/OrgSwiftUITests/OrgMathLayoutTests.swift history · blame · raw

88 lines · 3299 bytes

8 symbols in this file
 1import Foundation
 2import SwiftUI
 3import Testing
 4@testable import OrgSwift
 5@testable import OrgSwiftUI
 6
 7@MainActor
 8struct OrgMathLayoutTests {
 9
10    private func layout(_ source: String) -> OrgLayout {
11        OrgLayoutBuilder(options: .init(), styler: PlainOrgCodeStyler(), keywords: .init())
12            .layout(OrgParser.parse(source))
13    }
14
15    @Test func aLatexBlockIsAMathBlock() {
16        let raw = "\\begin{align}\nx &= 1\n\\end{align}"
17        guard case .math(let math) = layout(raw).blocks.first else {
18            Issue.record("expected math, got \(layout(raw).blocks)"); return
19        }
20        #expect(math == OrgMath(tex: raw, display: true, source: raw))
21    }
22
23    @Test func aParagraphThatIsOneDisplayExpressionIsAMathBlock() {
24        guard case .math(let math) = layout(#"\[ x^2 \]"#).blocks.first else {
25            Issue.record("expected math"); return
26        }
27        #expect(math.tex == " x^2 ")
28        guard case .paragraph = layout(#"so \[ x^2 \]"#).blocks.first else {
29            Issue.record("prose around display math keeps the paragraph"); return
30        }
31    }
32
33    @Test func inlineMathIsItsSourceMarkedWithTheExpression() {
34        guard case .paragraph(let text) = layout("a $x$ b").blocks.first else {
35            Issue.record("expected a paragraph"); return
36        }
37        #expect(String(text.characters) == "a $x$ b")
38        let marked = text.runs.compactMap { $0[OrgMathAttribute.self] }
39        #expect(marked == [OrgMath(tex: "x", display: false, source: "$x$")])
40    }
41
42    @Test func anExpressionSplitByATransformDrawsOnce() {
43        let builder = OrgLayoutBuilder(options: .init(), styler: PlainOrgCodeStyler(), keywords: .init(),
44                                       textTransform: { text in
45            if let range = text.range(of: "#1") { text[range].link = URL(string: "https://x.test/1") }
46        })
47        guard case .paragraph(let text) = builder.layout(OrgParser.parse("a $x#1y$ b")).blocks.first else {
48            Issue.record("expected a paragraph"); return
49        }
50        var drawn = 0
51        _ = orgText(text) { _, _ in
52            drawn += 1
53            return Text(verbatim: "·")
54        }
55        #expect(drawn == 1)
56    }
57
58    @Test func theHookIsToldTheStyleOfTheTextAroundIt() {
59        let blocks = layout("* Heading $x$\n\nbody $y$").blocks
60        var styles: [String: Font.TextStyle] = [:]
61        for block in blocks {
62            let text: AttributedString
63            switch block {
64            case .heading(let heading, _): text = heading
65            case .paragraph(let paragraph): text = paragraph
66            default: continue
67            }
68            _ = orgText(text) { math, style in
69                styles[math.tex] = style
70                return Text(verbatim: "·")
71            }
72        }
73        #expect(styles == ["x": .title, "y": .body])
74    }
75
76    @Test func orgTextDrawsEachExpression() {
77        guard case .paragraph(let text) = layout("$x$$x$ and $y$").blocks.first else {
78            Issue.record("expected a paragraph"); return
79        }
80        var drawn: [String] = []
81        _ = orgText(text) { math, _ in
82            drawn.append(math.tex)
83            return Text(verbatim: "·")
84        }
85        #expect(drawn.sorted() == ["x", "y"])
86        _ = orgText(text, math: nil)
87    }
88}