oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1#if os(macOS)
2import AppKit
3import SwiftUI
4import XCTest
5@testable import DocsKit
6
7@MainActor private final class RenderState {
8 var pending = false
9 var allowed: UInt64 = 1
10 var selection = NSRange(location: 0, length: 0)
11 var acknowledgements: [UInt64] = []
12 var commands: [[String: JSONValue]] = []
13 func candidate(_ content: NSAttributedString, generation: UInt64) -> NativeDocumentTextView {
14 NativeDocumentTextView(content: content, generation: generation,
15 didRender: { self.acknowledgements.append($0) }, compositionChanged: { _ in },
16 isEditable: true, paged: false, pendingInput: pending,
17 canRender: { !self.pending && self.allowed == $0 }, currentSelection: { self.selection },
18 selection: Binding(get: { self.selection }, set: { self.selection = $0 }),
19 edit: { self.pending = true; self.commands.append($0); return true })
20 }
21}
22final class NativeRenderTests: XCTestCase {
23 @MainActor func testDelayedCandidateCannotOverwriteAcceptedNativeTyping() {
24 let state = RenderState()
25 let initial = state.candidate(NSAttributedString(string: "a😀b\n"), generation: 1)
26 let coordinator = initial.makeCoordinator()
27 let text = DocsTextView(frame: CGRect(x: 0, y: 0, width: 500, height: 700))
28 text.delegate = coordinator
29 coordinator.applyRender(initial, to: text)
30 state.allowed = 2
31 let delayed = state.candidate(NSAttributedString(string: "older server view\n"), generation: 2)
32 XCTAssertFalse(delayed.pendingInput)
33 text.insertText("X", replacementRange: NSRange(location: 4, length: 0))
34 XCTAssertTrue(state.pending)
35 XCTAssertEqual(text.string, "a😀bX\n")
36 XCTAssertEqual(state.commands.last?["generation"], .number(1))
37 coordinator.applyRender(delayed, to: text)
38 XCTAssertEqual(text.string, "a😀bX\n")
39 XCTAssertEqual(state.acknowledgements, [1])
40 state.pending = false; state.allowed = 3
41 coordinator.applyRender(delayed, to: text)
42 XCTAssertEqual(text.string, "a😀bX\n")
43 state.selection = NSRange(location: 6, length: 0)
44 let current = state.candidate(NSAttributedString(string: "a😀bX!\n"), generation: 3)
45 coordinator.applyRender(current, to: text)
46 XCTAssertEqual(text.string, "a😀bX!\n")
47 XCTAssertEqual(text.selectedRange(), NSRange(location: 6, length: 0))
48 XCTAssertEqual(state.acknowledgements, [1, 3])
49 }
50 @MainActor func testMarkedTextSurvivesPeerPresentationAndCommitsOnce() {
51 let state = RenderState()
52 let initial = state.candidate(NSAttributedString(string: "a😀b\n"), generation: 1)
53 let coordinator = initial.makeCoordinator()
54 let text = DocsTextView(frame: CGRect(x: 0, y: 0, width: 500, height: 700))
55 text.delegate = coordinator
56 text.compositionCommitted = { coordinator.commitComposition(before: $0, after: $1) }
57 coordinator.applyRender(initial, to: text)
58 text.setMarkedText("に", selectedRange: NSRange(location: 1, length: 0), replacementRange: NSRange(location: 1, length: 2))
59 XCTAssertTrue(text.hasMarkedText())
60 XCTAssertTrue(state.commands.isEmpty)
61 state.allowed = 2
62 coordinator.applyRender(state.candidate(NSAttributedString(string: "peer update\n"), generation: 2), to: text)
63 XCTAssertEqual(text.string, "aにb\n")
64 XCTAssertEqual(state.acknowledgements, [1])
65 text.unmarkText()
66 XCTAssertEqual(state.commands.count, 1)
67 XCTAssertEqual(state.commands.first?["generation"], .number(1))
68 XCTAssertEqual(state.commands.first?["at"], .number(1))
69 XCTAssertEqual(state.commands.first?["length"], .number(2))
70 XCTAssertEqual(state.commands.first?["text"], .string("に"))
71 }
72
73 @MainActor func testAttributeOnlyRefreshPreservesNativeCaret() {
74 let state = RenderState()
75 let initial = state.candidate(NSAttributedString(string: "abcdef\n"), generation: 1)
76 let coordinator = initial.makeCoordinator()
77 let text = DocsTextView(frame: CGRect(x: 0, y: 0, width: 500, height: 700))
78 coordinator.applyRender(initial, to: text)
79 text.setSelectedRange(NSRange(location: 4, length: 0))
80 state.selection = NSRange(location: 0, length: 0)
81 let changed = NSAttributedString(string: "abcdef\n", attributes: [.foregroundColor: NSColor.red])
82 coordinator.applyRender(state.candidate(changed, generation: 1), to: text)
83 XCTAssertEqual(text.selectedRange(), NSRange(location: 4, length: 0))
84 XCTAssertEqual(text.textStorage?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? NSColor, .red)
85 }
86}
87#endif
88