// Copyright © 2017 Schibsted. All rights reserved. import XCTest @testable import Layout final class XMLTests: XCTestCase { // MARK: Malformed XML func testEmptyXML() throws { let input = "" XCTAssertThrowsError(try Layout(xmlData: XCTUnwrap(input.data(using: .utf8)))) { error in XCTAssert("\(error)".contains("Empty")) } } func testHTMLAtRoot() throws { let input = "" XCTAssertThrowsError(try Layout(xmlData: XCTUnwrap(input.data(using: .utf8)))) { error in XCTAssert("\(error)".contains("Invalid root")) } } func testViewInsideHTML() throws { let input = "

" XCTAssertThrowsError(try Layout(xmlData: XCTUnwrap(input.data(using: .utf8)))) { error in XCTAssert("\(error)".contains("Unsupported HTML")) } } func testViewInsideHTMLInsideLabel() throws { let input = "

hello world

" XCTAssertThrowsError(try Layout(xmlData: XCTUnwrap(input.data(using: .utf8)))) { error in guard let layoutError = error as? LayoutError else { XCTFail("\(error)") return } XCTAssertTrue("\(layoutError)".contains("Unsupported HTML")) XCTAssertTrue("\(layoutError)".contains("UIView")) } } func testMismatchedHTML() throws { let input = "Some bold text" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("bold")) } } func testMissingParameterAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("type is a required attribute")) } } func testExtraParameterAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("Unexpected attribute value")) } } func testUnknownParameterType() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("Unknown or unsupported type")) } } func testChildNodeInParameter() throws { let input = "foo" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("should not contain sub-nodes")) } } func testMissingMacroAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("name is a required attribute")) } } func testExtraMacroAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("Unexpected attribute type")) } } func testChildNodeInMacro() throws { let input = "foo" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("should not contain sub-nodes")) } } func testStringInOutletAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertNoThrow(try Layout(xmlData: xmlData)) } func testCommentedOutOutletAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertNoThrow(try Layout(xmlData: xmlData)) } func testEmptyOutletAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertNoThrow(try Layout(xmlData: xmlData)) } func testExpressionInXMLAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("xml must be a literal value")) } } func testExpressionInTemplateAttribute() throws { let input = "" let xmlData = try XCTUnwrap(input.data(using: .utf8)) XCTAssertThrowsError(try Layout(xmlData: xmlData)) { error in XCTAssert("\(error)".contains("template must be a literal value")) } } // MARK: White space func testDiscardLeadingWhitespace() throws { let input = " " let xmlData = try XCTUnwrap(input.data(using: .utf8)) let xml = try XMLParser.parse(data: xmlData) guard xml.count == 1, case let .node(name, _, _) = xml[0] else { XCTFail() return } XCTAssertEqual(name, "UIView") } func testDiscardWhitespaceInsideLabel() throws { let input = "\n Foo\n" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, "Foo") } func testInterleavedTextAndViewsInsideLabel() throws { let input = "FooBar" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, "FooBar") } func testPreserveWhitespaceInsideHTML() throws { let html = "Some bold and italic text" let input = "\n \(html)\n" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, html) } func testPreserveHTMLAttributes() throws { let html = "An tag" let input = "\n \(html)\n" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, html) } // MARK: Entity encoding func testEncodeXMLEntities() { let input = "if 2 > 3 && 1 < 4" let expected = "if 2 > 3 && 1 < 4" XCTAssertEqual(input.xmlEncoded(), expected) } func testNoEncodeHTMLEntitiesInText() throws { let text = "2 legs are < 4 legs" let input = "\(text.xmlEncoded())" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, text) } func testEncodeHTMLEntitiesInHTML() throws { let html = "2 legs are < 4 legs
" let input = "\(html)" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, html) } func testEncodeHTMLEntitiesInHTML2() throws { let html = "

2 legs are < 4 legs

" let input = "\(html)" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, html) } func testEncodeHTMLEntitiesInHTML3() throws { let html = "trial & error" let input = "\(html)" let xmlData = try XCTUnwrap(input.data(using: .utf8)) let layout = try Layout(xmlData: xmlData) XCTAssertEqual(layout.body, html) } }