From f71181a0ae7bd9e9b317c01af9edf1c41a25a21e Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 10:53:06 +0100 Subject: [PATCH 01/15] =?UTF-8?q?Add=20`CALayer`=20extension=20to=20extrac?= =?UTF-8?q?t=20image=20from=20it=20=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Snap.xcodeproj/project.pbxproj | 12 ++++++++++++ .../Extension/CALayer/CALayer+Image.swift | 14 ++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 Snap/Core/Infrastructure/Extension/CALayer/CALayer+Image.swift diff --git a/Snap.xcodeproj/project.pbxproj b/Snap.xcodeproj/project.pbxproj index 5132345..ceae697 100644 --- a/Snap.xcodeproj/project.pbxproj +++ b/Snap.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 1C0FF4571FC823A5003B8B22 /* AddAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C0FF4561FC823A5003B8B22 /* AddAttachment.swift */; }; 1C0FF4591FC8294A003B8B22 /* UIImage+Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C0FF4581FC8294A003B8B22 /* UIImage+Diff.swift */; }; 1C7F066B1FC884110078CA7A /* Recordable+XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */; }; + 1C92A5061FC9736000E6C817 /* CALayer+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */; }; 1C92E5C31FC6E47300EF28C2 /* Snap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C92E5B91FC6E47300EF28C2 /* Snap.framework */; }; 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5C71FC6E47300EF28C2 /* SnapTests.swift */; }; 1C92E5CA1FC6E47300EF28C2 /* Snap.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C92E5BC1FC6E47300EF28C2 /* Snap.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -52,6 +53,7 @@ 1C0FF4561FC823A5003B8B22 /* AddAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAttachment.swift; sourceTree = ""; }; 1C0FF4581FC8294A003B8B22 /* UIImage+Diff.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Diff.swift"; sourceTree = ""; }; 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Recordable+XCTestCase.swift"; sourceTree = ""; }; + 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Image.swift"; sourceTree = ""; }; 1C92E5B91FC6E47300EF28C2 /* Snap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Snap.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1C92E5BC1FC6E47300EF28C2 /* Snap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Snap.h; sourceTree = ""; }; 1C92E5BD1FC6E47300EF28C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -99,6 +101,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1C92A5041FC9735500E6C817 /* CALayer */ = { + isa = PBXGroup; + children = ( + 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */, + ); + path = CALayer; + sourceTree = ""; + }; 1C92E5AF1FC6E47300EF28C2 = { isa = PBXGroup; children = ( @@ -168,6 +178,7 @@ 1C92E5DE1FC6E85B00EF28C2 /* Extension */ = { isa = PBXGroup; children = ( + 1C92A5041FC9735500E6C817 /* CALayer */, 1C92E6061FC7429D00EF28C2 /* UIImage */, 1C92E5DF1FC6E86500EF28C2 /* UIView */, ); @@ -455,6 +466,7 @@ 1C7F066B1FC884110078CA7A /* Recordable+XCTestCase.swift in Sources */, 1C0FF4571FC823A5003B8B22 /* AddAttachment.swift in Sources */, 1C92E5FD1FC70D5500EF28C2 /* Path.swift in Sources */, + 1C92A5061FC9736000E6C817 /* CALayer+Image.swift in Sources */, 1C92E5F41FC70B8A00EF28C2 /* SaveImageToDisk.swift in Sources */, 1C92E5F81FC70C3B00EF28C2 /* Environment.swift in Sources */, ); diff --git a/Snap/Core/Infrastructure/Extension/CALayer/CALayer+Image.swift b/Snap/Core/Infrastructure/Extension/CALayer/CALayer+Image.swift new file mode 100644 index 0000000..973f410 --- /dev/null +++ b/Snap/Core/Infrastructure/Extension/CALayer/CALayer+Image.swift @@ -0,0 +1,14 @@ +import UIKit + +extension CALayer { + /// Extract image from CALayer + func image() -> UIImage? { + defer { + UIGraphicsEndImageContext() + } + UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, contentsScale) + guard let context = UIGraphicsGetCurrentContext() else { return nil } + render(in: context) + return UIGraphicsGetImageFromCurrentImageContext() + } +} From e306f12ccbbcf870f829fb789956175d02ea2bf0 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:02:59 +0100 Subject: [PATCH 02/15] Add snapshot layer matcher (create layer view and use composition to match with the view matcher) --- Snap.xcodeproj/project.pbxproj | 4 +++ .../Matcher/SnapshotLayerMatcher.swift | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Snap/Core/Application/Matcher/SnapshotLayerMatcher.swift diff --git a/Snap.xcodeproj/project.pbxproj b/Snap.xcodeproj/project.pbxproj index ceae697..6b01b75 100644 --- a/Snap.xcodeproj/project.pbxproj +++ b/Snap.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 1C0FF4591FC8294A003B8B22 /* UIImage+Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C0FF4581FC8294A003B8B22 /* UIImage+Diff.swift */; }; 1C7F066B1FC884110078CA7A /* Recordable+XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */; }; 1C92A5061FC9736000E6C817 /* CALayer+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */; }; + 1C92A5091FC975E400E6C817 /* SnapshotLayerMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */; }; 1C92E5C31FC6E47300EF28C2 /* Snap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C92E5B91FC6E47300EF28C2 /* Snap.framework */; }; 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5C71FC6E47300EF28C2 /* SnapTests.swift */; }; 1C92E5CA1FC6E47300EF28C2 /* Snap.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C92E5BC1FC6E47300EF28C2 /* Snap.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -54,6 +55,7 @@ 1C0FF4581FC8294A003B8B22 /* UIImage+Diff.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Diff.swift"; sourceTree = ""; }; 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Recordable+XCTestCase.swift"; sourceTree = ""; }; 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Image.swift"; sourceTree = ""; }; + 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLayerMatcher.swift; sourceTree = ""; }; 1C92E5B91FC6E47300EF28C2 /* Snap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Snap.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1C92E5BC1FC6E47300EF28C2 /* Snap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Snap.h; sourceTree = ""; }; 1C92E5BD1FC6E47300EF28C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -218,6 +220,7 @@ children = ( 1C92E5E71FC6F28500EF28C2 /* Matcher.swift */, 1C92E5E91FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift */, + 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */, ); path = Matcher; sourceTree = ""; @@ -444,6 +447,7 @@ buildActionMask = 2147483647; files = ( 1C92E6031FC71DC400EF28C2 /* Reference.swift in Sources */, + 1C92A5091FC975E400E6C817 /* SnapshotLayerMatcher.swift in Sources */, 1C92E5E51FC6F25500EF28C2 /* Expectation.swift in Sources */, 1C0FF4551FC82234003B8B22 /* UIImage+Normalized.swift in Sources */, 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */, diff --git a/Snap/Core/Application/Matcher/SnapshotLayerMatcher.swift b/Snap/Core/Application/Matcher/SnapshotLayerMatcher.swift new file mode 100644 index 0000000..3507319 --- /dev/null +++ b/Snap/Core/Application/Matcher/SnapshotLayerMatcher.swift @@ -0,0 +1,35 @@ +import UIKit + +protocol SnapshotLayerMatcherProvider { + func makeMatcher(with layer: CALayer, isRecording: Bool, tesTarget: TestTarget) -> Matcher +} + +struct SnapshotLayerMatcher: Matcher { + + private let layer: CALayer + private let isRecording: Bool + private let testTarget: TestTarget + private let viewMatcherProvider: SnapshotViewMatcherProvider + + init(layer: CALayer, + isRecording: Bool, + testTarget: TestTarget, + viewMatcherProvider: SnapshotViewMatcherProvider) + { + self.layer = layer + self.isRecording = isRecording + self.testTarget = testTarget + self.viewMatcherProvider = viewMatcherProvider + } + + func toMatchSnapshot() { + let view = UIView(frame: layer.frame) + view.layer.insertSublayer(layer, at: 0) + + viewMatcherProvider.makeMatcher( + with: view, + isRecording: isRecording, + tesTarget: testTarget + ).toMatchSnapshot() + } +} From 2231eb00439783a2909f3504d117b4c4b98d48f4 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:03:08 +0100 Subject: [PATCH 03/15] Wire dependencies --- .../Infrastructure/Assembly/Assembly+Matchers.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Snap/Core/Infrastructure/Assembly/Assembly+Matchers.swift b/Snap/Core/Infrastructure/Assembly/Assembly+Matchers.swift index 481e7c3..d6d6efc 100644 --- a/Snap/Core/Infrastructure/Assembly/Assembly+Matchers.swift +++ b/Snap/Core/Infrastructure/Assembly/Assembly+Matchers.swift @@ -13,3 +13,16 @@ extension Assembly: SnapshotViewMatcherProvider { ) } } + +// MARK: - SnapshotLayerMatcherProvider + +extension Assembly: SnapshotLayerMatcherProvider { + func makeMatcher(with layer: CALayer, isRecording: Bool, tesTarget: TestTarget) -> Matcher { + return SnapshotLayerMatcher( + layer: layer, + isRecording: isRecording, + testTarget: tesTarget, + viewMatcherProvider: self + ) + } +} From 300e15f38edf2b38bf1e0336082bd864db14cbf1 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:10:24 +0100 Subject: [PATCH 04/15] Fix typo on `Expectation` --- ...iewExpecation.swift => SnapshotLayerExpectation.swift} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename Snap/Core/Application/Expectation/{SnapshotViewExpecation.swift => SnapshotLayerExpectation.swift} (52%) diff --git a/Snap/Core/Application/Expectation/SnapshotViewExpecation.swift b/Snap/Core/Application/Expectation/SnapshotLayerExpectation.swift similarity index 52% rename from Snap/Core/Application/Expectation/SnapshotViewExpecation.swift rename to Snap/Core/Application/Expectation/SnapshotLayerExpectation.swift index ff0b681..764090d 100644 --- a/Snap/Core/Application/Expectation/SnapshotViewExpecation.swift +++ b/Snap/Core/Application/Expectation/SnapshotLayerExpectation.swift @@ -1,16 +1,16 @@ import UIKit import XCTest -// MARK: - XCTestCase + Expectation +// MARK: - XCTestCase + CALayer Expectation -extension XCTestCase: Expectation { - public func expect(_ view: UIView, function: String = #function, file: String = #file ) -> Matcher { +extension XCTestCase { + public func expect(_ layer: CALayer, function: String = #function, file: String = #file ) -> Matcher { let testTarget = TestTarget( function: function, file: file ) return resolver.makeMatcher( - with: view, + with: layer, isRecording: isRecording, tesTarget: testTarget ) From 8e7490f3311d1f86cdc4bd46df58a9d84351dfed Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:12:05 +0100 Subject: [PATCH 05/15] - Remove unused protocol for `Expectation` as was doing nothing - Add `XCTestCase` extension to verify layers --- Snap.xcodeproj/project.pbxproj | 16 ++++++++-------- .../Application/Expectation/Expectation.swift | 1 - .../Expectation/SnapshotViewExpectation.swift | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) delete mode 100644 Snap/Core/Application/Expectation/Expectation.swift create mode 100644 Snap/Core/Application/Expectation/SnapshotViewExpectation.swift diff --git a/Snap.xcodeproj/project.pbxproj b/Snap.xcodeproj/project.pbxproj index 6b01b75..ac87589 100644 --- a/Snap.xcodeproj/project.pbxproj +++ b/Snap.xcodeproj/project.pbxproj @@ -14,14 +14,14 @@ 1C7F066B1FC884110078CA7A /* Recordable+XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */; }; 1C92A5061FC9736000E6C817 /* CALayer+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */; }; 1C92A5091FC975E400E6C817 /* SnapshotLayerMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */; }; + 1C92A50B1FC9776D00E6C817 /* SnapshotLayerExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A50A1FC9776D00E6C817 /* SnapshotLayerExpectation.swift */; }; 1C92E5C31FC6E47300EF28C2 /* Snap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C92E5B91FC6E47300EF28C2 /* Snap.framework */; }; 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5C71FC6E47300EF28C2 /* SnapTests.swift */; }; 1C92E5CA1FC6E47300EF28C2 /* Snap.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C92E5BC1FC6E47300EF28C2 /* Snap.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1C92E5E11FC6E87000EF28C2 /* UIView+Render.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E01FC6E87000EF28C2 /* UIView+Render.swift */; }; - 1C92E5E51FC6F25500EF28C2 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E41FC6F25500EF28C2 /* Expectation.swift */; }; 1C92E5E81FC6F28500EF28C2 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E71FC6F28500EF28C2 /* Matcher.swift */; }; 1C92E5EA1FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E91FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift */; }; - 1C92E5EC1FC6F2E300EF28C2 /* SnapshotViewExpecation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpecation.swift */; }; + 1C92E5EC1FC6F2E300EF28C2 /* SnapshotViewExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpectation.swift */; }; 1C92E5EF1FC6F99100EF28C2 /* Recordable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5EE1FC6F99100EF28C2 /* Recordable.swift */; }; 1C92E5F41FC70B8A00EF28C2 /* SaveImageToDisk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5F31FC70B8A00EF28C2 /* SaveImageToDisk.swift */; }; 1C92E5F81FC70C3B00EF28C2 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5F71FC70C3B00EF28C2 /* Environment.swift */; }; @@ -56,6 +56,7 @@ 1C7F06691FC8840B0078CA7A /* Recordable+XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Recordable+XCTestCase.swift"; sourceTree = ""; }; 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Image.swift"; sourceTree = ""; }; 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLayerMatcher.swift; sourceTree = ""; }; + 1C92A50A1FC9776D00E6C817 /* SnapshotLayerExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLayerExpectation.swift; sourceTree = ""; }; 1C92E5B91FC6E47300EF28C2 /* Snap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Snap.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1C92E5BC1FC6E47300EF28C2 /* Snap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Snap.h; sourceTree = ""; }; 1C92E5BD1FC6E47300EF28C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -64,10 +65,9 @@ 1C92E5C91FC6E47300EF28C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1C92E5D71FC6E52100EF28C2 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 1C92E5E01FC6E87000EF28C2 /* UIView+Render.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Render.swift"; sourceTree = ""; }; - 1C92E5E41FC6F25500EF28C2 /* Expectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Expectation.swift; sourceTree = ""; }; 1C92E5E71FC6F28500EF28C2 /* Matcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = ""; }; 1C92E5E91FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotViewMatcher.swift; sourceTree = ""; }; - 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpecation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotViewExpecation.swift; sourceTree = ""; }; + 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotViewExpectation.swift; sourceTree = ""; }; 1C92E5EE1FC6F99100EF28C2 /* Recordable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recordable.swift; sourceTree = ""; }; 1C92E5F31FC70B8A00EF28C2 /* SaveImageToDisk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveImageToDisk.swift; sourceTree = ""; }; 1C92E5F71FC70C3B00EF28C2 /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; @@ -209,8 +209,8 @@ 1C92E5E31FC6F24B00EF28C2 /* Expectation */ = { isa = PBXGroup; children = ( - 1C92E5E41FC6F25500EF28C2 /* Expectation.swift */, - 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpecation.swift */, + 1C92E5EB1FC6F2E300EF28C2 /* SnapshotViewExpectation.swift */, + 1C92A50A1FC9776D00E6C817 /* SnapshotLayerExpectation.swift */, ); path = Expectation; sourceTree = ""; @@ -447,8 +447,8 @@ buildActionMask = 2147483647; files = ( 1C92E6031FC71DC400EF28C2 /* Reference.swift in Sources */, + 1C92A50B1FC9776D00E6C817 /* SnapshotLayerExpectation.swift in Sources */, 1C92A5091FC975E400E6C817 /* SnapshotLayerMatcher.swift in Sources */, - 1C92E5E51FC6F25500EF28C2 /* Expectation.swift in Sources */, 1C0FF4551FC82234003B8B22 /* UIImage+Normalized.swift in Sources */, 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */, 1C0FF4531FC82229003B8B22 /* UIImage+Context.swift in Sources */, @@ -463,7 +463,7 @@ 1C0FF4591FC8294A003B8B22 /* UIImage+Diff.swift in Sources */, 1C92E5EF1FC6F99100EF28C2 /* Recordable.swift in Sources */, 1C92E5FA1FC70CAD00EF28C2 /* ApplicationEnvironment.swift in Sources */, - 1C92E5EC1FC6F2E300EF28C2 /* SnapshotViewExpecation.swift in Sources */, + 1C92E5EC1FC6F2E300EF28C2 /* SnapshotViewExpectation.swift in Sources */, 1CD1970C1FC839A200263A55 /* Assembly+Actions.swift in Sources */, 1C92E60A1FC7825F00EF28C2 /* ExtractViewImage.swift in Sources */, 1C92E6011FC714D700EF28C2 /* TestTarget.swift in Sources */, diff --git a/Snap/Core/Application/Expectation/Expectation.swift b/Snap/Core/Application/Expectation/Expectation.swift deleted file mode 100644 index f6ae435..0000000 --- a/Snap/Core/Application/Expectation/Expectation.swift +++ /dev/null @@ -1 +0,0 @@ -public protocol Expectation {} diff --git a/Snap/Core/Application/Expectation/SnapshotViewExpectation.swift b/Snap/Core/Application/Expectation/SnapshotViewExpectation.swift new file mode 100644 index 0000000..113d3d5 --- /dev/null +++ b/Snap/Core/Application/Expectation/SnapshotViewExpectation.swift @@ -0,0 +1,18 @@ +import UIKit +import XCTest + +// MARK: - XCTestCase + View Expectation + +extension XCTestCase { + public func expect(_ view: UIView, function: String = #function, file: String = #file ) -> Matcher { + let testTarget = TestTarget( + function: function, + file: file + ) + return resolver.makeMatcher( + with: view, + isRecording: isRecording, + tesTarget: testTarget + ) + } +} From 1501d80936b7ad1118c2b2996d05f8eadbea4fab Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:12:22 +0100 Subject: [PATCH 06/15] Remove unused assets --- ...ference_test_box_with_background_color@2x.png | Bin 1761 -> 0 bytes ...e_test_box_with_text_aligned_to_center@2x.png | Bin 4133 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 SnapTests/SnapTests.SnapTests/reference_test_box_with_background_color@2x.png delete mode 100644 SnapTests/SnapTests.SnapTests/reference_test_box_with_text_aligned_to_center@2x.png diff --git a/SnapTests/SnapTests.SnapTests/reference_test_box_with_background_color@2x.png b/SnapTests/SnapTests.SnapTests/reference_test_box_with_background_color@2x.png deleted file mode 100644 index 77486834ce116a187d769a25e81ae1e4a2a3b7a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1761 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 From 5fc16b443f0013a9af74fb92e93db61263ea8277 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:12:39 +0100 Subject: [PATCH 07/15] Add new test case for checking gradient layers --- ...reference_test_box_with_gradient_layer@2x.png | Bin 0 -> 6801 bytes SnapTests/SnapTests.swift | 14 ++++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 SnapTests/Snap/SnapTests/reference_test_box_with_gradient_layer@2x.png diff --git a/SnapTests/Snap/SnapTests/reference_test_box_with_gradient_layer@2x.png b/SnapTests/Snap/SnapTests/reference_test_box_with_gradient_layer@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3c7a5a50432370605ed3ae20f26659af706e6b GIT binary patch literal 6801 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 O&Dz|-?74||?EeA@juAuv literal 0 HcmV?d00001 diff --git a/SnapTests/SnapTests.swift b/SnapTests/SnapTests.swift index cee5325..069db62 100644 --- a/SnapTests/SnapTests.swift +++ b/SnapTests/SnapTests.swift @@ -21,4 +21,18 @@ class SnapTests: XCTestCase { expect(view).toMatchSnapshot() } + + func test_box_with_gradient_layer() { + let layer = CAGradientLayer() + layer.frame = CGRect(x: 0, y: 0, width: 100, height: 100) + layer.colors = [ + UIColor.red.cgColor, + UIColor.white.cgColor + ] + layer.locations = [0.0, 1.0] + layer.startPoint = CGPoint(x: 0.0, y: 1.0) + layer.endPoint = CGPoint(x: 0.0, y: 1.0) + + expect(layer).toMatchSnapshot() + } } From e5c03af2e9ed90f7bf25f92285985bb3b3c77042 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 11:20:55 +0100 Subject: [PATCH 08/15] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf94346..3671cd0 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,12 @@ This is ok, it just means that our reference images were saved, we can inspect t ### ☑ TODO: * [ ] Add tests for project -* [ ] Add `CALayer` matchers * [ ] Make device agnostic screenshots ### 📝 Notes +> As today, you can make assertions on `UIView` and `CALayer` classes. + This project is highly inspired on `Facebook` [FBSnapshotTestCase](https://github.com/facebookarchive/ios-snapshot-test-case/) library, it seems that they had archived the library so I started this one to continue envolving the project and continue with mobile `snapshot-testing` ### 😬 Contributions From b62ee6c6baef27c3265825065dc7826b509ba1de Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:12:33 +0100 Subject: [PATCH 09/15] Add `XCTestCase` extension that expose the view/layer verifications to Objc-C world --- .../Interoperability/Interoperability.swift | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Snap/Core/Infrastructure/Interoperability/Interoperability.swift diff --git a/Snap/Core/Infrastructure/Interoperability/Interoperability.swift b/Snap/Core/Infrastructure/Interoperability/Interoperability.swift new file mode 100644 index 0000000..1468273 --- /dev/null +++ b/Snap/Core/Infrastructure/Interoperability/Interoperability.swift @@ -0,0 +1,30 @@ +import UIKit +import XCTest + +public extension XCTestCase { + @objc + public func verify(view: UIView, function: String = #function, file: String = #file) { + let testTarget = TestTarget( + function: function, + file: file + ) + return resolver.makeMatcher( + with: view, + isRecording: isRecording, + tesTarget: testTarget + ).toMatchSnapshot() + } + + @objc + public func verify(layer: CALayer, function: String = #function, file: String = #file) { + let testTarget = TestTarget( + function: function, + file: file + ) + return resolver.makeMatcher( + with: layer, + isRecording: isRecording, + tesTarget: testTarget + ).toMatchSnapshot() + } +} From 5bee0cea13b1b1aa140a314d02e6dfd4f162ebc6 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:13:45 +0100 Subject: [PATCH 10/15] =?UTF-8?q?Add=20interoperability=20file=20so=20we?= =?UTF-8?q?=20can=20get=20the=20macros=20defined=20to=20assert=20views/lay?= =?UTF-8?q?ers=20(Oh=20lord=20I=20was=20missing=20all=20this=20macro-ish?= =?UTF-8?q?=20from=20objc=20=F0=9F=98=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Snap.xcodeproj/project.pbxproj | 24 +++++++++++++++---- .../Infrastructure/Interoperability/Snap.h | 13 ++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 Snap/Core/Infrastructure/Interoperability/Snap.h diff --git a/Snap.xcodeproj/project.pbxproj b/Snap.xcodeproj/project.pbxproj index ac87589..89594a2 100644 --- a/Snap.xcodeproj/project.pbxproj +++ b/Snap.xcodeproj/project.pbxproj @@ -15,9 +15,9 @@ 1C92A5061FC9736000E6C817 /* CALayer+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */; }; 1C92A5091FC975E400E6C817 /* SnapshotLayerMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */; }; 1C92A50B1FC9776D00E6C817 /* SnapshotLayerExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A50A1FC9776D00E6C817 /* SnapshotLayerExpectation.swift */; }; + 1C92A5141FC9808100E6C817 /* Interoperability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92A5131FC9808100E6C817 /* Interoperability.swift */; }; 1C92E5C31FC6E47300EF28C2 /* Snap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C92E5B91FC6E47300EF28C2 /* Snap.framework */; }; 1C92E5C81FC6E47300EF28C2 /* SnapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5C71FC6E47300EF28C2 /* SnapTests.swift */; }; - 1C92E5CA1FC6E47300EF28C2 /* Snap.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C92E5BC1FC6E47300EF28C2 /* Snap.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1C92E5E11FC6E87000EF28C2 /* UIView+Render.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E01FC6E87000EF28C2 /* UIView+Render.swift */; }; 1C92E5E81FC6F28500EF28C2 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E71FC6F28500EF28C2 /* Matcher.swift */; }; 1C92E5EA1FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C92E5E91FC6F2AC00EF28C2 /* SnapshotViewMatcher.swift */; }; @@ -57,8 +57,9 @@ 1C92A5051FC9736000E6C817 /* CALayer+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Image.swift"; sourceTree = ""; }; 1C92A5071FC9759E00E6C817 /* SnapshotLayerMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLayerMatcher.swift; sourceTree = ""; }; 1C92A50A1FC9776D00E6C817 /* SnapshotLayerExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLayerExpectation.swift; sourceTree = ""; }; + 1C92A5131FC9808100E6C817 /* Interoperability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interoperability.swift; sourceTree = ""; }; + 1C92A5251FC998E200E6C817 /* Snap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Snap.h; sourceTree = ""; }; 1C92E5B91FC6E47300EF28C2 /* Snap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Snap.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1C92E5BC1FC6E47300EF28C2 /* Snap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Snap.h; sourceTree = ""; }; 1C92E5BD1FC6E47300EF28C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1C92E5C21FC6E47300EF28C2 /* SnapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnapTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1C92E5C71FC6E47300EF28C2 /* SnapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapTests.swift; sourceTree = ""; }; @@ -111,6 +112,15 @@ path = CALayer; sourceTree = ""; }; + 1C92A5121FC9808100E6C817 /* Interoperability */ = { + isa = PBXGroup; + children = ( + 1C92A5131FC9808100E6C817 /* Interoperability.swift */, + 1C92A5251FC998E200E6C817 /* Snap.h */, + ); + path = Interoperability; + sourceTree = ""; + }; 1C92E5AF1FC6E47300EF28C2 = { isa = PBXGroup; children = ( @@ -133,7 +143,6 @@ 1C92E5BB1FC6E47300EF28C2 /* Snap */ = { isa = PBXGroup; children = ( - 1C92E5BC1FC6E47300EF28C2 /* Snap.h */, 1C92E5BD1FC6E47300EF28C2 /* Info.plist */, 1C92E5DC1FC6E66900EF28C2 /* Core */, ); @@ -170,6 +179,7 @@ 1C92E5DD1FC6E85300EF28C2 /* Infrastructure */ = { isa = PBXGroup; children = ( + 1C92A5121FC9808100E6C817 /* Interoperability */, 1CD197081FC8393100263A55 /* Assembly */, 1C92E5DE1FC6E85B00EF28C2 /* Extension */, 1C92E5F51FC70C2800EF28C2 /* Utils */, @@ -317,7 +327,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 1C92E5CA1FC6E47300EF28C2 /* Snap.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -378,6 +387,7 @@ }; 1C92E5C11FC6E47300EF28C2 = { CreatedOnToolsVersion = 9.1; + LastSwiftMigration = 0910; ProvisioningStyle = Automatic; }; }; @@ -457,6 +467,7 @@ 1CD197121FC839C400263A55 /* Assembly+Matchers.swift in Sources */, 1C92E5E81FC6F28500EF28C2 /* Matcher.swift in Sources */, 1C92E5E11FC6E87000EF28C2 /* UIView+Render.swift in Sources */, + 1C92A5141FC9808100E6C817 /* Interoperability.swift in Sources */, 1C92E6051FC736FF00EF28C2 /* CompareImages.swift in Sources */, 1C92E6081FC742AA00EF28C2 /* UIImage+Compare.swift in Sources */, 1CD1970A1FC8397E00263A55 /* Assembly.swift in Sources */, @@ -648,12 +659,15 @@ 1C92E5D11FC6E47300EF28C2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 3ZGLM2XX3U; INFOPLIST_FILE = SnapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = in.skydev.SnapTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -662,12 +676,14 @@ 1C92E5D21FC6E47300EF28C2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 3ZGLM2XX3U; INFOPLIST_FILE = SnapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = in.skydev.SnapTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/Snap/Core/Infrastructure/Interoperability/Snap.h b/Snap/Core/Infrastructure/Interoperability/Snap.h new file mode 100644 index 0000000..d1d0c31 --- /dev/null +++ b/Snap/Core/Infrastructure/Interoperability/Snap.h @@ -0,0 +1,13 @@ +#import "Snap_Swift-Swift.h" + +#define verifyView(view) \ +if (![view isKindOfClass: [UIView class]]) { \ +@throw[NSException exceptionWithName: @"Invalid view" reason: [NSString stringWithFormat: @"View is invalid, you must provider a UIView subclass instead of %@", [view class]] userInfo: nil]; \ +}\ +[self verifyWithView:view function:NSStringFromSelector(_cmd) file:[NSString stringWithFormat:@"%s", __FILE__]]; + +#define verifyLayer(layer) \ +if (![layer isKindOfClass: [CALayer class]]) { \ +@throw[NSException exceptionWithName: @"Invalid layer" reason: [NSString stringWithFormat: @"Layer is invalid, you must provider a CALayer subclass instead of %@", [view class]] userInfo: nil]; \ +}\ +[self verifyWithLayer:layer function:NSStringFromSelector(_cmd) file:[NSString stringWithFormat:@"%s", __FILE__]]; From abf061bc6eff28db4c7919aeb76ca2d3f756efc9 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:14:16 +0100 Subject: [PATCH 11/15] Make target tests to be private so there won't be seen by the Objc side --- SnapTests/SnapTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnapTests/SnapTests.swift b/SnapTests/SnapTests.swift index 069db62..ac90536 100644 --- a/SnapTests/SnapTests.swift +++ b/SnapTests/SnapTests.swift @@ -1,7 +1,7 @@ import XCTest import UIKit -class SnapTests: XCTestCase { +private final class SnapTests: XCTestCase { func test_box_with_background_color() { let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) From e5cb5ac1d732a6d5f6bf4ae25e9c3ef1b98174bc Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:14:45 +0100 Subject: [PATCH 12/15] Update podspec to expose the objc headers --- Snap.swift.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snap.swift.podspec b/Snap.swift.podspec index 0b1321d..e8e1b01 100644 --- a/Snap.swift.podspec +++ b/Snap.swift.podspec @@ -15,6 +15,6 @@ Pod::Spec.new do |s| s.ios.deployment_target = '9.0' - s.source_files = 'Snap/Core/**/*' + s.source_files = 'Snap/Core/**/*', 'Snap/Core/Infrastructure/Interoperability/*.h' s.frameworks = 'UIKit', 'CoreGraphics', 'XCTest' end From 06cab66904e2a6c0a1cde594fe8730830f238460 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:14:59 +0100 Subject: [PATCH 13/15] Update readme to add objc support --- README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3671cd0..b12f03a 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ * iOS 9.0+ * Xcode 9.0+ +* Swift / Objective-C ### 🚀 Getting started @@ -46,6 +47,8 @@ pod 'Snap.swift' 1) We first need to record our reference images, in order to do so we have to first go into our test class and set the `isRecording` variable to be `true` so the library knows that we are in record mode and can extract the `reference images` +> Swift + ```swift import XCTest import Snap_swift @@ -65,10 +68,37 @@ class SnapTests: XCTestCase { } ``` +> Objective-c +```objc +@import XCTest; +#import + +@interface SnapTests : XCTestCase +@end + +@implementation SnapTests + +- (void)setUp { + [super setUp]; + self.isRecording = YES; +} + +- (void)test_box_with_text_aligned_to_center { + + UIView *view = [BoxWithTextAlignedToCenterView new]; + + verifyView(view); +} + +@end + +``` + + After executing out test suite if everything was ok we should see that all of our tests failed with a warning similar to ```bash -⚠️ Test ran in record mode, reference image has been saved to /$SNAP_REFERENCE_IMAGE_PATH/testcase.png, now remove `isRecording` in order to perform the snapshot comparison. +⚠️ Test ran in record mode, reference image has been saved to $SNAP_REFERENCE_IMAGE_PATH/testcase.png, now remove `isRecording` in order to perform the snapshot comparison. ``` From 9474081d0d44c939c9d2facfc0a5b3c88ea4c604 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:20:49 +0100 Subject: [PATCH 14/15] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b12f03a..25370d6 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,9 @@ class SnapTests: XCTestCase { } func test_box_with_text_aligned_to_center() { - let view = BoxWithTextAlignedToCenterView() - - expect(view).toMatchSnapshot() + let view = BoxWithTextAlignedToCenterView() + + expect(view).toMatchSnapshot() } } ``` From 4cded759e733c6dd6842d569770cb90430f7f8d2 Mon Sep 17 00:00:00 2001 From: Oscar Antonio Duran Grillo Date: Sat, 25 Nov 2017 14:46:47 +0100 Subject: [PATCH 15/15] Update version number --- Snap.swift.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snap.swift.podspec b/Snap.swift.podspec index e8e1b01..05d3bb1 100644 --- a/Snap.swift.podspec +++ b/Snap.swift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Snap.swift' - s.version = '0.1.0' + s.version = '0.2.0' s.summary = 'Snapshot testing in a snap' s.description = <<-DESC