krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Tests/OrgCoreTests/TableElTests.swift

main
orgstar/Tests/OrgCoreTests/TableElTests.swift history · blame · raw

51 lines · 2724 bytes

5 symbols in this file
 1import Foundation
 2import Testing
 3@testable import OrgCore
 4
 5/// table.el tables against ox-html: the rows, each cell's spans and text.
 6struct TableElTests {
 7    static let tables = [
 8        "+-----+-----+\n| a   | b   |\n+-----+-----+\n| c d       |\n| more      |\n+-----+-----+\n| e   | f   |\n+-----+-----+\n",
 9        "+---+---+\n| a | b |\n|   +---+\n|   | c |\n+---+---+\n",
10        "  +----+---+----+\n  | x  | y | z  |\n  +----+---+----+\n  | wide row    |\n  +----+--------+\n  | p  | q & <r>|\n  +----+--------+\n",
11        "+---+\n| 1 |\n| 2 |\n+---+\n",
12    ]
13
14    static func describe(_ cells: [TableEl.Cell]) -> [String] {
15        Dictionary(grouping: cells, by: \.row).keys.sorted().map { row in
16            cells.filter { $0.row == row }.map { "\($0.colspan)x\($0.rowspan):" + $0.lines.reversed().drop { $0.isEmpty }.reversed().joined(separator: "/") }.joined(separator: " ")
17        }
18    }
19
20    /// The rows of ox-html's table, in the same terms.
21    static func describe(html: String) -> [String] {
22        html.components(separatedBy: "<tr>").dropFirst().map { row in
23            row.components(separatedBy: "<td").dropFirst().map { cell -> String in
24                let colspan = cell.firstMatch(of: /colspan="([0-9]+)"/).map { String($0.1) } ?? "1"
25                let rowspan = cell.firstMatch(of: /rowspan="([0-9]+)"/).map { String($0.1) } ?? "1"
26                let body = cell[cell.firstIndex(of: ">")!...].dropFirst().components(separatedBy: "</td>")[0]
27                let lines = body.components(separatedBy: "<br />").map {
28                    $0.replacingOccurrences(of: "&nbsp;", with: " ").replacingOccurrences(of: "&amp;", with: "&")
29                        .replacingOccurrences(of: "&lt;", with: "<").replacingOccurrences(of: "&gt;", with: ">")
30                        .trimmingCharacters(in: .whitespacesAndNewlines)
31                }
32                return "\(colspan)x\(rowspan):" + lines.reversed().drop { $0.isEmpty }.reversed().joined(separator: "/")
33            }.joined(separator: " ")
34        }
35    }
36
37    @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil))
38    func cellsMatchOxHtml() throws {
39        for table in Self.tables {
40            let html = try EmacsOracle.evaluate(table, "(progn (require 'ox-html) (list (org-export-as 'html nil nil t)))")[0]
41            let ours = try #require(TableEl.cells(table))
42            #expect(Self.describe(ours) == Self.describe(html: html), "\(table)\n\(html)")
43        }
44    }
45
46    @Test func exportsATable() {
47        let page = HTMLExport.page(Self.tables[0], fallbackTitle: "t")
48        #expect(page.contains("<td colspan=\"2\">c d<br>more</td>"))
49        #expect(!page.contains("<pre"))
50    }
51}