// // AttributedStringBuilderTests.swift // ElementXTests // // Created by Stefan Ceriu on 28/03/2022. // Copyright © 2022 Element. All rights reserved. // @testable import ElementX import XCTest class AttributedStringBuilderTests: XCTestCase { let attributedStringBuilder = AttributedStringBuilder() let maxHeaderPointSize = ceil(UIFont.preferredFont(forTextStyle: .body).pointSize * 1.2) func testRenderHTMLStringWithHeaders() async { let h1HTMLString = "
1\n2\n3\n4\n"
guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else {
XCTFail("Could not build the attributed string")
return
}
XCTAssertEqual(attributedString.runs.first?.uiKit.font?.fontName, "Menlo-Regular")
let string = String(attributedString.characters)
guard let regex = try? NSRegularExpression(pattern: "\\R", options: []) else {
XCTFail("Could not build the regex for the test.")
return
}
XCTAssertEqual(regex.numberOfMatches(in: string, options: [], range: .init(location: 0, length: string.count)), 3)
}
func testRenderHTMLStringWithLink() async {
let htmlString = "This text contains a link."
guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else {
XCTFail("Could not build the attributed string")
return
}
XCTAssertEqual(String(attributedString.characters), "This text contains a link.")
XCTAssertEqual(attributedString.runs.count, 3)
let link = attributedString.runs.first(where: { $0.link != nil })?.link
XCTAssertEqual(link?.host, "www.matrix.org")
}
func testRenderPlainStringWithLink() async {
let plainString = "This text contains a https://www.matrix.org link."
guard let attributedString = await attributedStringBuilder.fromPlain(plainString) else {
XCTFail("Could not build the attributed string")
return
}
XCTAssertEqual(String(attributedString.characters), plainString)
XCTAssertEqual(attributedString.runs.count, 3)
let link = attributedString.runs.first(where: { $0.link != nil })?.link
XCTAssertEqual(link?.host, "www.matrix.org")
}
func testRenderHTMLStringWithLinkInHeader() async {
let h1HTMLString = "Blockquote" guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 1) XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 1) for run in attributedString.runs { if run.elementX.blockquote != nil { return } } XCTFail("Couldn't find blockquote") } // swiftlint:disable line_length func testBlockquoteWithinText() async { let htmlString = """ The text before the blockquote
For 50 years, WWF has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.The text after the blockquote """ guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 3) XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 3) for run in attributedString.runs { if run.elementX.blockquote != nil { return } } XCTFail("Couldn't find blockquote") } // swiftlint:enable line_length func testBlockquoteWithLink() async { let htmlString = "
Blockquote with a link in it" guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 3) guard let coalescedComponents = attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString) else { XCTFail("Could not build the attributed string components") return } XCTAssertEqual(coalescedComponents.count, 1) XCTAssertEqual(coalescedComponents.first?.attributedString.runs.count, 3, "Link not present in the component") var foundBlockquoteAndLink = false for run in attributedString.runs { if run.elementX.blockquote != nil, run.link != nil { foundBlockquoteAndLink = true } } XCTAssertNotNil(foundBlockquoteAndLink, "Couldn't find blockquote or link") } func testMultipleGroupedBlockquotes() async { let htmlString = """
First blockquote with a link in it
Second blockquote with a link in it
Third blockquote with a link in it""" guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 7) XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 1) var numberOfBlockquotes = 0 for run in attributedString.runs { if run.elementX.blockquote != nil, run.link != nil { numberOfBlockquotes += 1 } } XCTAssertEqual(numberOfBlockquotes, 3, "Couldn't find all the blockquotes") } func testMultipleSeparatedBlockquotes() async { let htmlString = """ First
blockquote with a link in itSecond
blockquote with a link in itThird
blockquote with a link in it""" guard let attributedString = await attributedStringBuilder.fromHTML(htmlString) else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 12) XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 6) var numberOfBlockquotes = 0 for run in attributedString.runs { if run.elementX.blockquote != nil, run.link != nil { numberOfBlockquotes += 1 } } XCTAssertEqual(numberOfBlockquotes, 3, "Couldn't find all the blockquotes") } // MARK: - Private private func checkMatrixEntityLinkIn(attributedString: AttributedString?, expected: String) { guard let attributedString = attributedString else { XCTFail("Could not build the attributed string") return } XCTAssertEqual(attributedString.runs.count, 3) for run in attributedString.runs { if run.link != nil { XCTAssertEqual(run.link?.path, expected) return } } XCTFail("Couldn't find expected value.") } }