eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2@testable import LChatCore
3
4// The format-as-you-type brain (ComposerRules.swift) — semantics pinned here,
5// and the regex literals drift-gated against web/static/composer-pm.js (the
6// ComposerTypeaheadTests pattern): a web-side rule change fails this suite
7// until the native mirror follows.
8final class ComposerRulesTests: XCTestCase {
9 private var repoRoot: URL {
10 URL(fileURLWithPath: #filePath)
11 .deletingLastPathComponent() // Tests/LChatCoreTests
12 .deletingLastPathComponent() // Tests
13 .deletingLastPathComponent() // LChatCore
14 .deletingLastPathComponent() // ios
15 .deletingLastPathComponent() // repo
16 }
17
18 // MARK: inline completions
19
20 func testMarkCompletions() {
21 XCTAssertEqual(inlineCompletion(lineUpToCaret: "**bold**"),
22 InlineCompletion(replaceRange: 0..<8, content: "bold", mark: .bold))
23 XCTAssertEqual(inlineCompletion(lineUpToCaret: "say *it*"),
24 InlineCompletion(replaceRange: 4..<8, content: "it", mark: .italic))
25 XCTAssertEqual(inlineCompletion(lineUpToCaret: "`code`"),
26 InlineCompletion(replaceRange: 0..<6, content: "code", mark: .code))
27 XCTAssertEqual(inlineCompletion(lineUpToCaret: "~gone~"),
28 InlineCompletion(replaceRange: 0..<6, content: "gone", mark: .strike))
29 XCTAssertEqual(inlineCompletion(lineUpToCaret: "say _it_"),
30 InlineCompletion(replaceRange: 4..<8, content: "it", mark: .italic))
31 }
32
33 func testUnderscoreNeverFiresIntraword() {
34 XCTAssertNil(inlineCompletion(lineUpToCaret: "snake_case_"))
35 XCTAssertNil(inlineCompletion(lineUpToCaret: "a_b_"))
36 }
37
38 func testStrongWinsBeforeEm() {
39 // "**bold**" must fire strong, and the half-typed "**bold*" must not
40 // half-fire the em rule (its lookbehind rejects the second star).
41 XCTAssertEqual(inlineCompletion(lineUpToCaret: "**bold**")?.mark, .bold)
42 XCTAssertNil(inlineCompletion(lineUpToCaret: "**bold*"))
43 }
44
45 func testTildeLookbehind() {
46 XCTAssertNil(inlineCompletion(lineUpToCaret: "~~s~"), "double-tilde opener never pairs with a single closer")
47 }
48
49 func testNoFireOnWhitespaceEdges() {
50 XCTAssertNil(inlineCompletion(lineUpToCaret: "** x**"))
51 XCTAssertNil(inlineCompletion(lineUpToCaret: "*x *"))
52 }
53
54 func testUnicodeContentAndOffsets() {
55 // replaceRange is UTF-16: ✨ is BMP (1 unit), 😀 is a surrogate pair (2).
56 XCTAssertEqual(inlineCompletion(lineUpToCaret: "✨ **bí**"),
57 InlineCompletion(replaceRange: 2..<8, content: "bí", mark: .bold))
58 XCTAssertEqual(inlineCompletion(lineUpToCaret: "😀 **x**"),
59 InlineCompletion(replaceRange: 3..<8, content: "x", mark: .bold))
60 }
61
62 // MARK: drift gate against the web rules
63
64 func testRegexLiteralsMatchComposerPmJs() throws {
65 let js = try String(contentsOf: repoRoot.appendingPathComponent("web/static/composer-pm.js"), encoding: .utf8)
66 // The exact JS regex literals the Swift patterns transliterate. If a
67 // rule changes on the web, its literal disappears and this fails.
68 let literals = [
69 #"/\*\*([^*\s](?:[^*]*[^*\s])?)\*\*$/"#,
70 #"/(?<!\*)\*([^*\s](?:[^*]*[^*\s])?)\*$/"#,
71 #"/(?<![\w_])_([^_\s](?:[^_]*[^_\s])?)_$/"#,
72 #"/`([^`\s](?:[^`]*[^`\s])?)`$/"#,
73 #"/(?<!~)~([^~\s](?:[^~]*[^~\s])?)~$/"#,
74 ]
75 for literal in literals {
76 XCTAssertTrue(js.contains(literal), "composer-pm.js no longer contains \(literal) — mirror the rule change into ComposerRules.swift")
77 }
78 }
79}
80