diff --git a/Constrictor.podspec b/Constrictor.podspec index 2749f2a..ebbdf7d 100644 --- a/Constrictor.podspec +++ b/Constrictor.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| - s.swift_version = "4.2" + s.swift_version = "5.0" s.name = "Constrictor" - s.version = "5.0.1" + s.version = "6.0.0" s.summary = "🐍 Constrict your layout in Swift" s.description = "Constrict your Auto Layout code with Constrictor, your chainable sugar." diff --git a/Constrictor/Constrictor.xcodeproj/project.pbxproj b/Constrictor/Constrictor.xcodeproj/project.pbxproj index 3e7020c..d03227e 100644 --- a/Constrictor/Constrictor.xcodeproj/project.pbxproj +++ b/Constrictor/Constrictor.xcodeproj/project.pbxproj @@ -517,7 +517,7 @@ }; 53D8198620B57C0B00E62D1E = { CreatedOnToolsVersion = 9.3; - LastSwiftMigration = 0930; + LastSwiftMigration = 1020; }; }; }; @@ -526,7 +526,6 @@ developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - en, ); mainGroup = 53CDE3B420B3201E007E4AE0; productRefGroup = 53CDE3BF20B3201E007E4AE0 /* Products */; @@ -823,7 +822,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -851,7 +850,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -872,7 +871,7 @@ PRODUCT_BUNDLE_IDENTIFIER = pedrommcarrasco.ConstrictorTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -892,7 +891,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = pedrommcarrasco.ConstrictorTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Constrictor/Constrictor.xcodeproj/xcshareddata/xcschemes/Constrictor.xcscheme b/Constrictor/Constrictor.xcodeproj/xcshareddata/xcschemes/Constrictor.xcscheme index 4295278..28c9893 100644 --- a/Constrictor/Constrictor.xcodeproj/xcshareddata/xcschemes/Constrictor.xcscheme +++ b/Constrictor/Constrictor.xcodeproj/xcshareddata/xcschemes/Constrictor.xcscheme @@ -1,6 +1,6 @@ Self { - + func centerY(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorYAxis = .centerY, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.centerYAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.centerY.append(constraint) return self } @discardableResult - public func top(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorYAxis = .top, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func top(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorYAxis = .top, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.topAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.top.append(constraint) return self } @discardableResult - public func bottom(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorYAxis = .bottom, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func bottom(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorYAxis = .bottom, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.bottomAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.bottom.append(constraint) return self @@ -77,105 +77,105 @@ extension Constrictor { // MARK: XAxis @discardableResult - public func centerX(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorXAxis = .centerX, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func centerX(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorXAxis = .centerX, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.centerXAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.centerX.append(constraint) return self } @discardableResult - public func leading(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorXAxis = .leading, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func leading(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorXAxis = .leading, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.leadingAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.leading.append(constraint) return self } @discardableResult - public func trailing(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorXAxis = .trailing, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func trailing(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorXAxis = .trailing, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.trailingAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.trailing.append(constraint) return self } @discardableResult - public func right(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorXAxis = .right, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func right(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorXAxis = .right, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.rightAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.right.append(constraint) return self } @discardableResult - public func left(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorXAxis = .left, - with constant: CGFloat = 0, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func left(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorXAxis = .left, + with constant: CGFloat = 0, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.leftAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.left.append(constraint) return self @@ -183,82 +183,82 @@ extension Constrictor { // MARK: AnchorDimension @discardableResult - public func width(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorDimension = .width, - with constant: CGFloat = 0, - multiplyBy multiplier: CGFloat = 1, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func width(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorDimension = .width, + with constant: CGFloat = 0, + multiplyBy multiplier: CGFloat = 1, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.widthAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - multiplier: multiplier, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + multiplier: multiplier, + priority: priority, + state: state) constraints.width.append(constraint) return self } @discardableResult - public func width(as relation: LayoutRelation = .equal, - to constant: CGFloat, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func width(as relation: LayoutRelation = .equal, + to constant: CGFloat, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchor: object.widthAnchor, - relation: relation, - constant: constant, - priority: priority, - state: state) + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.width.append(constraint) return self } @discardableResult - public func height(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attribute: AnchorDimension = .height, - with constant: CGFloat = 0, - multiplyBy multiplier: CGFloat = 1, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func height(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attribute: AnchorDimension = .height, + with constant: CGFloat = 0, + multiplyBy multiplier: CGFloat = 1, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchorA: object.heightAnchor, - anchorB: attribute.anchor(for: item), - relation: relation, - constant: constant, - multiplier: multiplier, - priority: priority, - state: state) + anchorB: attribute.anchor(for: item), + relation: relation, + constant: constant, + multiplier: multiplier, + priority: priority, + state: state) constraints.height.append(constraint) return self } @discardableResult - public func height(as relation: LayoutRelation = .equal, - to constant: CGFloat, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { - + func height(as relation: LayoutRelation = .equal, + to constant: CGFloat, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { + guard let object = object else { return self } Assembler.configure(object) let constraint = Assembler.constrict(anchor: object.heightAnchor, - relation: relation, - constant: constant, - priority: priority, - state: state) + relation: relation, + constant: constant, + priority: priority, + state: state) constraints.height.append(constraint) return self diff --git a/Constrictor/Constrictor/Modifiers/LayoutPriority.swift b/Constrictor/Constrictor/Modifiers/LayoutPriority.swift index 2ea232c..7a66bb9 100644 --- a/Constrictor/Constrictor/Modifiers/LayoutPriority.swift +++ b/Constrictor/Constrictor/Modifiers/LayoutPriority.swift @@ -40,11 +40,11 @@ extension LayoutPriority { // MARK: - Operators public extension LayoutPriority { - public static func +(lhs: LayoutPriority, rhs: Float) -> LayoutPriority { + static func +(lhs: LayoutPriority, rhs: Float) -> LayoutPriority { return LayoutPriority(lhs.value + rhs) } - public static func -(lhs: LayoutPriority, rhs: Float) -> LayoutPriority { + static func -(lhs: LayoutPriority, rhs: Float) -> LayoutPriority { return LayoutPriority(lhs.value - rhs) } } diff --git a/Constrictor/Constrictor/Modifiers/LayoutState.swift b/Constrictor/Constrictor/Modifiers/LayoutState.swift index 040f144..2e1b0c0 100644 --- a/Constrictor/Constrictor/Modifiers/LayoutState.swift +++ b/Constrictor/Constrictor/Modifiers/LayoutState.swift @@ -28,11 +28,11 @@ extension LayoutState { // MARK: - NSLayoutConstraint's Sugar public extension NSLayoutConstraint { - public func enable() { + func enable() { isActive = true } - public func disable() { + func disable() { isActive = false } } diff --git a/Constrictor/Constrictor/Sugar/Center/CenterConstant.swift b/Constrictor/Constrictor/Sugar/Center/CenterConstant.swift index d7983e7..2d63278 100644 --- a/Constrictor/Constrictor/Sugar/Center/CenterConstant.swift +++ b/Constrictor/Constrictor/Sugar/Center/CenterConstant.swift @@ -10,27 +10,27 @@ import UIKit // MARK: - CenterConstant public struct CenterConstant: Equatable { - + let centerX: CGFloat let centerY: CGFloat } // MARK: - Modifiers -extension CenterConstant { - - public static func centerX(_ value: CGFloat) -> CenterConstant { +public extension CenterConstant { + + static func centerX(_ value: CGFloat) -> CenterConstant { return CenterConstant(centerX: value, centerY: 0) } - - public static func centerY(_ value: CGFloat) -> CenterConstant { + + static func centerY(_ value: CGFloat) -> CenterConstant { return CenterConstant(centerX: 0, centerY: value) } } // MARK: - Operator -extension CenterConstant { - - public static func & (lhs: CenterConstant, rhs: CenterConstant) -> CenterConstant { +public extension CenterConstant { + + static func & (lhs: CenterConstant, rhs: CenterConstant) -> CenterConstant { return .init(centerX: lhs.centerX + rhs.centerX, centerY: lhs.centerY + rhs.centerY) } } diff --git a/Constrictor/Constrictor/Sugar/Center/Constrictor+Center.swift b/Constrictor/Constrictor/Sugar/Center/Constrictor+Center.swift index 718d3db..b6a6b33 100644 --- a/Constrictor/Constrictor/Sugar/Center/Constrictor+Center.swift +++ b/Constrictor/Constrictor/Sugar/Center/Constrictor+Center.swift @@ -9,10 +9,10 @@ import UIKit // MARK: - Center -extension Constrictor { +public extension Constrictor { @discardableResult - public func center(as relation: LayoutRelation = .equal, + func center(as relation: LayoutRelation = .equal, in item: Anchorable, with constant: CenterConstant, prioritizeAs priority: LayoutPriority = .required, @@ -27,7 +27,7 @@ extension Constrictor { } @discardableResult - public func center(as relation: LayoutRelation = .equal, + func center(as relation: LayoutRelation = .equal, in item: Anchorable, with constant: CGFloat = 0, prioritizeAs priority: LayoutPriority = .required, diff --git a/Constrictor/Constrictor/Sugar/Edge/Constrictor+Edge.swift b/Constrictor/Constrictor/Sugar/Edge/Constrictor+Edge.swift index 0cfac25..688df64 100644 --- a/Constrictor/Constrictor/Sugar/Edge/Constrictor+Edge.swift +++ b/Constrictor/Constrictor/Sugar/Edge/Constrictor+Edge.swift @@ -9,14 +9,14 @@ import UIKit // MARK: - Edge -extension Constrictor { +public extension Constrictor { @discardableResult - public func edge(as relation: LayoutRelation = .equal, - to item: Anchorable, - with constant: CGFloat, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func edge(as relation: LayoutRelation = .equal, + to item: Anchorable, + with constant: CGFloat, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { edge(as: relation, to: item, with: .all(constant), prioritizeAs: priority, is: state) @@ -24,11 +24,11 @@ extension Constrictor { } @discardableResult - public func edge(as relation: LayoutRelation = .equal, - to item: Anchorable, - with constant: EdgeConstant = .zero, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func edge(as relation: LayoutRelation = .equal, + to item: Anchorable, + with constant: EdgeConstant = .zero, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { top(as: relation, to: item, .top, with: constant.top, prioritizeAs: priority, is: state) bottom(as: relation, to: item, .bottom, with: constant.bottom, prioritizeAs: priority, is: state) @@ -39,12 +39,12 @@ extension Constrictor { } @discardableResult - public func edge(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attributes: EdgeAnchor ..., - with constant: CGFloat, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func edge(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attributes: EdgeAnchor ..., + with constant: CGFloat, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { internalVariadicEdge(as: relation, to: item, attributes, with: .all(constant), prioritizeAs: priority, is: state) @@ -53,12 +53,12 @@ extension Constrictor { } @discardableResult - public func edge(as relation: LayoutRelation = .equal, - to item: Anchorable, - _ attributes: EdgeAnchor ..., - with constant: EdgeConstant = .zero, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func edge(as relation: LayoutRelation = .equal, + to item: Anchorable, + _ attributes: EdgeAnchor ..., + with constant: EdgeConstant = .zero, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { internalVariadicEdge(as: relation, to: item, attributes, with: constant, prioritizeAs: priority, is: state) diff --git a/Constrictor/Constrictor/Sugar/Edge/EdgeConstant.swift b/Constrictor/Constrictor/Sugar/Edge/EdgeConstant.swift index 612fdc2..1eb876d 100644 --- a/Constrictor/Constrictor/Sugar/Edge/EdgeConstant.swift +++ b/Constrictor/Constrictor/Sugar/Edge/EdgeConstant.swift @@ -18,33 +18,33 @@ public struct EdgeConstant: Equatable { } // MARK: - Modifiers -extension EdgeConstant { +public extension EdgeConstant { - public static var zero: EdgeConstant { + static var zero: EdgeConstant { return EdgeConstant(top: 0, bottom: 0, leading: 0, trailing: 0) } - public static func top(_ value: CGFloat) -> EdgeConstant { + static func top(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: value, bottom: 0, leading: 0, trailing: 0) } - public static func bottom(_ value: CGFloat) -> EdgeConstant { + static func bottom(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: 0, bottom: -value, leading: 0, trailing: 0) } - public static func leading(_ value: CGFloat) -> EdgeConstant { + static func leading(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: 0, bottom: 0, leading: value, trailing: 0) } - public static func trailing(_ value: CGFloat) -> EdgeConstant { + static func trailing(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: 0, bottom: 0, leading: 0, trailing: -value) } - public static func vertical(_ value: CGFloat) -> EdgeConstant { + static func vertical(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: value, bottom: -value, leading: 0, trailing: 0) } - public static func horizontal(_ value: CGFloat) -> EdgeConstant { + static func horizontal(_ value: CGFloat) -> EdgeConstant { return EdgeConstant(top: 0, bottom: 0, leading: value, trailing: -value) } @@ -54,9 +54,9 @@ extension EdgeConstant { } // MARK: - Operator -extension EdgeConstant { +public extension EdgeConstant { - public static func & (lhs: EdgeConstant, rhs: EdgeConstant) -> EdgeConstant { + static func & (lhs: EdgeConstant, rhs: EdgeConstant) -> EdgeConstant { return .init(top: lhs.top + rhs.top, bottom: lhs.bottom + rhs.bottom, leading: lhs.leading + rhs.leading, diff --git a/Constrictor/Constrictor/Sugar/Size/Constrictor+Size.swift b/Constrictor/Constrictor/Sugar/Size/Constrictor+Size.swift index 0b0ae32..099e320 100644 --- a/Constrictor/Constrictor/Sugar/Size/Constrictor+Size.swift +++ b/Constrictor/Constrictor/Sugar/Size/Constrictor+Size.swift @@ -9,15 +9,15 @@ import UIKit // MARK: - Size -extension Constrictor { +public extension Constrictor { @discardableResult - public func size(as relation: LayoutRelation = .equal, - to item: Anchorable, - with constant: SizeConstant, - multiplyBy multiplier: CGFloat = 1, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func size(as relation: LayoutRelation = .equal, + to item: Anchorable, + with constant: SizeConstant, + multiplyBy multiplier: CGFloat = 1, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { width(as: relation, to: item, .width, with: constant.width, multiplyBy: multiplier, prioritizeAs: priority, is: state) @@ -28,12 +28,12 @@ extension Constrictor { } @discardableResult - public func size(as relation: LayoutRelation = .equal, - to item: Anchorable, - with constant: CGFloat = 0, - multiplyBy multiplier: CGFloat = 1, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func size(as relation: LayoutRelation = .equal, + to item: Anchorable, + with constant: CGFloat = 0, + multiplyBy multiplier: CGFloat = 1, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { width(as: relation, to: item, .width, with: constant, multiplyBy: multiplier, prioritizeAs: priority, is: state) @@ -44,10 +44,10 @@ extension Constrictor { } @discardableResult - public func size(as relation: LayoutRelation = .equal, - to constant: CGFloat, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func size(as relation: LayoutRelation = .equal, + to constant: CGFloat, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { width(as: relation, to: constant, prioritizeAs: priority, is: state) height(as: relation, to: constant, prioritizeAs: priority, is: state) @@ -56,10 +56,10 @@ extension Constrictor { } @discardableResult - public func size(as relation: LayoutRelation = .equal, - to constant: SizeConstant, - prioritizeAs priority: LayoutPriority = .required, - is state: LayoutState = .enabled) -> Self { + func size(as relation: LayoutRelation = .equal, + to constant: SizeConstant, + prioritizeAs priority: LayoutPriority = .required, + is state: LayoutState = .enabled) -> Self { width(as: relation, to: constant.width, prioritizeAs: priority, is: state) height(as: relation, to: constant.height, prioritizeAs: priority, is: state) diff --git a/Constrictor/Constrictor/Sugar/Size/SizeConstant.swift b/Constrictor/Constrictor/Sugar/Size/SizeConstant.swift index 3d0268f..665d2c3 100644 --- a/Constrictor/Constrictor/Sugar/Size/SizeConstant.swift +++ b/Constrictor/Constrictor/Sugar/Size/SizeConstant.swift @@ -10,36 +10,36 @@ import UIKit // MARK: - SizeConstant public struct SizeConstant: Equatable { - + let width: CGFloat let height: CGFloat } // MARK: - Internal Custom Initializer extension SizeConstant { - + init(size: CGFloat) { self = .width(size) & .height(size) } } // MARK: - Modifiers -extension SizeConstant { - - public static func width(_ value: CGFloat) -> SizeConstant { +public extension SizeConstant { + + static func width(_ value: CGFloat) -> SizeConstant { return SizeConstant(width: value, height: 0) } - - public static func height(_ value: CGFloat) -> SizeConstant { + + static func height(_ value: CGFloat) -> SizeConstant { return SizeConstant(width: 0, height: value) } } // MARK: - Operator -extension SizeConstant { - - public static func & (lhs: SizeConstant, rhs: SizeConstant) -> SizeConstant { - +public extension SizeConstant { + + static func & (lhs: SizeConstant, rhs: SizeConstant) -> SizeConstant { + return .init(width: lhs.width + rhs.width, height: lhs.height + rhs.height) } } diff --git a/Constrictor/Podfile b/Constrictor/Podfile index 253ff1d..fd7a445 100644 --- a/Constrictor/Podfile +++ b/Constrictor/Podfile @@ -3,7 +3,7 @@ use_frameworks! target 'ConstrictorTests' do - pod 'SnapshotTesting', '~> 1.1' + pod 'SnapshotTesting', '~> 1.4' end post_install do |installer| diff --git a/Constrictor/Podfile.lock b/Constrictor/Podfile.lock index 30ffaf0..256d056 100644 --- a/Constrictor/Podfile.lock +++ b/Constrictor/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - SnapshotTesting (1.1.0) + - SnapshotTesting (1.4.0) DEPENDENCIES: - - SnapshotTesting (~> 1.1) + - SnapshotTesting (~> 1.4.0) SPEC REPOS: https://github.com/cocoapods/specs.git: - SnapshotTesting SPEC CHECKSUMS: - SnapshotTesting: 8ed6a4dceee63f59a60e1bc86f9adbba54eb9287 + SnapshotTesting: f50ca26f5f9dd8b26e158289ea1c2a89e2e54742 -PODFILE CHECKSUM: c2d1ee1204c0b55e6541a1bbe5271ba7c0a0d3ff +PODFILE CHECKSUM: de5dc4e277c07572740e623da59f8e811be4246d COCOAPODS: 1.6.0.beta.1 diff --git a/Constrictor/Pods/Manifest.lock b/Constrictor/Pods/Manifest.lock index 30ffaf0..256d056 100644 --- a/Constrictor/Pods/Manifest.lock +++ b/Constrictor/Pods/Manifest.lock @@ -1,16 +1,16 @@ PODS: - - SnapshotTesting (1.1.0) + - SnapshotTesting (1.4.0) DEPENDENCIES: - - SnapshotTesting (~> 1.1) + - SnapshotTesting (~> 1.4.0) SPEC REPOS: https://github.com/cocoapods/specs.git: - SnapshotTesting SPEC CHECKSUMS: - SnapshotTesting: 8ed6a4dceee63f59a60e1bc86f9adbba54eb9287 + SnapshotTesting: f50ca26f5f9dd8b26e158289ea1c2a89e2e54742 -PODFILE CHECKSUM: c2d1ee1204c0b55e6541a1bbe5271ba7c0a0d3ff +PODFILE CHECKSUM: de5dc4e277c07572740e623da59f8e811be4246d COCOAPODS: 1.6.0.beta.1 diff --git a/Constrictor/Pods/Pods.xcodeproj/project.pbxproj b/Constrictor/Pods/Pods.xcodeproj/project.pbxproj index d82c649..ba0eac9 100644 --- a/Constrictor/Pods/Pods.xcodeproj/project.pbxproj +++ b/Constrictor/Pods/Pods.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -18,13 +18,13 @@ 3CBEB8C7276400C4604AA97EBEE8419C /* Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 325603FA43576B3DCC4EEFAEF9F7530A /* Description.swift */; }; 3E29BD58F67FC0A9F5CCFDA1A0F14795 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ACDFECA08ADBD6CDD9C2318938A8BE9 /* UIView.swift */; }; 3F19DC66C3B02B502FC0FAC81A873BCE /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = A82E55A56F39592AE4647226A5DB2287 /* View.swift */; }; - 430781CCB5F19890179B83F1D561E185 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0053906DC63793F7F0D6BAA7879F1832 /* Foundation.framework */; }; 4F7754FD27BCAA00E6D87F23113B4CE0 /* CaseIterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF54ACC954EA5787070EC0CA3F4693B /* CaseIterable.swift */; }; 508AF4A6705FE4B9D70621D8C31281C2 /* SceneKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = D515332841F90ABF6E4DFCAE6620DA5E /* SceneKit.swift */; }; 53F963F670A3DDAE232EDD7B044291B9 /* SnapshotTesting-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8285AA0CA3D78EC3378A0E9828676F10 /* SnapshotTesting-dummy.m */; }; 5E0A647CC78EBEE5D44809188DBC40FD /* AssertSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74FF6FCA8CBF73368D75CA7C70E5BA5 /* AssertSnapshot.swift */; }; - 67458423793EF0BE12341ED242996488 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FE887C3930818A0B7A8E28E7D81F69C /* XCTest.framework */; }; + 5E34D0FF7666AD3FF60EED03E0CCAC8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDD0F5DAA0AC84C5E3ADE087C20B50BA /* Foundation.framework */; }; 688427B9B44598EDEC610DBE7F17026B /* XCTAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14AE1765EB1929E24F909D1D306B073E /* XCTAttachment.swift */; }; + 6ADAD98355237942D4C0105F9D4E4491 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80C82283F763D9ABC7DD3BB91787CA8D /* XCTest.framework */; }; 6ADE7D11AC860A32C422E15F6B6A5564 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092F375574FD335EB56B8A1EE355E389 /* Data.swift */; }; 6B1EC42E5DA5161BCD048C138177C594 /* Diffing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 833AAD366DE4DCAA910215957A0AE76A /* Diffing.swift */; }; 76F3BB4BA1316262EFF133E5E362EA15 /* NSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66D350A0588112F2B73F69DB0622387 /* NSView.swift */; }; @@ -33,10 +33,10 @@ 971DBAF739F6ED28467628E5632745DB /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0EE1EA8BE6EB23C28EF87720692D787 /* Async.swift */; }; 9BE6F342FBA5FF9B9D91E577C3512B66 /* Snapshotting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F865817C0A762B13678E4596AB8002B /* Snapshotting.swift */; }; 9EDFAC2CCDBB87DE8CCA0FA85C170EF2 /* Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE4EED2A9B54CF465CC4D71CF3F68C4 /* Codable.swift */; }; - A2F85EF4D6D69EB08A5D7521E6254C2B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0053906DC63793F7F0D6BAA7879F1832 /* Foundation.framework */; }; D002B722B0D79BA3B8F93778511CD940 /* NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745432196BF88070F451D1239BCF9429 /* NSImage.swift */; }; D1DAC0D39B6F2B030AB934A4EC936F12 /* Pods-ConstrictorTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 221469C1C1D2FCB6CA0499CD0EF7D5E0 /* Pods-ConstrictorTests-dummy.m */; }; D8297A06B19CB79779B29783561C01A7 /* SnapshotTesting-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DA90B581CDC1DC1ED665207492DBB907 /* SnapshotTesting-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE3AEAF523C8DD4972696FB360F01D93 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDD0F5DAA0AC84C5E3ADE087C20B50BA /* Foundation.framework */; }; E7E773534F7A42F64781B1062026D53B /* SnapshotTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0073F73C63C35F3E0202890FFCBCDF6 /* SnapshotTestCase.swift */; }; F5C049C7A2020FC07E6C4B5B943E3381 /* PlistEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83A0B60CF06D276D8176F2F0029332FA /* PlistEncoder.swift */; }; FE8905CFF32DA588967FB5470CD2C93F /* SpriteKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0F6DE73E6E46FC214D37A6FC0DA44A /* SpriteKit.swift */; }; @@ -53,15 +53,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0053906DC63793F7F0D6BAA7879F1832 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 02CA5A9DFA1F7B95BA35010254C739B7 /* SnapshotTesting-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapshotTesting-prefix.pch"; sourceTree = ""; }; 092F375574FD335EB56B8A1EE355E389 /* Data.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Data.swift; path = Sources/SnapshotTesting/Snapshotting/Data.swift; sourceTree = ""; }; 14AE1765EB1929E24F909D1D306B073E /* XCTAttachment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XCTAttachment.swift; path = Sources/SnapshotTesting/Common/XCTAttachment.swift; sourceTree = ""; }; 170141470BCEE0E866A0883348175C4E /* SnapshotTesting.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapshotTesting.modulemap; sourceTree = ""; }; 221469C1C1D2FCB6CA0499CD0EF7D5E0 /* Pods-ConstrictorTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ConstrictorTests-dummy.m"; sourceTree = ""; }; - 27EC77F7C3488DFCCCEA895DFC58816F /* Pods_ConstrictorTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_ConstrictorTests.framework; path = "Pods-ConstrictorTests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 27EC77F7C3488DFCCCEA895DFC58816F /* Pods_ConstrictorTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ConstrictorTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2AB14DB2D8F0C464D4831532282F0C5E /* Pods-ConstrictorTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ConstrictorTests-acknowledgements.plist"; sourceTree = ""; }; - 2FE887C3930818A0B7A8E28E7D81F69C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 325603FA43576B3DCC4EEFAEF9F7530A /* Description.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Description.swift; path = Sources/SnapshotTesting/Snapshotting/Description.swift; sourceTree = ""; }; 3EE4EED2A9B54CF465CC4D71CF3F68C4 /* Codable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Codable.swift; path = Sources/SnapshotTesting/Snapshotting/Codable.swift; sourceTree = ""; }; 494B51A675744614AD15B1A21D72FE4A /* SnapshotTesting.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapshotTesting.xcconfig; sourceTree = ""; }; @@ -72,13 +70,14 @@ 745432196BF88070F451D1239BCF9429 /* NSImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSImage.swift; path = Sources/SnapshotTesting/Snapshotting/NSImage.swift; sourceTree = ""; }; 7C0F6DE73E6E46FC214D37A6FC0DA44A /* SpriteKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SpriteKit.swift; path = Sources/SnapshotTesting/Snapshotting/SpriteKit.swift; sourceTree = ""; }; 7F865817C0A762B13678E4596AB8002B /* Snapshotting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Snapshotting.swift; path = Sources/SnapshotTesting/Snapshotting.swift; sourceTree = ""; }; + 80C82283F763D9ABC7DD3BB91787CA8D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 8285AA0CA3D78EC3378A0E9828676F10 /* SnapshotTesting-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapshotTesting-dummy.m"; sourceTree = ""; }; 833AAD366DE4DCAA910215957A0AE76A /* Diffing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Diffing.swift; path = Sources/SnapshotTesting/Diffing.swift; sourceTree = ""; }; 83A0B60CF06D276D8176F2F0029332FA /* PlistEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PlistEncoder.swift; path = Sources/SnapshotTesting/Common/PlistEncoder.swift; sourceTree = ""; }; 854A369E2E37BA308006317BEF0920CE /* Pods-ConstrictorTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ConstrictorTests.release.xcconfig"; sourceTree = ""; }; 8BD60F79DDD62B1C0C539060F53CCB07 /* Pods-ConstrictorTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ConstrictorTests-Info.plist"; sourceTree = ""; }; 9068A0A19BBA5BF01A7A3C8250903EC5 /* Internal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Internal.swift; path = Sources/SnapshotTesting/Common/Internal.swift; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 95ED557CB4BE004DA7F162926A2A0EBE /* CALayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CALayer.swift; path = Sources/SnapshotTesting/Snapshotting/CALayer.swift; sourceTree = ""; }; 9FF54ACC954EA5787070EC0CA3F4693B /* CaseIterable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CaseIterable.swift; path = Sources/SnapshotTesting/Snapshotting/CaseIterable.swift; sourceTree = ""; }; A146FC323424AB3CE6A49F99D01AD153 /* Any.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Any.swift; path = Sources/SnapshotTesting/Snapshotting/Any.swift; sourceTree = ""; }; @@ -94,11 +93,12 @@ D2BCFFB3D8BC3093A9218098D2E71039 /* Pods-ConstrictorTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ConstrictorTests-acknowledgements.markdown"; sourceTree = ""; }; D515332841F90ABF6E4DFCAE6620DA5E /* SceneKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SceneKit.swift; path = Sources/SnapshotTesting/Snapshotting/SceneKit.swift; sourceTree = ""; }; DA90B581CDC1DC1ED665207492DBB907 /* SnapshotTesting-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapshotTesting-umbrella.h"; sourceTree = ""; }; + DDD0F5DAA0AC84C5E3ADE087C20B50BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; E725C7B9BC61A9FC2D26057FB33C64B1 /* URLRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLRequest.swift; path = Sources/SnapshotTesting/Snapshotting/URLRequest.swift; sourceTree = ""; }; E73FBE97CC48A13A6DA4A406481D7313 /* SnapshotTesting-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapshotTesting-Info.plist"; sourceTree = ""; }; F0812C20800F483A46C8A953FB689938 /* Diff.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Diff.swift; path = Sources/SnapshotTesting/Diff.swift; sourceTree = ""; }; F2C094AADC0877AF57D3CD850D515EAC /* NSViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSViewController.swift; path = Sources/SnapshotTesting/Snapshotting/NSViewController.swift; sourceTree = ""; }; - F999D3CE5BE9440A8A491FF5E0A7A3A0 /* SnapshotTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SnapshotTesting.framework; path = SnapshotTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F999D3CE5BE9440A8A491FF5E0A7A3A0 /* SnapshotTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SnapshotTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -106,7 +106,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 430781CCB5F19890179B83F1D561E185 /* Foundation.framework in Frameworks */, + DE3AEAF523C8DD4972696FB360F01D93 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -114,8 +114,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A2F85EF4D6D69EB08A5D7521E6254C2B /* Foundation.framework in Frameworks */, - 67458423793EF0BE12341ED242996488 /* XCTest.framework in Frameworks */, + 5E34D0FF7666AD3FF60EED03E0CCAC8B /* Foundation.framework in Frameworks */, + 6ADAD98355237942D4C0105F9D4E4491 /* XCTest.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -136,10 +136,19 @@ path = "../Target Support Files/SnapshotTesting"; sourceTree = ""; }; + 1E85F0F44277212282918D8D5DDB3588 /* iOS */ = { + isa = PBXGroup; + children = ( + DDD0F5DAA0AC84C5E3ADE087C20B50BA /* Foundation.framework */, + 80C82283F763D9ABC7DD3BB91787CA8D /* XCTest.framework */, + ); + name = iOS; + sourceTree = ""; + }; 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { isa = PBXGroup; children = ( - DA95CB2A265418BD1B13AF21F6D87DE4 /* iOS */, + 1E85F0F44277212282918D8D5DDB3588 /* iOS */, ); name = Frameworks; sourceTree = ""; @@ -188,15 +197,6 @@ name = "Targets Support Files"; sourceTree = ""; }; - DA95CB2A265418BD1B13AF21F6D87DE4 /* iOS */ = { - isa = PBXGroup; - children = ( - 0053906DC63793F7F0D6BAA7879F1832 /* Foundation.framework */, - 2FE887C3930818A0B7A8E28E7D81F69C /* XCTest.framework */, - ); - name = iOS; - sourceTree = ""; - }; DF627238B6F87F4FA8E3E4EC87856EE2 /* SnapshotTesting */ = { isa = PBXGroup; children = ( @@ -228,7 +228,6 @@ 14AE1765EB1929E24F909D1D306B073E /* XCTAttachment.swift */, 0128B634F5A5A9546A46EA05686F7FA9 /* Support Files */, ); - name = SnapshotTesting; path = SnapshotTesting; sourceTree = ""; }; @@ -307,13 +306,14 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; @@ -399,7 +399,7 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 76B9E5B324C60C9153B2B34E88F3888D /* Debug */ = { + 09F7FD5B1A4800CCD75520020D8B7935 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 57B76EA784B1B515C325A3998E704B11 /* Pods-ConstrictorTests.debug.xcconfig */; buildSettings = { @@ -418,11 +418,7 @@ INFOPLIST_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests.modulemap"; OTHER_LDFLAGS = ""; @@ -432,14 +428,16 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 85AFA1F5BD41800ABB53DA006F248C17 /* Debug */ = { + 0F30791590DD99157675B5F6EC28E4B0 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 494B51A675744614AD15B1A21D72FE4A /* SnapshotTesting.xcconfig */; buildSettings = { @@ -459,11 +457,7 @@ INFOPLIST_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting.modulemap"; PRODUCT_MODULE_NAME = SnapshotTesting; PRODUCT_NAME = SnapshotTesting; @@ -471,14 +465,89 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; - SWIFT_VERSION = 4.2; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */ = { + 31E59BC4A4F940CBCDDE21FD8E122B17 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 854A369E2E37BA308006317BEF0920CE /* Pods-ConstrictorTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_CODE_COVERAGE = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 64183AA35770F8CC1425E67DC050B6CC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 494B51A675744614AD15B1A21D72FE4A /* SnapshotTesting.xcconfig */; + buildSettings = { + CLANG_ENABLE_CODE_COVERAGE = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SnapshotTesting/SnapshotTesting-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting.modulemap"; + PRODUCT_MODULE_NAME = SnapshotTesting; + PRODUCT_NAME = SnapshotTesting; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C92782E717C52E3633C9A5F211E7987A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -538,93 +607,11 @@ PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; - 9AC5201AA67B978B48357E46D9A8C4D3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 494B51A675744614AD15B1A21D72FE4A /* SnapshotTesting.xcconfig */; - buildSettings = { - CLANG_ENABLE_CODE_COVERAGE = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SnapshotTesting/SnapshotTesting-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/SnapshotTesting/SnapshotTesting.modulemap"; - PRODUCT_MODULE_NAME = SnapshotTesting; - PRODUCT_NAME = SnapshotTesting; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - B24665A94C5F8EA2496731DFCF414EEA /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 854A369E2E37BA308006317BEF0920CE /* Pods-ConstrictorTests.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_CODE_COVERAGE = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EXEC = "$(SRCROOT)/SWIFT_EXEC-no-coverage"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - D5F759C82752B2EB010DB3CD3D69707C /* Release */ = { + EA8C7AF90938697605468604B2A17B9F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -679,9 +666,6 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; name = Release; @@ -692,8 +676,8 @@ 0CE803963A033501ED3002FFAADD7B0E /* Build configuration list for PBXNativeTarget "Pods-ConstrictorTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 76B9E5B324C60C9153B2B34E88F3888D /* Debug */, - B24665A94C5F8EA2496731DFCF414EEA /* Release */, + 09F7FD5B1A4800CCD75520020D8B7935 /* Debug */, + 31E59BC4A4F940CBCDDE21FD8E122B17 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -701,8 +685,8 @@ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */, - D5F759C82752B2EB010DB3CD3D69707C /* Release */, + C92782E717C52E3633C9A5F211E7987A /* Debug */, + EA8C7AF90938697605468604B2A17B9F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -710,8 +694,8 @@ 954A05EE55DA799258014DC44E436277 /* Build configuration list for PBXNativeTarget "SnapshotTesting" */ = { isa = XCConfigurationList; buildConfigurations = ( - 85AFA1F5BD41800ABB53DA006F248C17 /* Debug */, - 9AC5201AA67B978B48357E46D9A8C4D3 /* Release */, + 0F30791590DD99157675B5F6EC28E4B0 /* Debug */, + 64183AA35770F8CC1425E67DC050B6CC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Constrictor/Pods/SnapshotTesting/LICENSE b/Constrictor/Pods/SnapshotTesting/LICENSE index cb5a021..cb545c0 100644 --- a/Constrictor/Pods/SnapshotTesting/LICENSE +++ b/Constrictor/Pods/SnapshotTesting/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Point-Free, Inc. +Copyright (c) 2019 Point-Free, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Constrictor/Pods/SnapshotTesting/README.md b/Constrictor/Pods/SnapshotTesting/README.md index d361610..cf3fc9a 100644 --- a/Constrictor/Pods/SnapshotTesting/README.md +++ b/Constrictor/Pods/SnapshotTesting/README.md @@ -1,6 +1,6 @@ # 📸 SnapshotTesting -[![Swift 4.2](https://img.shields.io/badge/swift-4.2-ED523F.svg?style=flat)](https://swift.org/download/) [![iOS/macOS/tvOS CI](https://img.shields.io/circleci/project/github/pointfreeco/swift-snapshot-testing/master.svg?label=ios/macos/tvos)](https://circleci.com/gh/pointfreeco/swift-snapshot-testing) [![Linux CI](https://img.shields.io/travis/pointfreeco/swift-snapshot-testing/master.svg?label=linux)](https://travis-ci.org/pointfreeco/swift-nonempty) [![@pointfreeco](https://img.shields.io/badge/contact-@pointfreeco-5AA9E7.svg?style=flat)](https://twitter.com/pointfreeco) +[![Swift 5](https://img.shields.io/badge/swift-5-ED523F.svg?style=flat)](https://swift.org/download/) [![iOS/macOS/tvOS CI](https://img.shields.io/circleci/project/github/pointfreeco/swift-snapshot-testing/master.svg?label=ios/macos/tvos)](https://circleci.com/gh/pointfreeco/swift-snapshot-testing) [![Linux CI](https://img.shields.io/travis/pointfreeco/swift-snapshot-testing/master.svg?label=linux)](https://travis-ci.org/pointfreeco/swift-snapshot-testing) [![@pointfreeco](https://img.shields.io/badge/contact-@pointfreeco-5AA9E7.svg?style=flat)](https://twitter.com/pointfreeco) Delightful Swift snapshot testing. @@ -73,6 +73,8 @@ assertSnapshot(matching: vc, as: .image(on: .iPadMini(.portrait))) assertSnapshot(matching: vc, as: .recursiveDescription(on: .iPadMini(.portrait))) ``` +> ⚠️ Warning: Snapshots must be compared using a simulator with the same OS, device gamut, and scale as the simulator that originally took the reference to avoid discrepancies between images. + Better yet, SnapshotTesting isn't limited to views and view controllers! There are [a number of available snapshot strategies](Documentation/Available-Snapshot-Strategies.md) to choose from. For example, you can snapshot test URL requests (_e.g._, those that your API client prepares). @@ -129,7 +131,7 @@ If your data can be represented as an image, text, or data, you can write a snap If you use [Carthage](https://github.com/Carthage/Carthage), you can add the following dependency to your `Cartfile`: ``` ruby -github "pointfreeco/swift-snapshot-testing" ~> 1.1 +github "pointfreeco/swift-snapshot-testing" ~> 1.4 ``` > ⚠️ Warning: Carthage instructs you to drag frameworks into your Xcode project. Xcode may automatically attempt to link these frameworks to your app target. `SnapshotTesting.framework` is only compatible with test targets, so when you first add it to your project: @@ -147,7 +149,7 @@ If your project uses [CocoaPods](https://cocoapods.org), add the pod to any appl ```ruby target 'MyAppTests' do - pod 'SnapshotTesting', '~> 1.1' + pod 'SnapshotTesting', '~> 1.4' end ``` @@ -157,7 +159,7 @@ If you want to use SnapshotTesting in a project that uses [SwiftPM](https://swif ```swift dependencies: [ - .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.1.0"), + .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.4.0"), ] ``` @@ -174,6 +176,12 @@ dependencies: [ - **SceneKit, SpriteKit, and WebKit support.** Most snapshot testing libraries don't support these view subclasses. - **`Codable` support**. Snapshot encodable data structures into their [JSON](Documentation/Available-Snapshot-Strategies.md#json) and [property list](Documentation/Available-Snapshot-Strategies.md#plist) representations. - **Custom diff tool integration**. + +## Plug-ins + + - [swift-html](https://github.com/pointfreeco/swift-html) is a Swift DSL for type-safe, extensible, and transformable HTML documents and includes an `HtmlSnapshotTesting` module to snapshot test its HTML documents. + +Have you written your own SnapshotTesting plug-in? [Add it here](https://github.com/pointfreeco/swift-snapshot-testing/edit/master/README.md) and submit a pull request! ## Related Tools @@ -187,7 +195,7 @@ SnapshotTesting was designed with [witness-oriented programming](https://www.poi This concept (and more) are explored thoroughly in a series of episodes on [Point-Free](https://www.pointfree.co), a video series exploring functional programming and Swift hosted by [Brandon Williams](https://github.com/mbrandonw) and [Stephen Celis](https://github.com/stephencelis). -Witness-oriented programming was explored in the following episodes: +Witness-oriented programming and the design of this library was explored in the following [Point-Free](https://www.pointfree.co) episodes: - [Episode 33](https://www.pointfree.co/episodes/ep33-protocol-witnesses-part-1): Protocol Witnesses: Part 1 - [Episode 34](https://www.pointfree.co/episodes/ep34-protocol-witnesses-part-1): Protocol Witnesses: Part 2 @@ -196,9 +204,11 @@ Witness-oriented programming was explored in the following episodes: - [Episode 37](https://www.pointfree.co/episodes/ep37-protocol-oriented-library-design-part-1): Protocol-Oriented Library Design: Part 1 - [Episode 38](https://www.pointfree.co/episodes/ep38-protocol-oriented-library-design-part-2): Protocol-Oriented Library Design: Part 2 - [Episode 39](https://www.pointfree.co/episodes/ep39-witness-oriented-library-design): Witness-Oriented Library Design + - [Episode 40](https://www.pointfree.co/episodes/ep40-async-functional-refactoring): Async Functional Refactoring + - [Episode 41](https://www.pointfree.co/episodes/ep41-a-tour-of-snapshot-testing): A Tour of Snapshot Testing 🆓 - - video poster image + + video poster image ## License diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/AssertSnapshot.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/AssertSnapshot.swift index 6f3355a..b0339c5 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,4 +1,3 @@ -#if !os(Linux) import XCTest /// Enhances failure messages with a command line diff tool expression that can be copied and pasted into a terminal. @@ -32,7 +31,7 @@ public func assertSnapshot( ) { let failure = verifySnapshot( - matching: value, + matching: try value(), as: snapshotting, named: name, record: recording, @@ -45,13 +44,109 @@ public func assertSnapshot( XCTFail(message, file: file, line: line) } +/// Asserts that a given value matches references on disk. +/// +/// - Parameters: +/// - value: A value to compare against a reference. +/// - snapshotting: An dictionnay of names and strategies for serializing, deserializing, and comparing values. +/// - recording: Whether or not to record a new reference. +/// - timeout: The amount of time a snapshot must be generated in. +/// - file: The file in which failure occurred. Defaults to the file name of the test case in which this function was called. +/// - testName: The name of the test in which failure occurred. Defaults to the function name of the test case in which this function was called. +/// - line: The line number on which failure occurred. Defaults to the line number on which this function was called. +public func assertSnapshots( + matching value: @autoclosure () throws -> Value, + as strategies: [String: Snapshotting], + record recording: Bool = false, + timeout: TimeInterval = 5, + file: StaticString = #file, + testName: String = #function, + line: UInt = #line + ) { + + try? strategies.forEach { name, strategy in + assertSnapshot( + matching: try value(), + as: strategy, + named: name, + record: recording, + timeout: timeout, + file: file, + testName: testName, + line: line + ) + } +} + +/// Asserts that a given value matches references on disk. +/// +/// - Parameters: +/// - value: A value to compare against a reference. +/// - snapshotting: An array of strategies for serializing, deserializing, and comparing values. +/// - recording: Whether or not to record a new reference. +/// - timeout: The amount of time a snapshot must be generated in. +/// - file: The file in which failure occurred. Defaults to the file name of the test case in which this function was called. +/// - testName: The name of the test in which failure occurred. Defaults to the function name of the test case in which this function was called. +/// - line: The line number on which failure occurred. Defaults to the line number on which this function was called. +public func assertSnapshots( + matching value: @autoclosure () throws -> Value, + as strategies: [Snapshotting], + record recording: Bool = false, + timeout: TimeInterval = 5, + file: StaticString = #file, + testName: String = #function, + line: UInt = #line + ) { + + try? strategies.forEach { strategy in + assertSnapshot( + matching: try value(), + as: strategy, + record: recording, + timeout: timeout, + file: file, + testName: testName, + line: line + ) + } +} + /// Verifies that a given value matches a reference on disk. /// +/// Third party snapshot assert helpers can be built on top of this function. Simply invoke `verifySnapshot` with your own arguments, and then invoke `XCTFail` with the string returned if it is non-`nil`. For example, if you want the snapshot directory to be determined by an environment variable, you can create your own assert helper like so: +/// +/// public func myAssertSnapshot( +/// matching value: @autoclosure () throws -> Value, +/// as snapshotting: Snapshotting, +/// named name: String? = nil, +/// record recording: Bool = false, +/// timeout: TimeInterval = 5, +/// file: StaticString = #file, +/// testName: String = #function, +/// line: UInt = #line +/// ) { +/// +/// let snapshotDirectory = ProcessInfo.processInfo.environment["SNAPSHOT_REFERENCE_DIR"]! + "/" + #file +/// let failure = verifySnapshot( +/// matching: value, +/// as: snapshotting, +/// named: name, +/// record: recording, +/// snapshotDirectory: snapshotDirectory, +/// timeout: timeout, +/// file: file, +/// testName: testName +/// ) +/// guard let message = failure else { return } +/// XCTFail(message, file: file, line: line) +/// } +/// /// - Parameters: /// - value: A value to compare against a reference. /// - snapshotting: A strategy for serializing, deserializing, and comparing values. /// - name: An optional description of the snapshot. /// - recording: Whether or not to record a new reference. +/// - snapshotDirectory: Optional directory to save snapshots. By default snapshots will be saved in a directory with the same name as the test file, and that directory will sit inside a directory `__Snapshots__` that sits next to your test file. /// - timeout: The amount of time a snapshot must be generated in. /// - file: The file in which failure occurred. Defaults to the file name of the test case in which this function was called. /// - testName: The name of the test in which failure occurred. Defaults to the function name of the test case in which this function was called. @@ -62,6 +157,7 @@ public func verifySnapshot( as snapshotting: Snapshotting, named name: String? = nil, record recording: Bool = false, + snapshotDirectory: String? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -74,10 +170,12 @@ public func verifySnapshot( do { let fileUrl = URL(fileURLWithPath: "\(file)") let fileName = fileUrl.deletingPathExtension().lastPathComponent - let directoryUrl = fileUrl.deletingLastPathComponent() - let snapshotDirectoryUrl: URL = directoryUrl - .appendingPathComponent("__Snapshots__") - .appendingPathComponent(fileName) + + let snapshotDirectoryUrl = snapshotDirectory.map(URL.init(fileURLWithPath:)) + ?? fileUrl + .deletingLastPathComponent() + .appendingPathComponent("__Snapshots__") + .appendingPathComponent(fileName) let identifier: String if let name = name { @@ -112,6 +210,8 @@ public func verifySnapshot( return "Exceeded timeout of \(timeout) seconds waiting for snapshot" case .incorrectOrder, .invertedFulfillment, .interrupted: return "Couldn't snapshot value" + @unknown default: + return "Couldn't snapshot value" } guard let diffable = optionalDiffable else { @@ -127,11 +227,11 @@ public func verifySnapshot( try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) return recording ? """ - Record mode is on. \(diffMessage) + Record mode is on. Turn record mode off and re-run "\(testName)" to test against the newly-recorded snapshot. open "\(snapshotFileUrl.path)" - Turn record mode off and re-run "\(testName)" to test against the newly-recorded snapshot. + \(diffMessage) """ : """ No reference was found on disk. Automatically recorded snapshot: … @@ -173,9 +273,11 @@ public func verifySnapshot( .map { "\($0) \"\(snapshotFileUrl.path)\" \"\(failedSnapshotFileUrl.path)\"" } ?? "@\(minus)\n\"\(snapshotFileUrl.path)\"\n@\(plus)\n\"\(failedSnapshotFileUrl.path)\"" return """ - \(failure.trimmingCharacters(in: .whitespacesAndNewlines)) + Snapshot does not match reference. \(diffMessage) + + \(failure.trimmingCharacters(in: .whitespacesAndNewlines)) """ } catch { return error.localizedDescription @@ -184,7 +286,6 @@ public func verifySnapshot( private let counterQueue = DispatchQueue(label: "co.pointfree.SnapshotTesting.counter") private var counterMap: [URL: Int] = [:] -#endif func sanitizePathComponent(_ string: String) -> String { return string diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/View.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/View.swift index 02ec376..171b6d0 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/View.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/View.swift @@ -156,6 +156,19 @@ public struct ViewImageConfig { } return .init(safeArea: .init(top: 20, left: 0, bottom: 0, right: 0), size: size, traits: .iPadPro10_5) } + + public static let iPadPro11 = ViewImageConfig.iPadPro11(.landscape) + + public static func iPadPro11(_ orientation: Orientation) -> ViewImageConfig { + let size: CGSize + switch orientation { + case .landscape: + size = .init(width: 1194, height: 834) + case .portrait: + size = .init(width: 834, height: 1194) + } + return .init(safeArea: .init(top: 24, left: 0, bottom: 20, right: 0), size: size, traits: .iPadPro11) + } public static let iPadPro12_9 = ViewImageConfig.iPadPro12_9(.landscape) @@ -350,6 +363,7 @@ extension UITraitCollection { public static let iPadMini = iPad public static let iPadPro10_5 = iPad + public static let iPadPro11 = iPad public static let iPadPro12_9 = iPad private static let iPad = UITraitCollection( diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/XCTAttachment.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/XCTAttachment.swift index 2358e33..312d8bc 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/XCTAttachment.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Common/XCTAttachment.swift @@ -2,7 +2,7 @@ import Foundation public struct XCTAttachment { - init(data: Data) {} - init(data: Data, uniformTypeIdentifier: String) {} + public init(data: Data) {} + public init(data: Data, uniformTypeIdentifier: String) {} } #endif diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Diffing.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Diffing.swift index 09ea426..663271a 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Diffing.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Diffing.swift @@ -4,13 +4,13 @@ import XCTest /// The ability to compare `Value`s and convert them to and from `Data`. public struct Diffing { /// Converts a value _to_ data. - public let toData: (Value) -> Data + public var toData: (Value) -> Data /// Produces a value _from_ data. - public let fromData: (Data) -> Value + public var fromData: (Data) -> Value /// Compares two values. If the values do not match, returns a failure message and artifacts describing the failure. - public let diff: (Value, Value) -> (String, [XCTAttachment])? + public var diff: (Value, Value) -> (String, [XCTAttachment])? /// Creates a new `Diffing` on `Value`. /// diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/SnapshotTestCase.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/SnapshotTestCase.swift index 0222707..ba93752 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/SnapshotTestCase.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/SnapshotTestCase.swift @@ -1,146 +1,4 @@ -#if os(Linux) import XCTest -/// An XCTest subclass that provides snaphot testing helpers. -open class SnapshotTestCase: XCTestCase { - /// Whether or not to record all new references. - open var record = false - - /// Enhances failure messages with a command line expression that can be copied and pasted into a terminal. - /// - /// diffTool = "ksdiff" - open var diffTool: String? = nil - - /// Asserts that a given value matches a reference on disk. - /// - /// - Parameters: - /// - value: A value to compare against a reference. - /// - snapshotting: A strategy for serializing, deserializing, and comparing values. - /// - name: An optional description of the snapshot. - /// - recording: Whether or not to record a new reference. - /// - timeout: The amount of time a snapshot must be generated in. - /// - file: The file in which failure occurred. Defaults to the file name of the test case in which this function was called. - /// - testName: The name of the test in which failure occurred. Defaults to the function name of the test case in which this function was called. - /// - line: The line number on which failure occurred. Defaults to the line number on which this function was called. - public func assertSnapshot( - matching value: Value, - as snapshotting: Snapshotting, - named name: String? = nil, - record recording: Bool = false, - timeout: TimeInterval = 5, - file: StaticString = #file, - testName: String = #function, - line: UInt = #line - ) { - - let recording = recording || self.record - - do { - let fileUrl = URL(fileURLWithPath: "\(file)") - let fileName = fileUrl.deletingPathExtension().lastPathComponent - let directoryUrl = fileUrl.deletingLastPathComponent() - let snapshotDirectoryUrl: URL = directoryUrl - .appendingPathComponent("__Snapshots__") - .appendingPathComponent(fileName) - - let identifier: String - if let name = name { - identifier = sanitizePathComponent(name) - } else { - identifier = String(counter) - counter += 1 - } - - let testName = sanitizePathComponent(testName) - let snapshotFileUrl = snapshotDirectoryUrl - .appendingPathComponent("\(testName).\(identifier)") - .appendingPathExtension(snapshotting.pathExtension ?? "") - let fileManager = FileManager.default - try fileManager.createDirectory(at: snapshotDirectoryUrl, withIntermediateDirectories: true) - - let tookSnapshot = self.expectation(description: "Took snapshot") - var optionalDiffable: Format? - snapshotting.snapshot(value).run { b in - optionalDiffable = b - tookSnapshot.fulfill() - } - #if os(Linux) - self.waitForExpectations(timeout: timeout) - #else - self.wait(for: [tookSnapshot], timeout: timeout) - #endif - - guard let diffable = optionalDiffable else { - XCTFail("Couldn't snapshot value", file: file, line: line) - return - } - - guard !recording, fileManager.fileExists(atPath: snapshotFileUrl.path) else { - let diffMessage = (try? Data(contentsOf: snapshotFileUrl)) - .flatMap { data in snapshotting.diffing.diff(snapshotting.diffing.fromData(data), diffable) } - .map { diff, _ in diff.trimmingCharacters(in: .whitespacesAndNewlines) } - ?? "Recorded snapshot: …" - - try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) - let message = recording - ? """ - Record mode is on. \(diffMessage) - - open "\(snapshotFileUrl.path)" - - Turn record mode off and re-run "\(testName)" to test against the newly-recorded snapshot. - """ - : """ - No reference was found on disk. Automatically recorded snapshot: … - - open "\(snapshotFileUrl.path)" - - Re-run "\(testName)" to test against the newly-recorded snapshot. - """ - - XCTFail(message, file: file, line: line) - return - } - - let data = try Data(contentsOf: snapshotFileUrl) - let reference = snapshotting.diffing.fromData(data) - - guard let (failure, attachments) = snapshotting.diffing.diff(reference, diffable) else { - return - } - - let artifactsUrl = URL( - fileURLWithPath: ProcessInfo.processInfo.environment["SNAPSHOT_ARTIFACTS"] ?? NSTemporaryDirectory() - ) - let artifactsSubUrl = artifactsUrl.appendingPathComponent(fileName) - try fileManager.createDirectory(at: artifactsSubUrl, withIntermediateDirectories: true) - let failedSnapshotFileUrl = artifactsSubUrl.appendingPathComponent(snapshotFileUrl.lastPathComponent) - try snapshotting.diffing.toData(diffable).write(to: failedSnapshotFileUrl) - - if !attachments.isEmpty { - #if !os(Linux) - XCTContext.runActivity(named: "Attached Failure Diff") { activity in - attachments.forEach { - activity.add($0) - } - } - #endif - } - - let diffMessage = self.diffTool - .map { "\($0) \"\(snapshotFileUrl.path)\" \"\(failedSnapshotFileUrl.path)\"" } - ?? "@\(minus)\n\"\(snapshotFileUrl.path)\"\n@\(plus)\n\"\(failedSnapshotFileUrl.path)\"" - let message = """ - \(failure.trimmingCharacters(in: .whitespacesAndNewlines)) - - \(diffMessage) - """ - XCTFail(message, file: file, line: line) - } catch { - XCTFail(error.localizedDescription, file: file, line: line) - } - } - - private var counter = 1 -} -#endif +@available(swift, obsoleted: 5.0, renamed: "XCTestCase", message: "Please use XCTestCase instead") +public typealias SnapshotTestCase = XCTestCase diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting.swift index db0844b..3d835a3 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting.swift @@ -7,10 +7,10 @@ public struct Snapshotting { public var pathExtension: String? /// How the snapshot format is diffed and converted to and from data. - public let diffing: Diffing + public var diffing: Diffing /// How a value is transformed into a diffable snapshot format. - public let snapshot: (Value) -> Async + public var snapshot: (Value) -> Async /// Creates a snapshot strategy. /// @@ -46,38 +46,54 @@ public struct Snapshotting { } } - /// Transforms a strategy on `Value`s into a strategy on `A`s through a function `(A) -> Async`. + /// Transforms a strategy on `Value`s into a strategy on `NewValue`s through a function `(NewValue) -> Value`. + /// + /// This is the most important operation for transforming existing strategies into new strategies. It allows you to transform a `Snapshotting` into a `Snapshotting` by pulling it back along a function `(NewValue) -> Value`. Notice that the function must go in in the direction `(NewValue) -> Value` even though we are transforming in the other direction `(Snapshotting) -> Snapshotting`. + /// + /// A simple example of this is to `pullback` the snapshot strategy on `UIView`s to work on `UIViewController`s: + /// + /// let strategy = Snapshotting.image.pullback { (vc: UIViewController) in + /// return vc.view + /// } + /// + /// Here we took the strategy that snapshots `UIView`s as `UIImage`s and pulled it back to work on `UIViewController`s by using the function `(UIViewController) -> UIView` that simply plucks the view out of the controller. + /// + /// Nearly every snapshot strategy provided in this library is a pullback of some base strategy, which shows just how important this operation is. /// /// - Parameters: - /// - transform: A transform function from `A` into `Async`. + /// - transform: A transform function from `NewValue` into `Value`. /// - otherValue: A value to be transformed. - public func asyncPullback(_ transform: @escaping (_ otherValue: A) -> Async) -> Snapshotting { - return Snapshotting( - pathExtension: self.pathExtension, - diffing: self.diffing - ) { a0 in - return .init { callback in - transform(a0).run { a in - self.snapshot(a).run { b in - callback(b) - } - } - } - } + public func pullback(_ transform: @escaping (_ otherValue: NewValue) -> Value) -> Snapshotting { + return self.asyncPullback { newValue in Async(value: transform(newValue)) } } - /// Transforms a strategy on `Value`s into a strategy on `A`s through a function `(A) -> Value`. + /// Transforms a strategy on `Value`s into a strategy on `NewValue`s through a function `(NewValue) -> Async`. + /// + /// See the documention of `pullback` for a full description of how pullbacks works. This operation differs from `pullback` in that it allows you to use a transformation `(NewValue) -> Async`, which is necessary when your transformation needs to perform some asynchronous work. /// /// - Parameters: - /// - transform: A transform function from `A` into `Value`. + /// - transform: A transform function from `NewValue` into `Async`. /// - otherValue: A value to be transformed. - public func pullback(_ transform: @escaping (_ otherValue: A) -> Value) -> Snapshotting { - return self.asyncPullback { Async(value: transform($0)) } + public func asyncPullback(_ transform: @escaping (_ otherValue: NewValue) -> Async) + -> Snapshotting { + + return Snapshotting( + pathExtension: self.pathExtension, + diffing: self.diffing + ) { newValue in + return .init { callback in + transform(newValue).run { value in + self.snapshot(value).run { snapshot in + callback(snapshot) + } + } + } + } } } /// A snapshot strategy where the type being snapshot is also a diffable type. -public typealias SimplySnapshotting = Snapshotting +public typealias SimplySnapshotting = Snapshotting extension Snapshotting where Value == Format { public init(pathExtension: String?, diffing: Diffing) { diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/Any.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/Any.swift index 6898fdf..2254190 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/Any.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/Any.swift @@ -55,7 +55,12 @@ private func snap(_ value: T, name: String? = nil, indent: Int = 0) -> String } private func sort(_ children: Mirror.Children) -> Mirror.Children { - return .init(children.sorted { snap($0) < snap($1) }) + return .init( + children + .map({ (child: $0, snap: snap($0)) }) + .sorted(by: { $0.snap < $1.snap }) + .map({ $0.child }) + ) } /// A type with a customized snapshot dump representation. diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/NSImage.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/NSImage.swift index d3bcd4d..9dd7a4e 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/NSImage.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/NSImage.swift @@ -2,6 +2,32 @@ import Cocoa import XCTest +extension Diffing where Value == NSImage { + /// A pixel-diffing strategy for NSImage's which requires a 100% match. + public static let image = Diffing.image(precision: 1) + + /// A pixel-diffing strategy for NSImage that allows customizing how precise the matching must be. + /// + /// - Parameter precision: A value between 0 and 1, where 1 means the images must match 100% of their pixels. + /// - Returns: A new diffing strategy. + public static func image(precision: Float) -> Diffing { + return .init( + toData: { NSImagePNGRepresentation($0)! }, + fromData: { NSImage(data: $0)! } + ) { old, new in + guard !compare(old, new, precision: precision) else { return nil } + let difference = SnapshotTesting.diff(old, new) + let message = new.size == old.size + ? "Newly-taken snapshot does not match reference." + : "Newly-taken snapshot@\(new.size) does not match reference@\(old.size)." + return ( + message, + [XCTAttachment(image: old), XCTAttachment(image: new), XCTAttachment(image: difference)] + ) + } + } +} + extension Snapshotting where Value == NSImage, Format == NSImage { /// A snapshot strategy for comparing images based on pixel equality. public static var image: Snapshotting { @@ -14,20 +40,7 @@ extension Snapshotting where Value == NSImage, Format == NSImage { public static func image(precision: Float) -> Snapshotting { return .init( pathExtension: "png", - diffing: .init( - toData: { NSImagePNGRepresentation($0)! }, - fromData: { NSImage(data: $0)! } - ) { old, new in - guard !compare(old, new, precision: precision) else { return nil } - let difference = diff(old, new) - let message = new.size == old.size - ? "Expected snapshot to match reference" - : "Expected snapshot@\(new.size) to match reference@\(old.size)" - return ( - message, - [XCTAttachment(image: old), XCTAttachment(image: new), XCTAttachment(image: difference)] - ) - } + diffing: .image(precision: precision) ) } } diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/String.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/String.swift index 07eddbd..3de02fe 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/String.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/String.swift @@ -21,6 +21,6 @@ extension Diffing where Value == String { .flatMap { [$0.patchMark] + $0.lines } .joined(separator: "\n") let attachment = XCTAttachment(data: Data(failure.utf8), uniformTypeIdentifier: "public.patch-file") - return ("Diff: …\n\n\(failure)", [attachment]) + return (failure, [attachment]) } } diff --git a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/UIImage.swift b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/UIImage.swift index 2d5c4e7..178fce1 100644 --- a/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/UIImage.swift +++ b/Constrictor/Pods/SnapshotTesting/Sources/SnapshotTesting/Snapshotting/UIImage.swift @@ -2,6 +2,38 @@ import UIKit import XCTest +extension Diffing where Value == UIImage { + /// A pixel-diffing strategy for UIImage's which requires a 100% match. + public static let image = Diffing.image(precision: 1) + + /// A pixel-diffing strategy for UIImage that allows customizing how precise the matching must be. + /// + /// - Parameter precision: A value between 0 and 1, where 1 means the images must match 100% of their pixels. + /// - Returns: A new diffing strategy. + public static func image(precision: Float) -> Diffing { + return Diffing( + toData: { $0.pngData()! }, + fromData: { UIImage(data: $0, scale: UIScreen.main.scale)! } + ) { old, new in + guard !compare(old, new, precision: precision) else { return nil } + let difference = SnapshotTesting.diff(old, new) + let message = new.size == old.size + ? "Newly-taken snapshot does not match reference." + : "Newly-taken snapshot@\(new.size) does not match reference@\(old.size)." + let oldAttachment = XCTAttachment(image: old) + oldAttachment.name = "reference" + let newAttachment = XCTAttachment(image: new) + newAttachment.name = "failure" + let differenceAttachment = XCTAttachment(image: difference) + differenceAttachment.name = "difference" + return ( + message, + [oldAttachment, newAttachment, differenceAttachment] + ) + } + } +} + extension Snapshotting where Value == UIImage, Format == UIImage { /// A snapshot strategy for comparing images based on pixel equality. public static var image: Snapshotting { @@ -14,26 +46,7 @@ extension Snapshotting where Value == UIImage, Format == UIImage { public static func image(precision: Float) -> Snapshotting { return .init( pathExtension: "png", - diffing: .init( - toData: { $0.pngData()! }, - fromData: { UIImage(data: $0, scale: UIScreen.main.scale)! } - ) { old, new in - guard !compare(old, new, precision: precision) else { return nil } - let difference = diff(old, new) - let message = new.size == old.size - ? "Expected snapshot to match reference" - : "Expected snapshot@\(new.size) to match reference@\(old.size)" - let oldAttachment = XCTAttachment(image: old) - oldAttachment.name = "reference" - let newAttachment = XCTAttachment(image: new) - newAttachment.name = "failure" - let differenceAttachment = XCTAttachment(image: difference) - differenceAttachment.name = "difference" - return ( - message, - [oldAttachment, newAttachment, differenceAttachment] - ) - } + diffing: .image(precision: precision) ) } } diff --git a/Constrictor/Pods/Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-acknowledgements.markdown b/Constrictor/Pods/Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-acknowledgements.markdown index 4ca0b1c..339c3a6 100644 --- a/Constrictor/Pods/Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-acknowledgements.markdown +++ b/Constrictor/Pods/Target Support Files/Pods-ConstrictorTests/Pods-ConstrictorTests-acknowledgements.markdown @@ -5,7 +5,7 @@ This application makes use of the following third party libraries: MIT License -Copyright (c) 2017 Point-Free, Inc. +Copyright (c) 2019 Point-Free, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Constrictor/Pods/Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist b/Constrictor/Pods/Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist index 21a30b4..7b6b52a 100644 --- a/Constrictor/Pods/Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist +++ b/Constrictor/Pods/Target Support Files/SnapshotTesting/SnapshotTesting-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.0 + 1.4.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 0004efd..1e3739a 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ 203559FF20B371B900A82EB8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 203559FD20B371B900A82EB8 /* Main.storyboard */; }; 20355A0120B371BB00A82EB8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 20355A0020B371BB00A82EB8 /* Assets.xcassets */; }; 20355A0420B371BB00A82EB8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 20355A0220B371BB00A82EB8 /* LaunchScreen.storyboard */; }; - 8ECA734855E07CD56060EDE9 /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F9164658DAF9914261ECF13F /* libPods-Example.a */; }; + C136279F3D123FFA8C438574 /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FB4C602F309086099488F91 /* libPods-Example.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -23,9 +23,9 @@ 20355A0020B371BB00A82EB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 20355A0320B371BB00A82EB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 20355A0520B371BB00A82EB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 68C87651C3AC19C7DB6EDE86 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; - 810D2625B22C3D585D7157A4 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; - F9164658DAF9914261ECF13F /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3FB4C602F309086099488F91 /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9BB20C9EE746FFC3F3D36677 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; + ED981D51B570D96B856499F8 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -33,29 +33,20 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8ECA734855E07CD56060EDE9 /* libPods-Example.a in Frameworks */, + C136279F3D123FFA8C438574 /* libPods-Example.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1971680AD76A225740D46043 /* Pods */ = { - isa = PBXGroup; - children = ( - 68C87651C3AC19C7DB6EDE86 /* Pods-Example.debug.xcconfig */, - 810D2625B22C3D585D7157A4 /* Pods-Example.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; 203559ED20B371B900A82EB8 = { isa = PBXGroup; children = ( 203559F820B371B900A82EB8 /* Example */, 203559F720B371B900A82EB8 /* Products */, - 1971680AD76A225740D46043 /* Pods */, - 46412AEAB7B7DE7CAF1E120E /* Frameworks */, + 6C59D80B577E4C0FDFCA82E9 /* Pods */, + 3828149ACEFB3E5840ED021B /* Frameworks */, ); sourceTree = ""; }; @@ -80,14 +71,24 @@ path = Example; sourceTree = ""; }; - 46412AEAB7B7DE7CAF1E120E /* Frameworks */ = { + 3828149ACEFB3E5840ED021B /* Frameworks */ = { isa = PBXGroup; children = ( - F9164658DAF9914261ECF13F /* libPods-Example.a */, + 3FB4C602F309086099488F91 /* libPods-Example.a */, ); name = Frameworks; sourceTree = ""; }; + 6C59D80B577E4C0FDFCA82E9 /* Pods */ = { + isa = PBXGroup; + children = ( + ED981D51B570D96B856499F8 /* Pods-Example.debug.xcconfig */, + 9BB20C9EE746FFC3F3D36677 /* Pods-Example.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -95,7 +96,7 @@ isa = PBXNativeTarget; buildConfigurationList = 20355A0820B371BB00A82EB8 /* Build configuration list for PBXNativeTarget "Example" */; buildPhases = ( - E3BE9F3FF71AE0B9786F4AD0 /* [CP] Check Pods Manifest.lock */, + 7707462FA78ACE670FFE2F00 /* [CP] Check Pods Manifest.lock */, 203559F220B371B900A82EB8 /* Sources */, 203559F320B371B900A82EB8 /* Frameworks */, 203559F420B371B900A82EB8 /* Resources */, @@ -156,16 +157,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - E3BE9F3FF71AE0B9786F4AD0 /* [CP] Check Pods Manifest.lock */ = { + 7707462FA78ACE670FFE2F00 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt", ); @@ -324,7 +329,7 @@ }; 20355A0920B371BB00A82EB8 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 68C87651C3AC19C7DB6EDE86 /* Pods-Example.debug.xcconfig */; + baseConfigurationReference = ED981D51B570D96B856499F8 /* Pods-Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; @@ -336,14 +341,14 @@ ); PRODUCT_BUNDLE_IDENTIFIER = pedrommcarrasco.Example; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 20355A0A20B371BB00A82EB8 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 810D2625B22C3D585D7157A4 /* Pods-Example.release.xcconfig */; + baseConfigurationReference = 9BB20C9EE746FFC3F3D36677 /* Pods-Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; @@ -355,7 +360,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = pedrommcarrasco.Example; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift index 013879f..f2f983d 100644 --- a/Example/Example/AppDelegate.swift +++ b/Example/Example/AppDelegate.swift @@ -14,33 +14,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - } - diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index 0815dd0..7604f1f 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -25,7 +25,7 @@ class ViewController: UIViewController { // Constraints -> Same dimensions of redview's superview redView.constrictor - .edge(to: view) + .edge(to: view, with: .top(10) & .horizontal(20)) // ** Blue View ** // Boilerplate diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 2d77e1b..dc89351 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - Constrictor (5.0.1) + - Constrictor (6.0.0) DEPENDENCIES: - Constrictor (from `..`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: ".." SPEC CHECKSUMS: - Constrictor: 20d4193f6cd126076f9636eefc66d7f41e18c5ca + Constrictor: 01a8e28f39876bca706de6e14ca43fa614298eda PODFILE CHECKSUM: 378ecc6ae0c8cd6d7e4d84896a541255c3c32287