krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Tests/OrgCoreTests/SparseTreeTests.swift

3a3dedba062790e1580c66d38606eda4b02cb501
orgstar/Tests/OrgCoreTests/SparseTreeTests.swift history · blame · raw

78 lines · 3962 bytes

 1import Foundation
 2import Testing
 3@testable import OrgCore
 4
 5struct SparseTreeTests {
 6    static let oracle = ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil
 7    static let seconds = 1_789_000_000
 8
 9    static let text = """
10        Preamble text
11        * TODO Alpha :work:
12        alpha body with foo
13        ** DONE Beta
14        beta body
15        ** TODO Gamma :home:
16        DEADLINE: <2026-09-15 Tue>
17        gamma Foo
18        *** Delta
19        SCHEDULED: <2026-09-01 Tue>
20        delta
21        **** Deep
22        deep text
23        * Epsilon :ARCHIVE:
24        ** Zeta foo
25        * DONE Eta
26        DEADLINE: <2026-08-01 Sat>
27        * Theta
28        SCHEDULED: <2026-10-01 Thu 10:00>
29        theta
30
31        * TODO Iota
32        DEADLINE: <2026-11-30 Mon>
33        """ + "\n"
34
35    @Test(.enabled(if: oracle))
36    func buildsSparseTreesLikeOrg() throws {
37        var utc = Calendar(identifier: .gregorian)
38        utc.timeZone = TimeZone(identifier: "UTC")!
39        let now = Date(timeIntervalSince1970: Double(Self.seconds))
40        let tree = OrgParser.parse(Self.text)
41        let cases: [(String, SparseTree.Matches)] = [
42            ("(org-occur \"foo\")", try SparseTree.occur("foo", in: Self.text)),
43            ("(org-occur \"^\\\\*+ .*a$\")", try SparseTree.occur("^\\*+ .*a$", in: Self.text)),
44            ("(org-show-todo-tree nil)", SparseTree.todo(nil, in: Self.text, settings: tree.settings)),
45            ("(org-match-sparse-tree nil \"home|work\")", SparseTree.match("home|work", in: Self.text, now: now, calendar: utc)),
46            ("(org-match-sparse-tree nil \"LEVEL>2\")", SparseTree.match("LEVEL>2", in: Self.text, now: now, calendar: utc)),
47            ("(org-check-deadlines nil)", SparseTree.deadlines(within: 14, in: Self.text, settings: tree.settings, now: now, calendar: utc)),
48            ("(org-check-before-date \"2026-09-20\")", SparseTree.planning(from: nil, to: "2026-09-20", in: Self.text, calendar: utc)),
49            ("(org-check-after-date \"2026-09-20\")", SparseTree.planning(from: "2026-09-20", to: nil, in: Self.text, calendar: utc)),
50            ("(org-check-dates-range \"2026-09-01\" \"2026-10-01 10:00\")", SparseTree.planning(from: "2026-09-01", to: "2026-10-01 10:00", in: Self.text, calendar: utc)),
51        ]
52        let forms = cases.map { form, _ in
53            frozenClock(Self.seconds, """
54                (with-current-buffer (find-file-noselect "oracle.org")
55                  (org-fold-show-all) \(form)
56                  (list (mapconcat (lambda (o) (format "%d-%d" (1- (overlay-start o)) (1- (overlay-end o))))
57                                   (sort (copy-sequence org-occur-highlights) (lambda (a b) (< (overlay-start a) (overlay-start b)))) " ")
58                        (let (vis) (goto-char (point-min))
59                          (while (not (eobp)) (push (if (if (eolp) (and (not (bobp)) (org-invisible-p (1- (point)))) (org-invisible-p (point))) "0" "1") vis) (forward-line 1))
60                          (apply #'concat (nreverse vis)))))
61                """)
62        }
63        let emacs = try EmacsOracle.evaluate(Self.text, "(apply (function append) (list \(forms.joined(separator: " "))))", prelude: "(setenv \"TZ\" \"UTC0\")")
64        for (i, (form, matches)) in cases.enumerated() {
65            let hidden = SparseTree.hidden(matches.points, in: Self.text, tree: tree)
66            let ns = Self.text as NSString
67            var visibility = ""
68            var offset = 0
69            while offset < ns.length {
70                visibility += hidden.contains { $0.contains(offset) } ? "0" : "1"
71                offset = NSMaxRange(ns.lineRange(for: NSRange(location: offset, length: 0)))
72            }
73            let highlights = matches.highlights.map { "\($0.lowerBound)-\($0.upperBound)" }.joined(separator: " ")
74            #expect(highlights == emacs[2 * i], "\(form) highlights")
75            #expect(visibility == emacs[2 * i + 1], "\(form) visibility")
76        }
77    }
78}