oficina / docs Public

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

Plain git — no account needed to clone.

Download

Download this file

1import Foundation
2import XCTest
3@testable import DocsKit
4
5final class CRDTClipboardTests: XCTestCase {
6 @MainActor func testPasteThenImmediateTypingBeforeRenderPreservesMarksAndOffsets() async throws {
7 let replica = CRDTReplica(guid: "clipboard-typeahead")
8 _ = try await replica.open(update: Data())
9 _ = try await replica.command(["op": .string("insert_element"), "at": .number(0), "type": .string("paragraph")])
10 _ = try await replica.command(["op": .string("display_edit"), "at": .number(0), "length": .number(0), "text": .string("AB")])
11 let presentation = try await replica.presentation(source: 0, selection: NSRange(location: 1, length: 0))
12 let (source, projection, _) = try XCTUnwrap(presentation)
13 let content = NativeTextProjection.render(projection)
14 let blocks: [JSONValue] = [.object(["type": .string("paragraph"), "children": .array([.object(["type": .string("text"), "runs": .array([.object(["insert": .string("bold😀"), "marks": .object(["strong": .object([:])])])])])])])]
15 let pasted = try XCTUnwrap(DocumentClipboardInsertion.attributed(blocks: blocks, in: content, range: NSRange(location: 1, length: 0)))
16 _ = try await replica.command(["op": .string("display_paste"), "generation": .number(Double(source)), "at": .number(1), "length": .number(0), "blocks": .array(blocks)])
17 let native = NSMutableAttributedString(attributedString: content)
18 native.replaceCharacters(in: NSRange(location: 1, length: 0), with: pasted)
19 var typing = try XCTUnwrap(TextEditMapping.displayCommand(in: native, range: NSRange(location: 7, length: 0), replacement: "!"))
20 typing["generation"] = .number(Double(source))
21 _ = try await replica.command(typing)
22 let final = try await replica.projection()
23 XCTAssertEqual(final.children.map(\.plainText).joined(), "Abold😀!B")
24 let runs = final.children[0].children?.flatMap { $0.runs ?? [] } ?? []
25 XCTAssertTrue(runs.contains { $0.insert.contains("!") && $0.marks?["strong"] == .object([:]) })
26 await replica.close()
27 }
28 @MainActor func testRuleRevertAndRapidNewlineTypingUseSameDisplayedSource() async throws {
29 let replica = CRDTReplica(guid: "rules-typeahead")
30 _ = try await replica.open(update: Data())
31 let receiver = CRDTReplica(guid: "rules-typeahead")
32 _ = try await receiver.open(update: Data())
33 let (initial, _) = try await replica.command(["op": .string("insert_element"), "at": .number(0), "type": .string("paragraph")])
34 _ = try await receiver.apply(initial)
35 let presentation = try await replica.presentation(source: 0, selection: NSRange(location: 0, length: 0))
36 let source = try XCTUnwrap(presentation?.0)
37 for command: [String: JSONValue] in [
38 ["op": .string("display_edit"), "at": .number(0), "length": .number(0), "text": .string("-")],
39 ["op": .string("display_autoformat"), "at": .number(0), "length": .number(1), "kind": .string("bullet_list"), "level": .number(0)],
40 ["op": .string("display_revert_rule"), "at": .number(0), "kind": .string("bullet_list"), "prior_type": .string("paragraph"), "prior_attrs": .object([:]), "text": .string("- ")],
41 ["op": .string("display_edit"), "at": .number(2), "length": .number(0), "text": .string("one\n")],
42 ["op": .string("display_edit"), "at": .number(6), "length": .number(0), "text": .string("two😀")]
43 ] {
44 var command = command; command["generation"] = .number(Double(source))
45 let (update, _) = try await replica.command(command)
46 _ = try await receiver.apply(update)
47 let local = try await replica.projection(); let remote = try await receiver.projection()
48 XCTAssertEqual(local.children.map(\.id), remote.children.map(\.id))
49 XCTAssertEqual(local.children.map(\.type), remote.children.map(\.type))
50 XCTAssertEqual(local.children.map(\.plainText), remote.children.map(\.plainText))
51 }
52 let final = try await replica.projection()
53 XCTAssertEqual(final.children.map(\.plainText), ["- one", "two😀"])
54 XCTAssertEqual(final.children.map(\.type), ["paragraph", "paragraph"])
55 let received = try await receiver.projection()
56 XCTAssertEqual(received.children.map(\.plainText), ["- one", "two😀"])
57 XCTAssertEqual(received.children.map(\.type), ["paragraph", "paragraph"])
58 await receiver.close()
59 await replica.close()
60 }
61}
62