Tests/OrgEditorAppKitTests/MarkupTests.swift
113 lines · 4426 bytes
1import AppKit
2import OrgCore
3import OrgPresentation
4import Testing
5@testable import OrgEditorAppKit
6
7/// Hiding link and emphasis markup, with the caret's line showing it.
8@MainActor
9struct MarkupTests {
10 static let text = "See [[https://example.org][Example]] and =code= here\nsecond line\n"
11
12 func size(_ h: Harness, at offset: Int) -> CGFloat {
13 (h.textView.textStorage!.attribute(.font, at: offset, effectiveRange: nil) as! NSFont).pointSize
14 }
15
16 func x(_ h: Harness, _ offset: Int) -> CGFloat {
17 h.layout()
18 return h.textView.firstRect(forCharacterRange: NSRange(location: offset, length: 1), actualRange: nil).minX
19 }
20
21 @Test func hidesMarkupOffTheCaretLine() {
22 let h = Harness(Self.text)
23 let ns = Self.text as NSString
24 let bracket = ns.range(of: "[[").location
25 let equals = ns.range(of: "=code").location
26 #expect(size(h, at: bracket) > 1)
27
28 h.caret(at: ns.range(of: "second").location)
29 h.editor.options.hideEmphasisMarkers = true
30 h.editor.showMarkup = false
31 h.drainStyling()
32 #expect(size(h, at: bracket) < 1)
33 #expect(size(h, at: equals) < 1)
34 #expect(size(h, at: ns.range(of: "Example").location) > 1)
35 // Hidden text takes no room: "Example" starts right after "See ".
36 let column = x(h, 1) - x(h, 0)
37 #expect(abs(x(h, ns.range(of: "Example").location) - x(h, 0) - 4 * column) < 1)
38
39 h.caret(at: 1)
40 #expect(size(h, at: bracket) > 1)
41 h.caret(at: ns.range(of: "second").location)
42 #expect(size(h, at: bracket) < 1)
43
44 h.editor.showMarkup = true
45 h.drainStyling()
46 #expect(size(h, at: bracket) > 1)
47 }
48
49 @Test func emphasisFollowsTheEmacsSetting() {
50 let h = Harness(Self.text)
51 let ns = Self.text as NSString
52 h.caret(at: ns.range(of: "second").location)
53 h.editor.options.hideEmphasisMarkers = false
54 h.editor.showMarkup = false
55 h.drainStyling()
56 #expect(size(h, at: ns.range(of: "=code").location) > 1)
57 #expect(size(h, at: ns.range(of: "[[").location) < 1)
58 }
59}
60
61@MainActor
62struct LineNumberTests {
63 @Test func marginFollowsTheSettingAndLineCount() {
64 let h = Harness("* a\nb\n")
65 h.editor.showLineNumbers = true
66 let narrow = h.textView.textContainerInset.width
67 #expect(narrow > 0)
68 h.textView.insertText(String(repeating: "x\n", count: 120), replacementRange: NSRange(location: 6, length: 0))
69 #expect(h.textView.textContainerInset.width > narrow)
70 h.editor.showLineNumbers = false
71 #expect(h.textView.textContainerInset.width == 0)
72 }
73}
74
75@MainActor
76struct PrettyEntityTests {
77 @Test func entitiesShowAsCharactersOffTheCaretLine() {
78 let text = "first\nThen \\alpha and x_{1}\n"
79 let h = Harness(text)
80 h.caret(at: 0)
81 h.editor.options.prettyEntities = true
82 h.editor.options.subSuperscriptsNeedBraces = true
83 h.editor.showMarkup = false
84 h.drainStyling()
85 let storage = h.textView.textStorage!
86 let last = (text as NSString).range(of: "\\alpha").location + 5
87 #expect(storage.attribute(.orgEntityDisplay, at: last, effectiveRange: nil) as? String == "α")
88 let one = (text as NSString).range(of: "1}").location
89 #expect((storage.attribute(.baselineOffset, at: one, effectiveRange: nil) as? CGFloat ?? 0) < 0)
90
91 h.caret(at: last)
92 #expect(storage.attribute(.orgEntityDisplay, at: last, effectiveRange: nil) == nil)
93 }
94}
95
96@MainActor
97struct EditorThemeTests {
98 @Test func themeChangesFontAndColors() {
99 let h = Harness("* Heading\nbody\n")
100 var spec = ThemeSpec.default
101 spec.fontSize = 17
102 spec.light["heading-1"] = RGBA(hex: "#ff0000")
103 spec.dark["heading-1"] = RGBA(hex: "#ff0000")
104 spec.todo["WAIT"] = RGBA(hex: "#00ff00")
105 h.editor.themeSpec = spec
106 h.drainStyling()
107 let storage = h.textView.textStorage!
108 #expect((storage.attribute(.font, at: 11, effectiveRange: nil) as? NSFont)?.pointSize == 17)
109 let color = (storage.attribute(.foregroundColor, at: 3, effectiveRange: nil) as? NSColor)?.usingColorSpace(.sRGB)
110 #expect(color.map { ($0.redComponent * 255).rounded() } == 255)
111 #expect((storage.attribute(.font, at: 3, effectiveRange: nil) as? NSFont)?.pointSize == 20)
112 }
113}