krz/orgstar

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

Tests/OrgCoreTests/FastSelectionTests.swift

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

109 lines · 5783 bytes

8 symbols in this file
  1import Foundation
  2import Testing
  3@testable import OrgCore
  4
  5struct FastSelectionTests {
  6    static let oracle = ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil
  7
  8    static let todoTexts = [
  9        // Without log flags: notes are stored after the command, which these cases don't reach.
 10        "#+TODO: TODO(t) WAIT(w) | DONE(d) CANCELED(c)\n* TODO Task\n",
 11        "#+TODO: TODO(t) NEXT | DONE(d)\n#+TODO: BUG(b) TRIAGE(t) | FIXED(f)\n* BUG Task\n",
 12        "#+TODO: TODO(t) NEXT | DONE(d)\n#+TODO: BUG(b) TRIAGE(t) | FIXED(f)\n* Task\n",
 13        "#+TODO: TODO(t) DOING DONE\n* DOING Task\n",
 14    ]
 15
 16    @Test(.enabled(if: oracle))
 17    func selectsTodoLikeOrgTodo() throws {
 18        var cases: [EmacsOracle.Case] = []
 19        var ours: [String] = []
 20        for text in Self.todoTexts {
 21            let heading = (text as NSString).range(of: "Task").location
 22            for key in ["t", "w", "d", " ", "x", "q", "n", "o", "0", "f"] {
 23                let char = key == " " ? "?\\s" : "?" + key
 24                cases.append(EmacsOracle.Case(text: text, point: EmacsOracle.point(heading, in: text), form: """
 25                    (condition-case nil
 26                        (cl-letf (((symbol-function 'read-char-exclusive) (lambda (&rest _) \(char)))) (org-todo))
 27                      (quit nil))
 28                    """))
 29                ours.append(runCommand(TodoCycle(), text, caret: heading, answers: ["todo": key]).text)
 30            }
 31        }
 32        let emacs = try EmacsOracle.run(cases)
 33        for (i, (mine, theirs)) in zip(ours, emacs).enumerated() {
 34            #expect(mine == theirs.text, "\(mine.debugDescription) vs \(theirs.text.debugDescription) \(cases[i].form) on \(cases[i].text.debugDescription)")
 35        }
 36    }
 37
 38    @Test(.enabled(if: oracle))
 39    func shiftsLikeOrgShiftRightAndLeft() throws {
 40        let texts = Self.todoTexts + ["* Task\n", "* TODO Task\n", "* DONE Task\n"]
 41        var cases: [EmacsOracle.Case] = []
 42        var ours: [String] = []
 43        for text in texts {
 44            let heading = (text as NSString).range(of: "Task").location
 45            for (right, form) in [(true, "(org-shiftright)"), (false, "(org-shiftleft)"), (true, "(progn (org-shiftright) (org-shiftright))")] {
 46                cases.append(EmacsOracle.Case(text: text, point: EmacsOracle.point(heading, in: text), form: form))
 47                var result = runCommand(TodoShift(right: right), text, caret: heading).text
 48                if form.contains("progn") { result = runCommand(TodoShift(right: right), result, caret: heading).text }
 49                ours.append(result)
 50            }
 51        }
 52        let emacs = try EmacsOracle.run(cases)
 53        for (i, (mine, theirs)) in zip(ours, emacs).enumerated() {
 54            #expect(mine == theirs.text, "\(mine.debugDescription) vs \(theirs.text.debugDescription) \(cases[i].form) on \(cases[i].text.debugDescription) \(theirs.error)")
 55        }
 56    }
 57
 58    static let tagTexts = [
 59        "#+TAGS: work(w) home(h) errand\n* Task :home:\n",
 60        "#+TAGS: { office(o) home(h) } computer(c) phone\n#+TAGS: @read reading\n* Task :phone:\n",
 61        "#+TAGS: [ Project : alpha(a) beta(b) ] solo(s)\n#+FILETAGS: :top:\n* Parent :solo:\n** Task\n",
 62        "#+TAGS: alpha(a) apple avocado\n* Task :avocado:alpha:\n",
 63    ]
 64
 65    @Test(.enabled(if: oracle))
 66    func selectsTagsLikeOrgFastTagSelection() throws {
 67        let sequences = ["\r", "w\r", "wh\r", "o\r", "oh\r", "c o h\r", "!oh\r", " \r", "a\r", "e\r", "r\r", "q", "ap\r", "s\r", "b\r", "AB\r"]
 68        var cases: [EmacsOracle.Case] = []
 69        var ours: [String] = []
 70        for text in Self.tagTexts {
 71            let heading = (text as NSString).range(of: "Task").location
 72            for keys in sequences {
 73                let chars = keys.map { $0 == "\r" ? "?\\r" : $0 == " " ? "?\\s" : "?" + String($0) }.joined(separator: " ")
 74                cases.append(EmacsOracle.Case(text: text, point: EmacsOracle.point(heading, in: text), form: """
 75                    (condition-case nil
 76                        (let ((keys (list \(chars))))
 77                          (cl-letf (((symbol-function 'read-char-exclusive) (lambda (&rest _) (if keys (pop keys) (signal 'quit nil)))))
 78                            (org-set-tags-command)))
 79                      (quit nil))
 80                    """))
 81                let answer = String(keys.prefix { $0 != "\r" })
 82                ours.append(runCommand(SetTags(), text, caret: heading, answers: ["tags": answer]).text)
 83            }
 84        }
 85        let emacs = try EmacsOracle.run(cases)
 86        for (i, (mine, theirs)) in zip(ours, emacs).enumerated() {
 87            #expect(mine == theirs.text, "\(mine.debugDescription) vs \(theirs.text.debugDescription) \(cases[i].form.split(separator: "\n")[1]) on \(cases[i].text.debugDescription) \(theirs.error)")
 88        }
 89    }
 90
 91    @Test func assignsTagKeysAsOrgDoes() {
 92        let table = FastSelection.tagTable("#+TAGS: alpha(a) apple avocado banana @bread\n")!
 93        let fast = FastSelection.tags(table: table, current: [], inherited: [])!
 94        #expect(fast.options.map { "\($0.key)\($0.name)" } == ["aalpha", "bapple", "cavocado", "dbanana", "e@bread"])
 95    }
 96
 97    @Test func encodesTypedTags() {
 98        let inputs: [FastSelection.Input] = [.key("a"), .typed("new tag"), .key(" ")]
 99        #expect(FastSelection.decode(FastSelection.encode(inputs)) == inputs)
100    }
101}
102
103struct TodoKeywordSettingsTests {
104    @Test func readsOneSequencePerLine() {
105        let settings = OrgSettings.default.withTodoKeywords("TODO(t) | DONE(d)\nBUG | FIXED\n")!
106        #expect(settings.todoSequences.map { ($0.active + $0.done).map(\.name) } == [["TODO", "DONE"], ["BUG", "FIXED"]])
107        #expect(OrgSettings.default.withTodoKeywords("\n") == nil)
108    }
109}