Files
ichmagmaus111andClaude Opus 5.5 0622057a4f Ghostgram: open-source release
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:57:09 +01:00

93 lines
5.9 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if canImport(UIKit)
import XCTest
import RichTextEditorCore
@testable import RichTextEditorUIKit
final class PullQuoteGeometryTests: XCTestCase {
func test_pullQuotePill_isCenteredAndHugsContent() {
let canvas = DocumentCanvasView()
canvas.setBlocks([.pullQuote(PullQuote(id: BlockID("pq"), runs: [TextRun(text: "Hi")]))], width: 320)
canvas.frame = CGRect(x: 0, y: 0, width: 320, height: 400)
canvas.layoutIfNeeded()
let pills = canvas.pullQuotePillRects()
XCTAssertEqual(pills.count, 1)
XCTAssertGreaterThan(pills[0].width, 0)
XCTAssertLessThan(pills[0].width, 320) // hugs content, not full width
XCTAssertEqual(pills[0].midX, canvas.bounds.width / 2, accuracy: 1.0) // centered in the content column
}
func test_pullQuoteMarks_topLeftAndBottomRight() {
let canvas = DocumentCanvasView()
canvas.frame = CGRect(x: 0, y: 0, width: 320, height: 400)
canvas.simulateParentLayout()
canvas.setBlocks([.pullQuote(PullQuote(id: BlockID("pq"), runs: [TextRun(text: "Hi")]))], width: 320)
guard let box = canvas.boxes.first as? PullQuoteBox else { return XCTFail("expected a PullQuoteBox") }
let pill = canvas.pullQuotePillRects()[0]
let marks = canvas.pullQuoteMarkRects()
XCTAssertEqual(marks.count, 1)
XCTAssertEqual(marks[0].open.minX, pill.minX + 6, accuracy: 0.5) // top-left, inset 6
XCTAssertEqual(marks[0].open.minY, pill.minY + 6, accuracy: 0.5)
XCTAssertEqual(marks[0].close.maxX, pill.maxX - 6, accuracy: 0.5) // bottom-right (x/width unaffected)
// The close mark's Y now brackets the quote TEXT only (excludes the always-present author region,
// even the empty "Add author" placeholder) — the pill itself still spans the full box height.
XCTAssertEqual(marks[0].close.maxY, box.frame.minY + box.quoteOnlyHeight - 6, accuracy: 0.5)
}
func test_pullQuoteMarkRects_deriveFrames_fromNonSquareImageSizes() {
// The RichText/QuoteOpen & QuoteClose assets are 12×10 (non-square). Each mark rect must use its
// image's own size (not a square), anchored open→top-left / close→bottom-right, inset from the corner.
let pill = CGRect(x: 100, y: 50, width: 160, height: 90)
let size = CGSize(width: 12, height: 10)
let rects = DocumentCanvasView.pullQuoteMarkRects(pills: [pill], inset: 6, openSize: size, closeSize: size)
XCTAssertEqual(rects.count, 1)
XCTAssertEqual(rects[0].open, CGRect(x: 106, y: 56, width: 12, height: 10)) // top-left, natural size
XCTAssertEqual(rects[0].close.width, 12, accuracy: 0.001) // image width, not a forced square
XCTAssertEqual(rects[0].close.height, 10, accuracy: 0.001) // image height (non-square)
XCTAssertEqual(rects[0].close.maxX, pill.maxX - 6, accuracy: 0.001) // bottom-right anchored
XCTAssertEqual(rects[0].close.maxY, pill.maxY - 6, accuracy: 0.001)
}
func test_pullQuoteStyle_minWidthFloor_andMarkFromImageSize() {
let canvas = DocumentCanvasView()
canvas.frame = CGRect(x: 0, y: 0, width: 320, height: 400)
var style = PullQuoteStyle.default; style.minWidth = 200
canvas.applyPullQuoteStyle(style)
canvas.simulateParentLayout() // install callback before setBlocks so layout fires on content-size notify
canvas.setBlocks([.pullQuote(PullQuote(id: BlockID("pq"), runs: [TextRun(text: "x")]))], width: 320)
XCTAssertGreaterThanOrEqual(canvas.pullQuotePillRects()[0].width, 200) // minWidth floor
// mark frame size comes from the image's natural size (the generated stub under SwiftPM), not a config knob
XCTAssertEqual(canvas.pullQuoteMarkRects()[0].open.width,
PullQuoteMarksView.openImageNaturalSize.width, accuracy: 0.5)
}
func test_pullQuoteCloseMark_excludesAuthorLine() {
// The close (bottom-right) corner mark must bracket the QUOTE TEXT only — sitting at the last text
// line's bottom, ABOVE the author line — even though the tinted pill background still spans the
// full box height (text + author).
let canvas = DocumentCanvasView()
canvas.frame = CGRect(x: 0, y: 0, width: 320, height: 400)
canvas.simulateParentLayout()
canvas.setBlocks([.pullQuote(PullQuote(id: BlockID("pq"), runs: [TextRun(text: "Hi")], author: [TextRun(text: "Ada")]))], width: 320)
guard let box = canvas.boxes.first as? PullQuoteBox else { return XCTFail("expected a PullQuoteBox") }
XCTAssertGreaterThan(box.frame.maxY, box.frame.minY + box.quoteOnlyHeight,
"sanity: the author line adds height beyond the quote-only height")
let marks = canvas.pullQuoteMarkRects()
XCTAssertEqual(marks.count, 1)
let close = marks[0].close
XCTAssertEqual(close.maxY, box.frame.minY + box.quoteOnlyHeight - canvas.pullQuoteStyle.markInset, accuracy: 0.5)
XCTAssertLessThan(close.maxY, box.frame.maxY, "close mark sits above the author line, not at the box bottom")
// The OPEN (top-left) mark is unaffected — still anchored off the box's top edge.
let open = marks[0].open
XCTAssertEqual(open.minY, box.frame.minY + canvas.pullQuoteStyle.markInset, accuracy: 0.5)
}
func test_pullQuoteUnderlay_cornerRadius_comesFromPullQuoteStyleDefault() {
// Regression: the pull-quote pill underlay must take its corner radius from PullQuoteStyle (the
// pull-quote's own look), NOT borrow the block-quote underlay's radius at init — otherwise changing
// PullQuoteStyle.cornerRadius has no effect in hosts that don't assign a custom pullQuoteStyle (the composer).
let canvas = DocumentCanvasView()
XCTAssertEqual(canvas.pullQuoteUnderlay.cornerRadius, PullQuoteStyle.default.cornerRadius, accuracy: 0.001)
}
}
#endif