Tests/OrgEditorAppKitTests/LineIndexTests.swift
52 lines · 2410 bytes
5 symbols in this file
1import Foundation
2import Testing
3import OrgPresentation
4@testable import OrgEditorAppKit
5
6struct LineIndexTests {
7 func naive(_ text: String) -> [Int] {
8 var starts = [0]
9 for (i, u) in text.utf16.enumerated() where u == 10 { starts.append(i + 1) }
10 return starts
11 }
12
13 @Test func followsRandomEdits() {
14 var generator = SystemRandomNumberGenerator()
15 let pieces = ["a", "bc\n", "\n", "\n\n", "xyz", "é\n", "😀", ""]
16 var text = "first\nsecond\n\nthird"
17 let index = LineIndex(text as NSString)
18 for _ in 0..<2000 {
19 let ns = text as NSString
20 let start = Int.random(in: 0...ns.length, using: &generator)
21 let end = min(ns.length, start + Int.random(in: 0...6, using: &generator))
22 let replacement = pieces.randomElement(using: &generator)!
23 text = ns.replacingCharacters(in: NSRange(location: start, length: end - start), with: replacement)
24 index.replace(start..<end, newLength: (replacement as NSString).length, in: text as NSString)
25 #expect(index.starts == naive(text))
26 if index.starts != naive(text) { return }
27 }
28 #expect(index.line(of: 0) == 1)
29 #expect(index.line(of: (text as NSString).length) == naive(text).count)
30 }
31}
32
33@MainActor
34struct ShadedBlockTests {
35 /// Bands after edits match a full search once typing settles.
36 @Test func incrementalMatchesFull() {
37 var generator = SystemRandomNumberGenerator()
38 let pieces = ["x", "word ", "\n", "#+begin_src sh\n", "#+end_src\n", ": fixed\n", "* H\n", "#+begin_quote\n", "#+end_quote\n", ""]
39 let h = Harness("* A\n#+begin_src sh\nls\n#+end_src\ntext\n: one\n* B\nbody\n")
40 for _ in 0..<400 {
41 let length = h.editor.document.text.utf16.count
42 let start = Int.random(in: 0...length, using: &generator)
43 let end = min(length, start + Int.random(in: 0...5, using: &generator))
44 let piece = pieces.randomElement(using: &generator)!
45 h.textView.insertText(piece, replacementRange: NSRange(location: start, length: end - start))
46 h.editor.settleBlocks()
47 let full = Presentation.shadedBlocks(h.editor.document.tree)
48 #expect(h.editor.shaded.all == full, "\(h.editor.document.text)")
49 if h.editor.shaded.all != full { return }
50 }
51 }
52}