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 markdown rendering contract (issue #531): every vector in
5// Fixtures/markdown-vector.json — a byte-identical copy of the canonical
6// test/event-vectors/markdown.json, gated by test/markdown.test.mjs — must
7// normalize to the same semantic tree on both twins. The web side asserts
8// parseMessage(input) == tree; this suite asserts markdownTree(input) == tree.
9// When a vector fails here, the twins have diverged: fix MarkdownTree.swift
10// (or markdown.js), never the vector.
11final class MarkdownVectorTests: XCTestCase {
12 struct VectorFile: Decodable {
13 let vectors: [Vector]
14 }
15 struct Vector: Decodable {
16 let name: String
17 let input: String
18 let tree: [MDBlock]
19 let plain: String? // pins markdownPlainText (previews/notifications) when present
20 let note: String?
21 }
22
23 private func loadVectors() throws -> [Vector] {
24 let url = try XCTUnwrap(
25 Bundle.module.url(forResource: "Fixtures/markdown-vector", withExtension: "json"),
26 "Fixtures/markdown-vector.json missing — run cp test/event-vectors/markdown.json ios/LChatCore/Tests/LChatCoreTests/Fixtures/markdown-vector.json")
27 return try JSONDecoder().decode(VectorFile.self, from: Data(contentsOf: url)).vectors
28 }
29
30 private func json(_ blocks: [MDBlock]) -> String {
31 let enc = JSONEncoder()
32 enc.outputFormatting = [.sortedKeys]
33 return (try? String(decoding: enc.encode(blocks), as: UTF8.self)) ?? "<encode failed>"
34 }
35
36 func testVectorCoverage() throws {
37 let vectors = try loadVectors()
38 XCTAssertGreaterThanOrEqual(vectors.count, 60, "vector corpus shrank — regenerate from web")
39 }
40
41 func testAllVectors() throws {
42 for v in try loadVectors() {
43 let got = markdownTree(v.input)
44 XCTAssertEqual(
45 got, v.tree,
46 """
47 vector '\(v.name)' diverged\(v.note.map { " (\($0))" } ?? "")
48 input: \(v.input.debugDescription)
49 expected: \(json(v.tree))
50 got: \(json(got))
51 """)
52 if let plain = v.plain {
53 XCTAssertEqual(markdownPlainText(v.input), plain,
54 "vector '\(v.name)' plain projection diverged from the web twin")
55 }
56 }
57 }
58
59 // Beyond the shared corpus: edges the web suite pins in test/markdown.test.mjs.
60 func testHostileSchemesNeverLink() {
61 let tree = markdownTree("[a](data:text/html,x) [b](vbscript:x) <ftp://x.com>")
62 func assertNoLinks(_ inlines: [MDInline]) {
63 for node in inlines {
64 switch node {
65 case .link(let href, _):
66 XCTAssertTrue(href.lowercased().hasPrefix("http"), "non-http(s) link leaked: \(href)")
67 case .strong(let c), .em(let c), .strike(let c):
68 assertNoLinks(c)
69 default: break
70 }
71 }
72 }
73 for block in tree {
74 if case .p(let children) = block { assertNoLinks(children) }
75 }
76 }
77
78 func testMismatchedTildesStayLiteral() {
79 XCTAssertEqual(markdownTree("~a~~"), [.p([.text("~a~~")])])
80 }
81
82 func testAdjacentTextMerges() {
83 XCTAssertEqual(markdownTree("a \\* b &amp; c"), [.p([.text("a * b & c")])])
84 }
85
86 func testEmptyInput() {
87 XCTAssertEqual(markdownTree(""), [])
88 XCTAssertEqual(markdownTree(" "), [])
89 }
90}
91