krz/orgstar

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

Tests/OrgCoreTests/PropertyTests.swift

main
orgstar/Tests/OrgCoreTests/PropertyTests.swift history · blame · raw

75 lines · 3824 bytes

4 symbols in this file
 1import Foundation
 2import Testing
 3@testable import OrgCore
 4
 5struct PropertyTests {
 6    static let texts = [
 7        "* TODO Task\n",
 8        "* TODO Task\nBody\n",
 9        "* Task\nSCHEDULED: <2026-10-05 Mon>\nBody\n",
10        "* Task\n:PROPERTIES:\n:OWNER: alice\n:SIZE:     3\n:END:\nBody\n",
11        "* Task :tag:\n:PROPERTIES:\n:ID: x\n:END:\n** Child\n",
12        "* DONE Old\n* TODO Repeat\nSCHEDULED: <2026-10-05 Mon +1w>\n",
13        "* Task",
14    ]
15
16    @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil))
17    func matchesEmacs() throws {
18        let edits: [(any OrgCommand, String)] = [
19            (SetProperty(key: "OWNER", value: "bob"), "(org-entry-put nil \"OWNER\" \"bob\")"),
20            (SetProperty(key: "Effort", value: "1:30"), "(org-entry-put nil \"Effort\" \"1:30\")"),
21            (SetProperty(key: "LONGPROPERTYNAME", value: "v"), "(org-entry-put nil \"LONGPROPERTYNAME\" \"v\")"),
22            (SetProperty(key: "SIZE", value: ""), "(org-entry-put nil \"SIZE\" \"\")"),
23            (SetTodo(keyword: "DONE"), "(org-todo \"DONE\")"),
24            (SetTodo(keyword: "TODO"), "(org-todo \"TODO\")"),
25            (SetTodo(keyword: nil), "(org-todo 'none)"),
26        ]
27        var cases: [EmacsOracle.Case] = []
28        var ours: [(text: String, caret: Int, failure: String?)] = []
29        for text in Self.texts {
30            for heading in [(text as NSString).range(of: "Task").location, (text as NSString).range(of: "Repeat").location] where heading != NSNotFound {
31                for (command, form) in edits {
32                    cases.append(EmacsOracle.Case(text: text, point: EmacsOracle.point(heading, in: text), form: frozenClock(1_789_000_000, "(progn \(form) (run-hooks 'post-command-hook))")))
33                    var utc = Calendar(identifier: .gregorian)
34                    utc.timeZone = TimeZone(identifier: "UTC")!
35                    let context = EditContext(revision: 0, text: text, tree: OrgParser.parse(text), selection: [heading..<heading], now: Date(timeIntervalSince1970: 1_789_000_000), calendar: utc)
36                    switch command.run(in: context) {
37                    case .commit(let result):
38                        var new = text
39                        for edit in result.edits.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) { new = edit.apply(to: new) }
40                        ours.append((new, heading, nil))
41                    case .failed(let message): ours.append((text, heading, message))
42                    default: ours.append((text, heading, "other"))
43                    }
44                }
45            }
46        }
47        let emacs = try EmacsOracle.run(cases)
48        for (i, (mine, theirs)) in zip(ours, emacs).enumerated() {
49            #expect(mine.text == theirs.text, "\(cases[i].form.split(separator: "\n").last ?? "") on \(cases[i].text.debugDescription)\nours:  \(mine.text.debugDescription) \(mine.failure ?? "")\nemacs: \(theirs.text.debugDescription) \(theirs.error)")
50        }
51    }
52}
53
54struct BoardTests {
55    @Test func entriesAndKeywords() {
56        let source = AgendaSource(path: "/n/a.org", text: """
57        #+TODO: TODO NEXT | DONE
58        * TODO [#A] One :work:
59        :PROPERTIES:
60        :EFFORT: 1:00
61        :END:
62        * Plain
63        * DONE Two
64        DEADLINE: <2026-10-05 Mon>
65        * ARCHIVED TODO :ARCHIVE:
66        ** TODO Hidden
67        """)
68        let all = Board.entries([source], match: "")
69        #expect(all.map(\.title) == ["One", "Two"])
70        #expect(all[0].properties["EFFORT"] == "1:00" && all[0].priority == "A" && all[0].tags == ["work"])
71        #expect(all[1].deadline == "2026-10-05 Mon")
72        #expect(Board.entries([source], match: "+work").map(\.title) == ["One"])
73        #expect(Board.keywords([source]) == ["TODO", "NEXT", "DONE"])
74    }
75}