mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
623 lines
21 KiB
Swift
Executable File
623 lines
21 KiB
Swift
Executable File
// Copyright © 2017 Schibsted. All rights reserved.
|
|
|
|
import XCTest
|
|
@testable import Layout
|
|
|
|
final class TestClass: NSObject {
|
|
@objc static var foo: Double {
|
|
return 5
|
|
}
|
|
}
|
|
|
|
func makeLayout(
|
|
expressions: [String: String] = [:],
|
|
parameters: [String: RuntimeType] = [:],
|
|
macros: [String: String] = [:],
|
|
children: [Layout] = []
|
|
) -> Layout {
|
|
return Layout(
|
|
className: "UIView",
|
|
id: nil,
|
|
expressions: expressions,
|
|
parameters: parameters,
|
|
macros: macros,
|
|
children: children,
|
|
body: nil,
|
|
xmlPath: nil,
|
|
templatePath: nil,
|
|
childrenTagIndex: nil,
|
|
relativePath: nil,
|
|
rootURL: nil
|
|
)
|
|
}
|
|
|
|
final class LayoutExpressionTests: XCTestCase {
|
|
// MARK: Expression parsing
|
|
|
|
func testParseExpressionWithoutBraces() {
|
|
let expression = try? parseExpression("4 + 5")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertEqual(expression?.symbols, [.infix("+")])
|
|
}
|
|
|
|
func testParseExpressionWithBraces() {
|
|
let expression = try? parseExpression("{4 + 5}")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertEqual(expression?.symbols, [.infix("+")])
|
|
}
|
|
|
|
func testParseExpressionWithBracesAndWhitespace() {
|
|
let expression = try? parseExpression(" {4 + 5} ")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertEqual(expression?.symbols, [.infix("+")])
|
|
}
|
|
|
|
func testParseExpressionWithLeadingGarbage() {
|
|
XCTAssertThrowsError(try parseExpression("foo {4 + 5}"))
|
|
}
|
|
|
|
func testParseExpressionWithTrailingGarbage() {
|
|
XCTAssertThrowsError(try parseExpression("{4 + 5} foo"))
|
|
}
|
|
|
|
func testParseExpressionWithBracesWithLeadingWhitespace() {
|
|
XCTAssertNoThrow(try parseExpression("{ 4 + 5}"))
|
|
}
|
|
|
|
func testParseExpressionWithLeadingWhitespace() {
|
|
XCTAssertNoThrow(try parseExpression(" 4 + 5"))
|
|
}
|
|
|
|
func testParseEmptyExpression() {
|
|
XCTAssertNoThrow(try parseExpression(""))
|
|
}
|
|
|
|
func testParseExpressionWithEmptyBraces() {
|
|
XCTAssertNoThrow(try parseExpression("{}"))
|
|
}
|
|
|
|
func testParseExpressionOpeningBrace() {
|
|
XCTAssertThrowsError(try parseExpression("{"))
|
|
}
|
|
|
|
func testParseExpressionWithClosingBrace() {
|
|
XCTAssertThrowsError(try parseExpression("}"))
|
|
}
|
|
|
|
func testParseExpressionWithMissingClosingBrace() {
|
|
XCTAssertThrowsError(try parseExpression("{4 + 5"))
|
|
}
|
|
|
|
func testParseExpressionWithMissingOpeningBrace() {
|
|
XCTAssertThrowsError(try parseExpression("4 + 5}"))
|
|
}
|
|
|
|
func testParseExpressionWithExtraOpeningBrace() {
|
|
XCTAssertThrowsError(try parseExpression("{{4 + 5}"))
|
|
}
|
|
|
|
func testParseExpressionWithExtraClosingBrace() {
|
|
XCTAssertThrowsError(try parseExpression("{4 + 5}}"))
|
|
}
|
|
|
|
func testParseExpressionWithClosingBraceInQuotes() {
|
|
let expression = try? parseExpression("{'}'}")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertNil(expression?.error)
|
|
}
|
|
|
|
func testParseExpressionWithOpeningBraceInQuotes() {
|
|
let expression = try? parseExpression("{'{'}")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertNil(expression?.error)
|
|
}
|
|
|
|
func testParseExpressionWithBracesInQuotes() {
|
|
let expression = try? parseExpression("{'{foo}'}")
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertNil(expression?.error)
|
|
}
|
|
|
|
// MARK: String expression parsing
|
|
|
|
func testParseStringExpressionWithoutBraces() {
|
|
let parts = (try? parseStringExpression("4 + 5")) ?? []
|
|
XCTAssertEqual(parts.count, 1)
|
|
guard let part = parts.first, case let .string(string) = part else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(string, "4 + 5")
|
|
}
|
|
|
|
func testParseStringExpressionWithBraces() {
|
|
let parts = (try? parseStringExpression("{4 + 5}")) ?? []
|
|
XCTAssertEqual(parts.count, 1)
|
|
guard let part = parts.first, case let .expression(expression) = part else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(expression.symbols, [.infix("+")])
|
|
}
|
|
|
|
func testParseStringExpressionWithBracesAndWhitespace() {
|
|
let parts = (try? parseStringExpression(" {4 + 5} ")) ?? []
|
|
guard parts.count == 3 else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .string(a) = parts[0], a == " " else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .expression(b) = parts[1], b.symbols == [.infix("+")] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .string(c) = parts[2], c == " " else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
}
|
|
|
|
func testParseStringExpressionWithMultipleBraces() {
|
|
let parts = (try? parseStringExpression("{4} + {5}")) ?? []
|
|
guard parts.count == 3 else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .expression(a) = parts[0], a.symbols == [] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .string(b) = parts[1], b == " + " else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .expression(c) = parts[2], c.symbols == [] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
}
|
|
|
|
func testParseEmptyStringExpression() {
|
|
do {
|
|
let parts = try parseStringExpression("")
|
|
XCTAssertTrue(parts.isEmpty)
|
|
} catch {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func testParseStringExpressionWithEmptyBraces() {
|
|
XCTAssertNoThrow(try parseStringExpression("{}"))
|
|
}
|
|
|
|
func testParseStringExpressionOpeningBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("{"))
|
|
}
|
|
|
|
func testParseStringExpressionClosingBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("}"))
|
|
}
|
|
|
|
func testParseStringExpressionWithMissingClosingBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("{4 + 5"))
|
|
}
|
|
|
|
func testParseStringExpressionWithMissingOpeningBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("4 + 5}"))
|
|
}
|
|
|
|
func testParseStringExpressionWithExtraOpeningBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("{{4 + 5}"))
|
|
}
|
|
|
|
func testParseStringExpressionWithExtraClosingBrace() {
|
|
XCTAssertThrowsError(try parseStringExpression("{4 + 5}}"))
|
|
}
|
|
|
|
func testParseStringExpressionWithClosingBraceInQuotes() {
|
|
let parts = (try? parseStringExpression("{'}'}")) ?? []
|
|
XCTAssertEqual(parts.count, 1)
|
|
guard let part = parts.first, case let .expression(expression) = part else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertNil(expression.error)
|
|
}
|
|
|
|
func testParseStringExpressionWithOpeningBraceInQuotes() {
|
|
let parts = (try? parseStringExpression("{'{'}")) ?? []
|
|
XCTAssertEqual(parts.count, 1)
|
|
guard let part = parts.first, case let .expression(expression) = part else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertNil(expression.error)
|
|
}
|
|
|
|
func testParseStringExpressionWithBracesInQuotes() {
|
|
let parts = (try? parseStringExpression("{'{foo}'}")) ?? []
|
|
XCTAssertEqual(parts.count, 1)
|
|
guard let part = parts.first, case let .expression(expression) = part else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertNil(expression.error)
|
|
}
|
|
|
|
// MARK: Expression comments
|
|
|
|
func testParseExpressionWithCommentWithoutBraces() throws {
|
|
let expression = try parseExpression("4 + 5 // hello")
|
|
XCTAssertEqual(expression.symbols, [.infix("+")])
|
|
XCTAssertEqual(expression.description, "4 + 5 // hello")
|
|
}
|
|
|
|
func testCommentedOutExpressionWithoutBraces() throws {
|
|
let expression = try parseExpression(" //4 + 5")
|
|
XCTAssertEqual(expression.isEmpty, true)
|
|
XCTAssertEqual(expression.description, "// 4 + 5")
|
|
}
|
|
|
|
func testParseExpressionWithCommentInBraces() throws {
|
|
let expression = try parseExpression("{4 + 5 // hello}")
|
|
XCTAssertEqual(expression.symbols, [.infix("+")])
|
|
XCTAssertEqual(expression.description, "4 + 5 // hello")
|
|
}
|
|
|
|
func testParseExpressionWithCommentAfterBraces() throws {
|
|
let expression = try parseExpression("{4 + 5} // hello")
|
|
XCTAssertEqual(expression.symbols, [.infix("+")])
|
|
XCTAssertEqual(expression.description, "4 + 5 // hello")
|
|
}
|
|
|
|
func testParseExpressionWithCommentInAndAfterBraces() throws {
|
|
let expression = try parseExpression("{4 + 5 // hello} // world")
|
|
XCTAssertEqual(expression.symbols, [.infix("+")])
|
|
XCTAssertEqual(expression.description, "4 + 5 // hello // world")
|
|
}
|
|
|
|
func testCommentedOutExpressionWithBraces() throws {
|
|
let expression = try parseExpression("{ //4 + 5}")
|
|
XCTAssertEqual(expression.isEmpty, true)
|
|
XCTAssertEqual(expression.description, "// 4 + 5")
|
|
}
|
|
|
|
func testParseExpressionWithCommentBeforeBraces() throws {
|
|
let expression = try parseExpression(" //{4 + 5}")
|
|
XCTAssertEqual(expression.isEmpty, true)
|
|
XCTAssertEqual(expression.description, "// {4 + 5}")
|
|
}
|
|
|
|
// MARK: String expression comments
|
|
|
|
func testParseStringExpressionWithComment() throws {
|
|
let expression = "foo {4 + 5 // hello } bar"
|
|
let parts = try parseStringExpression(expression)
|
|
guard parts.count == 3 else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case .string("foo ") = parts[0] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .expression(exp) = parts[1] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(exp.symbols, [.infix("+")])
|
|
XCTAssertEqual(exp.description, "4 + 5 // hello")
|
|
XCTAssertNil(exp.error)
|
|
guard case .string(" bar") = parts[2] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard let layoutExpression = LayoutExpression(stringExpression: expression, for: LayoutNode()) else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(try layoutExpression.evaluate() as? String, "foo 9 bar")
|
|
}
|
|
|
|
func testParseStringExpressionWithCommentedOutClause() throws {
|
|
let expression = "foo {// 4 + 5} bar"
|
|
let parts = try parseStringExpression(expression)
|
|
guard parts.count == 3 else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case .string("foo ") = parts[0] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .expression(exp) = parts[1] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(exp.symbols, [])
|
|
XCTAssertEqual(exp.description, "// 4 + 5")
|
|
XCTAssertTrue(exp.isEmpty)
|
|
guard let layoutExpression = LayoutExpression(stringExpression: expression, for: LayoutNode()) else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(try layoutExpression.evaluate() as? String, "foo bar")
|
|
}
|
|
|
|
func testCommentedOutStringExpression() throws {
|
|
let expression = " //hello {'world'}"
|
|
let parts = try parseStringExpression(expression)
|
|
guard parts.count == 1 else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
guard case let .comment(comment) = parts[0] else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertEqual(comment, "hello {'world'}")
|
|
XCTAssertEqual(parts.description, "// hello {'world'}")
|
|
XCTAssertNil(LayoutExpression(stringExpression: expression, for: LayoutNode()))
|
|
}
|
|
|
|
// MARK: Image and color expression comments
|
|
|
|
func testCommentedOutColorExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(colorExpression: "// red", for: node)
|
|
XCTAssertNil(expression)
|
|
}
|
|
|
|
func testCommentedOutImageExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(imageExpression: "// MyImage.png", for: node)
|
|
XCTAssertNil(expression)
|
|
}
|
|
|
|
func testColorExpressionWithComment() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(colorExpression: "red // comment", for: node)
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertEqual(try expression?.evaluate() as? UIColor, .red)
|
|
}
|
|
|
|
func testImageExpressionWithComment() { // Not supported
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(imageExpression: "MyImage.png // comment", for: node)
|
|
XCTAssertNotNil(expression)
|
|
XCTAssertThrowsError(try expression?.evaluate())
|
|
}
|
|
|
|
// MARK: Class properties
|
|
|
|
func testClassPropertyInDoubleExpression() {
|
|
let node = LayoutNode()
|
|
let className = NSStringFromClass(TestClass.self)
|
|
let expression = LayoutExpression(doubleExpression: "\(className).foo", for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 5)
|
|
}
|
|
|
|
func testUIColorPropertyInColorExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(colorExpression: "UIColor.red", for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? UIColor, .red)
|
|
}
|
|
|
|
func testEnumPropertyInEnumExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(expression: "UIViewContentMode.center", type: .uiViewContentMode, for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? UIView.ContentMode, .center)
|
|
}
|
|
|
|
func testOptionSetPropertyInEnumExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(expression: "UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight", type: .uiViewAutoresizing, for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? UIView.AutoresizingMask, [.flexibleWidth, .flexibleHeight])
|
|
}
|
|
|
|
// MARK: Integration tests
|
|
|
|
func testOptionalBracesInNumberExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(doubleExpression: "{4 + 5}", for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 9)
|
|
}
|
|
|
|
func testOptionalBracesInColorExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(colorExpression: "{white}", for: node)
|
|
XCTAssertEqual(try expression?.evaluate() as? UIColor, .white)
|
|
}
|
|
|
|
func testOptionalMultipleExpressionBodiesDisallowedInNumberExpression() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(doubleExpression: "{5}{6}", for: node)
|
|
XCTAssertThrowsError(try expression?.evaluate())
|
|
}
|
|
|
|
func testFalseTreatedAsConstant() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(boolExpression: "false", for: node)
|
|
XCTAssertEqual(expression?.symbols.isEmpty, true)
|
|
}
|
|
|
|
func testSetLayerContentsWithCGImageConstant() throws {
|
|
UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
|
|
let image: AnyObject = try XCTUnwrap(UIGraphicsGetImageFromCurrentImageContext()?.cgImage)
|
|
UIGraphicsEndImageContext()
|
|
let node = LayoutNode(
|
|
constants: ["image": image],
|
|
expressions: ["layer.contents": "{image}"]
|
|
)
|
|
node.update()
|
|
XCTAssertTrue(node.view.layer.contents as AnyObject === image)
|
|
}
|
|
|
|
func testSetLayerContentsWithUIImageConstant() throws {
|
|
UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
|
|
let image = try XCTUnwrap(UIGraphicsGetImageFromCurrentImageContext())
|
|
UIGraphicsEndImageContext()
|
|
let node = LayoutNode(
|
|
constants: ["image": image],
|
|
expressions: ["layer.contents": "{image}"]
|
|
)
|
|
node.update()
|
|
XCTAssertTrue(node.view.layer.contents as AnyObject === image.cgImage as AnyObject)
|
|
}
|
|
|
|
func testSetLayerShadowPathWithConstant() {
|
|
let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
|
|
let path = CGPath(rect: rect, transform: nil)
|
|
let node = LayoutNode(
|
|
constants: ["path": path],
|
|
expressions: ["layer.shadowPath": "path"]
|
|
)
|
|
node.update()
|
|
XCTAssertEqual(node.view.layer.shadowPath, path)
|
|
}
|
|
|
|
func testThrowErrorForConstantExpression() {
|
|
let node = LayoutNode(
|
|
constants: ["foo": "Not a color"],
|
|
expressions: ["backgroundColor": "{foo}"]
|
|
)
|
|
node.update()
|
|
XCTAssertThrowsError(try node.throwUnhandledError())
|
|
}
|
|
|
|
// MARK: Constant optimization
|
|
|
|
func testLiteral() {
|
|
let node = LayoutNode()
|
|
let expression = LayoutExpression(doubleExpression: "5 + 6", for: node)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testConstant() {
|
|
let node = LayoutNode(constants: ["foo": 5])
|
|
let expression = LayoutExpression(doubleExpression: "foo + 6", for: node)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testState() {
|
|
let node = LayoutNode(state: ["foo": 5])
|
|
let expression = LayoutExpression(doubleExpression: "foo + 6", for: node)
|
|
XCTAssertEqual(expression?.isConstant, false)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testInheritedConstant() {
|
|
let child = LayoutNode()
|
|
let parent = LayoutNode(constants: ["foo": 5], children: [child])
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "foo + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testParentLiteralExpression() {
|
|
let child = LayoutNode()
|
|
let parent = LayoutNode(expressions: ["height": "5"], children: [child])
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "parent.height + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testParentConstantExpression() {
|
|
let child = LayoutNode()
|
|
let parent = LayoutNode(constants: ["foo": 5], expressions: ["height": "foo + 6"], children: [child])
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "parent.height + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 17)
|
|
}
|
|
|
|
func testLiteralParameter() throws {
|
|
let layout = makeLayout(
|
|
expressions: ["foo": "5"],
|
|
parameters: ["foo": RuntimeType(Int.self)],
|
|
children: [
|
|
makeLayout(),
|
|
]
|
|
)
|
|
let parent = try LayoutNode(layout: layout)
|
|
let child = parent.children[0]
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "foo + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testConstantParameter() throws {
|
|
let layout = makeLayout(
|
|
expressions: ["foo": "bar + 3"],
|
|
parameters: ["foo": RuntimeType(Int.self)],
|
|
children: [
|
|
makeLayout(),
|
|
]
|
|
)
|
|
let parent = try LayoutNode(layout: layout, constants: ["bar": 5])
|
|
let child = parent.children[0]
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "foo + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 14)
|
|
}
|
|
|
|
func testLiteralMacro() throws {
|
|
let layout = makeLayout(
|
|
macros: ["BAR": "5"],
|
|
children: [
|
|
makeLayout(),
|
|
]
|
|
)
|
|
let parent = try LayoutNode(layout: layout)
|
|
let child = parent.children[0]
|
|
parent.update()
|
|
let expression = LayoutExpression(doubleExpression: "BAR + 6", for: child)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 11)
|
|
}
|
|
|
|
func testArrayMacro() throws {
|
|
let layout = makeLayout(macros: ["ITEMS": "1,2,3"])
|
|
let node = try LayoutNode(layout: layout)
|
|
node.update()
|
|
let expression = LayoutExpression(doubleExpression: "ITEMS[1]", for: node)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 2)
|
|
}
|
|
|
|
func testArrayMacro2() throws {
|
|
let layout = makeLayout(macros: ["ITEMS": "[1,2,3]"])
|
|
let node = try LayoutNode(layout: layout)
|
|
node.update()
|
|
let expression = LayoutExpression(doubleExpression: "ITEMS[1]", for: node)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? Double, 2)
|
|
}
|
|
|
|
func testArrayConstant() {
|
|
let node = LayoutNode(constants: ["items": ["foo", "bar", "baz"]])
|
|
node.update()
|
|
let expression = LayoutExpression(stringExpression: "{items[0]}", for: node)
|
|
XCTAssertEqual(expression?.isConstant, true)
|
|
XCTAssertEqual(try expression?.evaluate() as? String, "foo")
|
|
}
|
|
|
|
// MARK: Edge cases
|
|
|
|
func testPercentOperatorSpacingAmbiguity() {
|
|
let child = LayoutNode(expressions: ["width": "100%-5"])
|
|
let parent = LayoutNode(expressions: ["width": "50"], children: [child])
|
|
parent.update()
|
|
XCTAssertEqual(child.frame.width, 45)
|
|
}
|
|
}
|