Tests/OrgCoreTests/FastSelectionTests.swift
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}