// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // @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 where run.elementX.blockquote ?? false { 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 where run.elementX.blockquote ?? false { 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 where run.elementX.blockquote ?? false && 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 where run.elementX.blockquote ?? false && 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 where run.elementX.blockquote ?? false && 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 where run.link != nil { XCTAssertEqual(run.link?.path, expected) return } XCTFail("Couldn't find expected value.") } }