Tests/OrgCoreTests/ListCommandTests.swift
82 lines · 4320 bytes
6 symbols in this file
1import Foundation
2import Testing
3@testable import OrgCore
4
5struct ListCommandTests {
6 @Test func basics() {
7 #expect(runCommand(InsertItem(), "- a\n", caret: 3).text == "- a\n- \n")
8 #expect(runCommand(InsertItem(), "1. a\n2. b\n", caret: 4).text == "1. a\n2. \n3. b\n")
9 #expect(runCommand(IndentItem(), "- a\n- b\n", caret: 4).text == "- a\n - b\n")
10 #expect(runCommand(OutdentItem(), "- a\n - b\n", caret: 6).text == "- a\n- b\n")
11 #expect(runCommand(MoveItemDown(), "- a\n- b\n", caret: 0).text == "- b\n- a\n")
12 #expect(runCommand(ToggleCheckbox(), "* h [0/1]\n- [ ] a\n", caret: 12).text == "* h [1/1]\n- [X] a\n")
13 #expect(runCommand(IndentItem(), "text\n", caret: 0).failure != nil)
14 }
15}
16
17struct ListOracleTests {
18 static let variants = [
19 "- a\n- b\n- c\n",
20 "1. one\n2. two\n3. three\n",
21 "- a\n - b\n - c\n- d\n",
22 "- [ ] a\n- [X] b\n",
23 "* T [1/3]\n- [X] a\n- [ ] b\n- [ ] c\n",
24 "* T [50%]\n- [ ] a\n - [X] b\n - [ ] c\n",
25 "- a\n\n- b\n",
26 "- term :: def\n- other :: x\n",
27 "text\n- a\n more\n- b\nafter\n",
28 "1) x\n2) y\n",
29 "- a 😀\n - b\n",
30 "#+begin_src\n- a\n#+end_src\n",
31 "- a\n- b\n - c\n- d\n",
32 ]
33
34 static let commands: [(command: any OrgCommand, form: String, headingLineOnly: Bool)] = [
35 (InsertItem(), "(or (org-insert-item) (error \"Not in an item\"))", false),
36 (InsertCheckboxItem(), "(or (org-insert-item 'checkbox) (error \"Not in an item\"))", false),
37 (IndentItem(), "(org-indent-item)", false),
38 (OutdentItem(), "(org-outdent-item)", false),
39 (IndentItemTree(), "(org-indent-item-tree)", false),
40 (OutdentItemTree(), "(org-outdent-item-tree)", false),
41 (MoveItemUp(), "(org-move-item-up)", false),
42 (MoveItemDown(), "(org-move-item-down)", false),
43 (ToggleCheckbox(), "(if (org-at-heading-p) (error \"heading\") (org-toggle-checkbox))", false),
44 ]
45
46 @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil))
47 func listCommandsMatchEmacs() throws {
48 try compareWithEmacs(Self.variants.map { ($0, EmacsOracle.positions($0)) }, Self.commands)
49 }
50
51 @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil))
52 func listCommandsMatchEmacsWithDoomOptions() throws {
53 let alphabetical = ["a. x\nb. y\n", "A) one\n - sub\nB) two\n", "- [@c] x\n- y\n", "1. a\n2. b\n"]
54 try compareWithEmacs((Self.variants + alphabetical).map { ($0, EmacsOracle.positions($0)) }, Self.commands, options: doomOptions)
55 }
56
57 /// Real lists: `ORGSTAR_ORACLE_CORPUS=<folder>` runs every list command in files up to
58 /// 20 KB with the caret at the start, bullet end and end of up to six item lines per file.
59 @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_ORACLE_CORPUS"] != nil))
60 func listCommandsMatchEmacsOnACorpus() throws {
61 let root = URL(fileURLWithPath: ProcessInfo.processInfo.environment["ORGSTAR_ORACLE_CORPUS"]!)
62 let files = FileManager.default.enumerator(at: root, includingPropertiesForKeys: nil)!
63 .compactMap { $0 as? URL }.filter { $0.pathExtension == "org" }.sorted { $0.path < $1.path }
64 let item = try NSRegularExpression(pattern: "^[ \\t]*(?:[-+]|[0-9]+[.)]) ")
65 var samples: [(String, [Int])] = []
66 for file in files where samples.count < 60 {
67 guard let text = try? String(contentsOf: file, encoding: .utf8), text.utf16.count <= 20_000, !text.contains("\r") else { continue }
68 let ns = text as NSString
69 var carets: [Int] = []
70 var location = 0
71 while location < ns.length, carets.count < 18 {
72 let line = ns.lineRange(for: NSRange(location: location, length: 0))
73 if let match = item.firstMatch(in: text, options: .anchored, range: line) {
74 carets += [line.location, NSMaxRange(match.range), NSMaxRange(line) - (ns.substring(with: line).hasSuffix("\n") ? 1 : 0)]
75 }
76 location = NSMaxRange(line)
77 }
78 if !carets.isEmpty { samples.append((text, carets)) }
79 }
80 try compareWithEmacs(samples, Self.commands)
81 }
82}