mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-11-03 22:27:13 +01:00
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
4.6 KiB
Swift
77 lines
4.6 KiB
Swift
#if canImport(UIKit)
|
|
import XCTest
|
|
import RichTextEditorCore
|
|
@testable import RichTextEditorUIKit
|
|
|
|
@available(iOS 13.0, *)
|
|
final class TableCellAlignmentTests: XCTestCase {
|
|
private func cell(_ id: String, _ text: String, h: TextAlignment = .center, v: VerticalAlignment = .top) -> Cell {
|
|
Cell(id: BlockID(id), blocks: [.paragraph(ParagraphBlock(id: BlockID(id + "p"), style: .body,
|
|
runs: [TextRun(text: text)]))], horizontalAlignment: h, verticalAlignment: v)
|
|
}
|
|
|
|
func test_currentBlock_roundTripsPerCellAlignment() {
|
|
let table = TableBlock(id: BlockID("t"),
|
|
columns: [ColumnSpec(width: 100), ColumnSpec(width: 100)],
|
|
rows: [Row(id: BlockID("r0"), isHeader: true, cells: [cell("a","A", h: .left), cell("b","B", h: .right, v: .bottom)])])
|
|
let box = TableBlockBox(table: table, mapper: AttributedStringMapper(), width: 390)
|
|
box.frame = CGRect(x: 0, y: 0, width: 390, height: 200); box.recompute()
|
|
guard case .table(let out) = box.currentBlock() else { return XCTFail() }
|
|
XCTAssertEqual(out.rows[0].cells[0].horizontalAlignment, .left)
|
|
XCTAssertEqual(out.rows[0].cells[1].horizontalAlignment, .right)
|
|
XCTAssertEqual(out.rows[0].cells[1].verticalAlignment, .bottom)
|
|
}
|
|
|
|
func test_verticalAlignment_offsetsCellContentWithinTallRow() {
|
|
// Column 0 is a single short line; column 1 is forced tall so the row has free vertical space.
|
|
let tall = "L1\nL2\nL3\nL4"
|
|
let table = TableBlock(id: BlockID("t"),
|
|
columns: [ColumnSpec(width: 120), ColumnSpec(width: 120)],
|
|
rows: [Row(id: BlockID("r0"), cells: [
|
|
cell("a", "short", v: .bottom),
|
|
Cell(id: BlockID("b"), blocks: tall.split(separator: "\n").enumerated().map { i, s in
|
|
.paragraph(ParagraphBlock(id: BlockID("b\(i)"), style: .body, runs: [TextRun(text: String(s))])) })
|
|
])])
|
|
let box = TableBlockBox(table: table, mapper: AttributedStringMapper(), width: 390)
|
|
box.frame = CGRect(x: 0, y: 0, width: 390, height: 400); box.recompute()
|
|
// `BlockStack` itself carries no `frame` — its child boxes do. The cell's stack holds one
|
|
// paragraph `BlockBox`, whose `frame.minY` is the laid-out content origin (see `BlockStack.layout`:
|
|
// the first box in a stack is placed at exactly `origin.y`, and with `verticalInsetBase == 0` for a
|
|
// cell stack, its `topInset` is 0 too, so no additional offset hides inside the box itself).
|
|
let shortStack = box.cells[0][0]
|
|
let cellTopY = box.cellRect(row: 0, column: 0)!.minY
|
|
let pad = TableBlockBox.cellVerticalPadding
|
|
// Bottom-aligned short content sits well BELOW the top padding line (there is free space in the tall row).
|
|
XCTAssertGreaterThan(shortStack.boxes[0].frame.minY, cellTopY + pad + 1.0)
|
|
}
|
|
|
|
func test_verticalAlignment_topIsUnchanged() {
|
|
let table = TableBlock(id: BlockID("t"), columns: [ColumnSpec(width: 200)],
|
|
rows: [Row(id: BlockID("r0"), cells: [cell("a", "x", v: .top)])])
|
|
let box = TableBlockBox(table: table, mapper: AttributedStringMapper(), width: 390)
|
|
box.frame = CGRect(x: 0, y: 0, width: 390, height: 200); box.recompute()
|
|
let cellTopY = box.cellRect(row: 0, column: 0)!.minY
|
|
XCTAssertEqual(box.cells[0][0].boxes[0].frame.minY, cellTopY + TableBlockBox.cellVerticalPadding, accuracy: 0.5)
|
|
}
|
|
|
|
func test_setSelectionHorizontalAlignment_setsSelectedColumnCells() {
|
|
let v = DocumentCanvasView()
|
|
v.setBlocks([.table(TableBlock(id: BlockID("t"),
|
|
columns: [ColumnSpec(width: 120), ColumnSpec(width: 120)],
|
|
rows: [Row(id: BlockID("r0"), isHeader: true, cells: [cell("a","A"), cell("b","B")]),
|
|
Row(id: BlockID("r1"), cells: [cell("c","C"), cell("d","D")])]))], width: 390)
|
|
v.frame = CGRect(x: 0, y: 0, width: 390, height: 400); v.layoutIfNeeded()
|
|
let t = v.boxes[0] as! TableBlockBox
|
|
v.setSelectionForTesting(anchor: t.cellTextStart(row: 1, column: 1)!, head: t.cellTextStart(row: 1, column: 1)!)
|
|
v.selectTableColumn(1)
|
|
v.setSelectionVerticalAlignment(.bottom)
|
|
v.setSelectionHorizontalAlignment(.right)
|
|
guard case .table(let out) = v.boxes[0].currentBlock() else { return XCTFail() }
|
|
// Column 1 cells updated; column 0 untouched.
|
|
XCTAssertEqual(out.rows[0].cells[1].horizontalAlignment, .right)
|
|
XCTAssertEqual(out.rows[1].cells[1].verticalAlignment, .bottom)
|
|
XCTAssertEqual(out.rows[0].cells[0].horizontalAlignment, .center, "column 0 untouched")
|
|
}
|
|
}
|
|
#endif
|