Release 0.1.0
This commit is contained in:
parent
fae05a1709
commit
c8bd9b7435
@ -9,4 +9,6 @@ target 'TabBarPicker_Tests', :exclusive => true do
|
|||||||
pod "TabBarPicker", :path => "../"
|
pod "TabBarPicker", :path => "../"
|
||||||
|
|
||||||
pod 'FBSnapshotTestCase'
|
pod 'FBSnapshotTestCase'
|
||||||
|
pod 'PureLayout'
|
||||||
|
pod 'pop', '~> 1.0'
|
||||||
end
|
end
|
||||||
|
|||||||
27
Example/Podfile.lock
Normal file
27
Example/Podfile.lock
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
PODS:
|
||||||
|
- FBSnapshotTestCase (2.0.2):
|
||||||
|
- FBSnapshotTestCase/SwiftSupport (= 2.0.2)
|
||||||
|
- FBSnapshotTestCase/Core (2.0.2)
|
||||||
|
- FBSnapshotTestCase/SwiftSupport (2.0.2):
|
||||||
|
- FBSnapshotTestCase/Core
|
||||||
|
- pop (1.0.7)
|
||||||
|
- PureLayout (2.0.6)
|
||||||
|
- TabBarPicker (0.1.0)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- FBSnapshotTestCase
|
||||||
|
- pop (~> 1.0)
|
||||||
|
- PureLayout
|
||||||
|
- TabBarPicker (from `../`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
TabBarPicker:
|
||||||
|
:path: ../
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
FBSnapshotTestCase: fd500d5b282c4ec60215d26d0b58b0cf271dd0d6
|
||||||
|
pop: 628ffc631644601567ee8bfaaaea493ebd7d0923
|
||||||
|
PureLayout: f25f0bb904d5ccfe6e31da3cb869185259f02e0d
|
||||||
|
TabBarPicker: f26d10a5d9f460b5a5a2d5ce5b48635c802577c5
|
||||||
|
|
||||||
|
COCOAPODS: 0.37.2
|
||||||
127
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Normal file
127
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <FBSnapshotTestCase/FBSnapshotTestCasePlatform.h>
|
||||||
|
|
||||||
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though.
|
||||||
|
@param view The view to snapshot
|
||||||
|
@param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method.
|
||||||
|
@param suffixes An NSOrderedSet of strings for the different suffixes
|
||||||
|
@param tolerance The percentage of pixels that can differ and still count as an 'identical' view
|
||||||
|
*/
|
||||||
|
#define FBSnapshotVerifyViewWithOptions(view__, identifier__, suffixes__, tolerance__) \
|
||||||
|
{ \
|
||||||
|
NSString *envReferenceImageDirectory = [NSProcessInfo processInfo].environment[@"FB_REFERENCE_IMAGE_DIR"]; \
|
||||||
|
NSError *error__ = nil; \
|
||||||
|
BOOL comparisonSuccess__; \
|
||||||
|
XCTAssertTrue((suffixes__.count > 0), @"Suffixes set cannot be empty %@", suffixes__); \
|
||||||
|
XCTAssertNotNil(envReferenceImageDirectory, @"Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.");\
|
||||||
|
for (NSString *suffix__ in suffixes__) { \
|
||||||
|
NSString *referenceImagesDirectory__ = [NSString stringWithFormat:@"%@%@", envReferenceImageDirectory, suffix__]; \
|
||||||
|
comparisonSuccess__ = [self compareSnapshotOfView:(view__) referenceImagesDirectory:referenceImagesDirectory__ identifier:(identifier__) tolerance:(tolerance__) error:&error__]; \
|
||||||
|
if (comparisonSuccess__ || self.recordMode) break; \
|
||||||
|
} \
|
||||||
|
XCTAssertTrue(comparisonSuccess__, @"Snapshot comparison failed: %@", error__); \
|
||||||
|
XCTAssertFalse(self.recordMode, @"Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FBSnapshotVerifyView(view__, identifier__) \
|
||||||
|
{ \
|
||||||
|
FBSnapshotVerifyViewWithOptions(view__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though.
|
||||||
|
@param layer The layer to snapshot
|
||||||
|
@param identifier An optional identifier, used is there are multiple snapshot tests in a given -test method.
|
||||||
|
@param suffixes An NSOrderedSet of strings for the different suffixes
|
||||||
|
@param tolerance The percentage of pixels that can differ and still count as an 'identical' layer
|
||||||
|
*/
|
||||||
|
#define FBSnapshotVerifyLayerWithOptions(layer__, identifier__, suffixes__, tolerance__) \
|
||||||
|
{ \
|
||||||
|
NSString *envReferenceImageDirectory = [NSProcessInfo processInfo].environment[@"FB_REFERENCE_IMAGE_DIR"]; \
|
||||||
|
NSError *error__ = nil; \
|
||||||
|
BOOL comparisonSuccess__; \
|
||||||
|
XCTAssertTrue((suffixes__.count > 0), @"Suffixes set cannot be empty %@", suffixes__); \
|
||||||
|
XCTAssertNotNil(envReferenceImageDirectory, @"Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.");\
|
||||||
|
for (NSString *suffix__ in suffixes__) { \
|
||||||
|
NSString *referenceImagesDirectory__ = [NSString stringWithFormat:@"%@%@", envReferenceImageDirectory, suffix__]; \
|
||||||
|
comparisonSuccess__ = [self compareSnapshotOfLayer:(layer__) referenceImagesDirectory:referenceImagesDirectory__ identifier:(identifier__) tolerance:(tolerance__) error:&error__]; \
|
||||||
|
if (comparisonSuccess__ || self.recordMode) break; \
|
||||||
|
} \
|
||||||
|
XCTAssertTrue(comparisonSuccess__, @"Snapshot comparison failed: %@", error__); \
|
||||||
|
XCTAssertFalse(self.recordMode, @"Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FBSnapshotVerifyLayer(layer__, identifier__) \
|
||||||
|
{ \
|
||||||
|
FBSnapshotVerifyLayerWithOptions(layer__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The base class of view snapshotting tests. If you have small UI component, it's often easier to configure it in a test
|
||||||
|
and compare an image of the view to a reference image that write lots of complex layout-code tests.
|
||||||
|
|
||||||
|
In order to flip the tests in your subclass to record the reference images set @c recordMode to @c YES.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
@code
|
||||||
|
- (void)setUp
|
||||||
|
{
|
||||||
|
[super setUp];
|
||||||
|
self.recordMode = YES;
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
@interface FBSnapshotTestCase : XCTestCase
|
||||||
|
|
||||||
|
/**
|
||||||
|
When YES, the test macros will save reference images, rather than performing an actual test.
|
||||||
|
*/
|
||||||
|
@property (readwrite, nonatomic, assign) BOOL recordMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs the comparison or records a snapshot of the layer if recordMode is YES.
|
||||||
|
@param layer The Layer to snapshot
|
||||||
|
@param referenceImagesDirectory The directory in which reference images are stored.
|
||||||
|
@param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method.
|
||||||
|
@param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care
|
||||||
|
@param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc).
|
||||||
|
@returns YES if the comparison (or saving of the reference image) succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)compareSnapshotOfLayer:(CALayer *)layer
|
||||||
|
referenceImagesDirectory:(NSString *)referenceImagesDirectory
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs the comparison or records a snapshot of the view if recordMode is YES.
|
||||||
|
@param view The view to snapshot
|
||||||
|
@param referenceImagesDirectory The directory in which reference images are stored.
|
||||||
|
@param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method.
|
||||||
|
@param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care
|
||||||
|
@param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc).
|
||||||
|
@returns YES if the comparison (or saving of the reference image) succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)compareSnapshotOfView:(UIView *)view
|
||||||
|
referenceImagesDirectory:(NSString *)referenceImagesDirectory
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
@end
|
||||||
86
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m
generated
Normal file
86
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m
generated
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "FBSnapshotTestCase.h"
|
||||||
|
|
||||||
|
#import "FBSnapshotTestController.h"
|
||||||
|
|
||||||
|
@implementation FBSnapshotTestCase
|
||||||
|
{
|
||||||
|
FBSnapshotTestController *_snapshotController;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setUp
|
||||||
|
{
|
||||||
|
[super setUp];
|
||||||
|
_snapshotController = [[FBSnapshotTestController alloc] initWithTestName:NSStringFromClass([self class])];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tearDown
|
||||||
|
{
|
||||||
|
_snapshotController = nil;
|
||||||
|
[super tearDown];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)recordMode
|
||||||
|
{
|
||||||
|
return _snapshotController.recordMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRecordMode:(BOOL)recordMode
|
||||||
|
{
|
||||||
|
NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__);
|
||||||
|
_snapshotController.recordMode = recordMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareSnapshotOfLayer:(CALayer *)layer
|
||||||
|
referenceImagesDirectory:(NSString *)referenceImagesDirectory
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
return [self _compareSnapshotOfViewOrLayer:layer
|
||||||
|
referenceImagesDirectory:referenceImagesDirectory
|
||||||
|
identifier:identifier
|
||||||
|
tolerance:tolerance
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareSnapshotOfView:(UIView *)view
|
||||||
|
referenceImagesDirectory:(NSString *)referenceImagesDirectory
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
return [self _compareSnapshotOfViewOrLayer:view
|
||||||
|
referenceImagesDirectory:referenceImagesDirectory
|
||||||
|
identifier:identifier
|
||||||
|
tolerance:tolerance
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Private API
|
||||||
|
|
||||||
|
- (BOOL)_compareSnapshotOfViewOrLayer:(id)viewOrLayer
|
||||||
|
referenceImagesDirectory:(NSString *)referenceImagesDirectory
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
_snapshotController.referenceImagesDirectory = referenceImagesDirectory;
|
||||||
|
return [_snapshotController compareSnapshotOfViewOrLayer:viewOrLayer
|
||||||
|
selector:self.invocation.selector
|
||||||
|
identifier:identifier
|
||||||
|
tolerance:tolerance
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
36
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Normal file
36
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a Boolean value that indicates whether the snapshot test is running in 64Bit.
|
||||||
|
This method is a convenience for creating the suffixes set based on the architecture
|
||||||
|
that the test is running.
|
||||||
|
|
||||||
|
@returns @c YES if the test is running in 64bit, otherwise @c NO.
|
||||||
|
*/
|
||||||
|
BOOL FBSnapshotTestCaseIs64Bit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a default set of strings that is used to append a suffix based on the architectures.
|
||||||
|
@warning Do not modify this function, you can create your own and use it with @c FBSnapshotVerifyViewWithOptions()
|
||||||
|
|
||||||
|
@returns An @c NSOrderedSet object containing strings that are appended to the reference images directory.
|
||||||
|
*/
|
||||||
|
NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
31
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m
generated
Normal file
31
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m
generated
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <FBSnapshotTestCase/FBSnapshotTestCasePlatform.h>
|
||||||
|
|
||||||
|
BOOL FBSnapshotTestCaseIs64Bit(void)
|
||||||
|
{
|
||||||
|
#if __LP64__
|
||||||
|
return YES;
|
||||||
|
#else
|
||||||
|
return NO;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void)
|
||||||
|
{
|
||||||
|
NSMutableOrderedSet *suffixesSet = [[NSMutableOrderedSet alloc] init];
|
||||||
|
[suffixesSet addObject:@"_32"];
|
||||||
|
[suffixesSet addObject:@"_64"];
|
||||||
|
if (FBSnapshotTestCaseIs64Bit()) {
|
||||||
|
return [suffixesSet reversedOrderedSet];
|
||||||
|
}
|
||||||
|
return [suffixesSet copy];
|
||||||
|
}
|
||||||
154
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Normal file
154
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, FBSnapshotTestControllerErrorCode) {
|
||||||
|
FBSnapshotTestControllerErrorCodeUnknown,
|
||||||
|
FBSnapshotTestControllerErrorCodeNeedsRecord,
|
||||||
|
FBSnapshotTestControllerErrorCodePNGCreationFailed,
|
||||||
|
FBSnapshotTestControllerErrorCodeImagesDifferentSizes,
|
||||||
|
FBSnapshotTestControllerErrorCodeImagesDifferent,
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Errors returned by the methods of FBSnapshotTestController use this domain.
|
||||||
|
*/
|
||||||
|
extern NSString *const FBSnapshotTestControllerErrorDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary.
|
||||||
|
*/
|
||||||
|
extern NSString *const FBReferenceImageFilePathKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Provides the heavy-lifting for FBSnapshotTestCase. It loads and saves images, along with performing the actual pixel-
|
||||||
|
by-pixel comparison of images.
|
||||||
|
Instances are initialized with the test class, and directories to read and write to.
|
||||||
|
*/
|
||||||
|
@interface FBSnapshotTestController : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
Record snapshots.
|
||||||
|
**/
|
||||||
|
@property (readwrite, nonatomic, assign) BOOL recordMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@param testClass The subclass of FBSnapshotTestCase that is using this controller.
|
||||||
|
@returns An instance of FBSnapshotTestController.
|
||||||
|
*/
|
||||||
|
- (instancetype)initWithTestClass:(Class)testClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Designated initializer.
|
||||||
|
@param testName The name of the tests.
|
||||||
|
@returns An instance of FBSnapshotTestController.
|
||||||
|
*/
|
||||||
|
- (instancetype)initWithTestName:(NSString *)testName;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs the comparison of the layer.
|
||||||
|
@param layer The Layer to snapshot.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method.
|
||||||
|
@param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc).
|
||||||
|
@returns YES if the comparison (or saving of the reference image) succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)compareSnapshotOfLayer:(CALayer *)layer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs the comparison of the view.
|
||||||
|
@param view The view to snapshot.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method.
|
||||||
|
@param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc).
|
||||||
|
@returns YES if the comparison (or saving of the reference image) succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)compareSnapshotOfView:(UIView *)view
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs the comparison of a view or layer.
|
||||||
|
@param view The view or layer to snapshot.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method.
|
||||||
|
@param tolerance The percentage of pixels that can differ and still be considered 'identical'
|
||||||
|
@param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc).
|
||||||
|
@returns YES if the comparison (or saving of the reference image) succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The directory in which referfence images are stored.
|
||||||
|
*/
|
||||||
|
@property (readwrite, nonatomic, copy) NSString *referenceImagesDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads a reference image.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier The optional identifier, used when multiple images are tested in a single -test method.
|
||||||
|
@param errorPtr An error, if this methods returns nil, the error will be something useful.
|
||||||
|
@returns An image.
|
||||||
|
*/
|
||||||
|
- (UIImage *)referenceImageForSelector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Saves a reference image.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier The optional identifier, used when multiple images are tested in a single -test method.
|
||||||
|
@param errorPtr An error, if this methods returns NO, the error will be something useful.
|
||||||
|
@returns An image.
|
||||||
|
*/
|
||||||
|
- (BOOL)saveReferenceImage:(UIImage *)image
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs a pixel-by-pixel comparison of the two images with an allowable margin of error.
|
||||||
|
@param referenceImage The reference (correct) image.
|
||||||
|
@param image The image to test against the reference.
|
||||||
|
@param tolerance The percentage of pixels that can differ and still be considered 'identical'
|
||||||
|
@param errorPtr An error that indicates why the comparison failed if it does.
|
||||||
|
@returns YES if the comparison succeeded and the images are the same(ish).
|
||||||
|
*/
|
||||||
|
- (BOOL)compareReferenceImage:(UIImage *)referenceImage
|
||||||
|
toImage:(UIImage *)image
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Saves the reference image and the test image to `failedOutputDirectory`.
|
||||||
|
@param referenceImage The reference (correct) image.
|
||||||
|
@param testImage The image to test against the reference.
|
||||||
|
@param selector The test method being run.
|
||||||
|
@param identifier The optional identifier, used when multiple images are tested in a single -test method.
|
||||||
|
@param errorPtr An error that indicates why the comparison failed if it does.
|
||||||
|
@returns YES if the save succeeded.
|
||||||
|
*/
|
||||||
|
- (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage
|
||||||
|
testImage:(UIImage *)testImage
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr;
|
||||||
|
@end
|
||||||
384
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m
generated
Normal file
384
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m
generated
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "FBSnapshotTestController.h"
|
||||||
|
|
||||||
|
#import "UIImage+Compare.h"
|
||||||
|
#import "UIImage+Diff.h"
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NSString *const FBSnapshotTestControllerErrorDomain = @"FBSnapshotTestControllerErrorDomain";
|
||||||
|
|
||||||
|
NSString *const FBReferenceImageFilePathKey = @"FBReferenceImageFilePathKey";
|
||||||
|
|
||||||
|
@implementation FBSnapshotTestController
|
||||||
|
{
|
||||||
|
NSString *_testName;
|
||||||
|
NSFileManager *_fileManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Lifecycle
|
||||||
|
|
||||||
|
- (instancetype)initWithTestClass:(Class)testClass;
|
||||||
|
{
|
||||||
|
return [self initWithTestName:NSStringFromClass(testClass)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithTestName:(NSString *)testName
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_testName = [testName copy];
|
||||||
|
_fileManager = [[NSFileManager alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
- (NSString *)description
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"%@ %@", [super description], _referenceImagesDirectory];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Public API
|
||||||
|
|
||||||
|
- (UIImage *)referenceImageForSelector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier];
|
||||||
|
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
|
||||||
|
if (nil == image && NULL != errorPtr) {
|
||||||
|
BOOL exists = [_fileManager fileExistsAtPath:filePath];
|
||||||
|
if (!exists) {
|
||||||
|
*errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain
|
||||||
|
code:FBSnapshotTestControllerErrorCodeNeedsRecord
|
||||||
|
userInfo:@{
|
||||||
|
FBReferenceImageFilePathKey: filePath,
|
||||||
|
NSLocalizedDescriptionKey: @"Unable to load reference image.",
|
||||||
|
NSLocalizedFailureReasonErrorKey: @"Reference image not found. You need to run the test in record mode",
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
*errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain
|
||||||
|
code:FBSnapshotTestControllerErrorCodeUnknown
|
||||||
|
userInfo:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)saveReferenceImage:(UIImage *)image
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
BOOL didWrite = NO;
|
||||||
|
if (nil != image) {
|
||||||
|
NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier];
|
||||||
|
NSData *pngData = UIImagePNGRepresentation(image);
|
||||||
|
if (nil != pngData) {
|
||||||
|
NSError *creationError = nil;
|
||||||
|
BOOL didCreateDir = [_fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent]
|
||||||
|
withIntermediateDirectories:YES
|
||||||
|
attributes:nil
|
||||||
|
error:&creationError];
|
||||||
|
if (!didCreateDir) {
|
||||||
|
if (NULL != errorPtr) {
|
||||||
|
*errorPtr = creationError;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
didWrite = [pngData writeToFile:filePath options:NSDataWritingAtomic error:errorPtr];
|
||||||
|
if (didWrite) {
|
||||||
|
NSLog(@"Reference image save at: %@", filePath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nil != errorPtr) {
|
||||||
|
*errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain
|
||||||
|
code:FBSnapshotTestControllerErrorCodePNGCreationFailed
|
||||||
|
userInfo:@{
|
||||||
|
FBReferenceImageFilePathKey: filePath,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return didWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage
|
||||||
|
testImage:(UIImage *)testImage
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
NSData *referencePNGData = UIImagePNGRepresentation(referenceImage);
|
||||||
|
NSData *testPNGData = UIImagePNGRepresentation(testImage);
|
||||||
|
|
||||||
|
NSString *referencePath = [self _failedFilePathForSelector:selector
|
||||||
|
identifier:identifier
|
||||||
|
fileNameType:FBTestSnapshotFileNameTypeFailedReference];
|
||||||
|
|
||||||
|
NSError *creationError = nil;
|
||||||
|
BOOL didCreateDir = [_fileManager createDirectoryAtPath:[referencePath stringByDeletingLastPathComponent]
|
||||||
|
withIntermediateDirectories:YES
|
||||||
|
attributes:nil
|
||||||
|
error:&creationError];
|
||||||
|
if (!didCreateDir) {
|
||||||
|
if (NULL != errorPtr) {
|
||||||
|
*errorPtr = creationError;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![referencePNGData writeToFile:referencePath options:NSDataWritingAtomic error:errorPtr]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *testPath = [self _failedFilePathForSelector:selector
|
||||||
|
identifier:identifier
|
||||||
|
fileNameType:FBTestSnapshotFileNameTypeFailedTest];
|
||||||
|
|
||||||
|
if (![testPNGData writeToFile:testPath options:NSDataWritingAtomic error:errorPtr]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *diffPath = [self _failedFilePathForSelector:selector
|
||||||
|
identifier:identifier
|
||||||
|
fileNameType:FBTestSnapshotFileNameTypeFailedTestDiff];
|
||||||
|
|
||||||
|
UIImage *diffImage = [referenceImage diffWithImage:testImage];
|
||||||
|
NSData *diffImageData = UIImagePNGRepresentation(diffImage);
|
||||||
|
|
||||||
|
if (![diffImageData writeToFile:diffPath options:NSDataWritingAtomic error:errorPtr]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"If you have Kaleidoscope installed you can run this command to see an image diff:\n"
|
||||||
|
@"ksdiff \"%@\" \"%@\"", referencePath, testPath);
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareReferenceImage:(UIImage *)referenceImage
|
||||||
|
toImage:(UIImage *)image
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr {
|
||||||
|
if (CGSizeEqualToSize(referenceImage.size, image.size)) {
|
||||||
|
|
||||||
|
BOOL imagesEqual = [referenceImage compareWithImage:image tolerance:tolerance];
|
||||||
|
if (NULL != errorPtr) {
|
||||||
|
*errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain
|
||||||
|
code:FBSnapshotTestControllerErrorCodeImagesDifferent
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: @"Images different",
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return imagesEqual;
|
||||||
|
}
|
||||||
|
if (NULL != errorPtr) {
|
||||||
|
*errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain
|
||||||
|
code:FBSnapshotTestControllerErrorCodeImagesDifferentSizes
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: @"Images different sizes",
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"referenceImage:%@, image:%@",
|
||||||
|
NSStringFromCGSize(referenceImage.size),
|
||||||
|
NSStringFromCGSize(image.size)],
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Private API
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, FBTestSnapshotFileNameType) {
|
||||||
|
FBTestSnapshotFileNameTypeReference,
|
||||||
|
FBTestSnapshotFileNameTypeFailedReference,
|
||||||
|
FBTestSnapshotFileNameTypeFailedTest,
|
||||||
|
FBTestSnapshotFileNameTypeFailedTestDiff,
|
||||||
|
};
|
||||||
|
|
||||||
|
- (NSString *)_fileNameForSelector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
fileNameType:(FBTestSnapshotFileNameType)fileNameType
|
||||||
|
{
|
||||||
|
NSString *fileName = nil;
|
||||||
|
switch (fileNameType) {
|
||||||
|
case FBTestSnapshotFileNameTypeFailedReference:
|
||||||
|
fileName = @"reference_";
|
||||||
|
break;
|
||||||
|
case FBTestSnapshotFileNameTypeFailedTest:
|
||||||
|
fileName = @"failed_";
|
||||||
|
break;
|
||||||
|
case FBTestSnapshotFileNameTypeFailedTestDiff:
|
||||||
|
fileName = @"diff_";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fileName = @"";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fileName = [fileName stringByAppendingString:NSStringFromSelector(selector)];
|
||||||
|
if (0 < identifier.length) {
|
||||||
|
fileName = [fileName stringByAppendingFormat:@"_%@", identifier];
|
||||||
|
}
|
||||||
|
if ([[UIScreen mainScreen] scale] > 1) {
|
||||||
|
fileName = [fileName stringByAppendingFormat:@"@%.fx", [[UIScreen mainScreen] scale]];
|
||||||
|
}
|
||||||
|
fileName = [fileName stringByAppendingPathExtension:@"png"];
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)_referenceFilePathForSelector:(SEL)selector identifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
NSString *fileName = [self _fileNameForSelector:selector
|
||||||
|
identifier:identifier
|
||||||
|
fileNameType:FBTestSnapshotFileNameTypeReference];
|
||||||
|
NSString *filePath = [_referenceImagesDirectory stringByAppendingPathComponent:_testName];
|
||||||
|
filePath = [filePath stringByAppendingPathComponent:fileName];
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)_failedFilePathForSelector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
fileNameType:(FBTestSnapshotFileNameType)fileNameType
|
||||||
|
{
|
||||||
|
NSString *fileName = [self _fileNameForSelector:selector
|
||||||
|
identifier:identifier
|
||||||
|
fileNameType:fileNameType];
|
||||||
|
NSString *folderPath = NSTemporaryDirectory();
|
||||||
|
if (getenv("IMAGE_DIFF_DIR")) {
|
||||||
|
folderPath = @(getenv("IMAGE_DIFF_DIR"));
|
||||||
|
}
|
||||||
|
NSString *filePath = [folderPath stringByAppendingPathComponent:_testName];
|
||||||
|
filePath = [filePath stringByAppendingPathComponent:fileName];
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareSnapshotOfLayer:(CALayer *)layer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
return [self compareSnapshotOfViewOrLayer:layer
|
||||||
|
selector:selector
|
||||||
|
identifier:identifier
|
||||||
|
tolerance:0
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareSnapshotOfView:(UIView *)view
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
return [self compareSnapshotOfViewOrLayer:view
|
||||||
|
selector:selector
|
||||||
|
identifier:identifier
|
||||||
|
tolerance:0
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
if (self.recordMode) {
|
||||||
|
return [self _recordSnapshotOfViewOrLayer:viewOrLayer selector:selector identifier:identifier error:errorPtr];
|
||||||
|
} else {
|
||||||
|
return [self _performPixelComparisonWithViewOrLayer:viewOrLayer selector:selector identifier:identifier tolerance:tolerance error:errorPtr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Private API
|
||||||
|
|
||||||
|
- (BOOL)_performPixelComparisonWithViewOrLayer:(id)viewOrLayer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
tolerance:(CGFloat)tolerance
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
UIImage *referenceImage = [self referenceImageForSelector:selector identifier:identifier error:errorPtr];
|
||||||
|
if (nil != referenceImage) {
|
||||||
|
UIImage *snapshot = [self _snapshotViewOrLayer:viewOrLayer];
|
||||||
|
BOOL imagesSame = [self compareReferenceImage:referenceImage toImage:snapshot tolerance:tolerance error:errorPtr];
|
||||||
|
if (!imagesSame) {
|
||||||
|
[self saveFailedReferenceImage:referenceImage
|
||||||
|
testImage:snapshot
|
||||||
|
selector:selector
|
||||||
|
identifier:identifier
|
||||||
|
error:errorPtr];
|
||||||
|
}
|
||||||
|
return imagesSame;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)_recordSnapshotOfViewOrLayer:(id)viewOrLayer
|
||||||
|
selector:(SEL)selector
|
||||||
|
identifier:(NSString *)identifier
|
||||||
|
error:(NSError **)errorPtr
|
||||||
|
{
|
||||||
|
UIImage *snapshot = [self _snapshotViewOrLayer:viewOrLayer];
|
||||||
|
return [self saveReferenceImage:snapshot selector:selector identifier:identifier error:errorPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *)_snapshotViewOrLayer:(id)viewOrLayer
|
||||||
|
{
|
||||||
|
CALayer *layer = nil;
|
||||||
|
|
||||||
|
if ([viewOrLayer isKindOfClass:[UIView class]]) {
|
||||||
|
return [self _renderView:viewOrLayer];
|
||||||
|
} else if ([viewOrLayer isKindOfClass:[CALayer class]]) {
|
||||||
|
layer = (CALayer *)viewOrLayer;
|
||||||
|
[layer layoutIfNeeded];
|
||||||
|
return [self _renderLayer:layer];
|
||||||
|
} else {
|
||||||
|
[NSException raise:@"Only UIView and CALayer classes can be snapshotted" format:@"%@", viewOrLayer];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *)_renderLayer:(CALayer *)layer
|
||||||
|
{
|
||||||
|
CGRect bounds = layer.bounds;
|
||||||
|
|
||||||
|
NSAssert1(CGRectGetWidth(bounds), @"Zero width for layer %@", layer);
|
||||||
|
NSAssert1(CGRectGetHeight(bounds), @"Zero height for layer %@", layer);
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0);
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
NSAssert1(context, @"Could not generate context for layer %@", layer);
|
||||||
|
|
||||||
|
CGContextSaveGState(context);
|
||||||
|
{
|
||||||
|
[layer renderInContext:context];
|
||||||
|
}
|
||||||
|
CGContextRestoreGState(context);
|
||||||
|
|
||||||
|
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *)_renderView:(UIView *)view
|
||||||
|
{
|
||||||
|
[view layoutIfNeeded];
|
||||||
|
return [self _renderLayer:view.layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
58
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift
generated
Normal file
58
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift
generated
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public extension FBSnapshotTestCase {
|
||||||
|
public func FBSnapshotVerifyView(view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), file: String = __FILE__, line: UInt = __LINE__) {
|
||||||
|
let envReferenceImageDirectory = NSProcessInfo.processInfo().environment["FB_REFERENCE_IMAGE_DIR"] as? String
|
||||||
|
var error: NSError?
|
||||||
|
|
||||||
|
if let envReferenceImageDirectory = envReferenceImageDirectory {
|
||||||
|
for suffix in suffixes {
|
||||||
|
let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)"
|
||||||
|
let comparisonSuccess = compareSnapshotOfView(view, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: 0, error: &error)
|
||||||
|
if comparisonSuccess || recordMode {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line)
|
||||||
|
assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(false, message: "Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.", file: file, line: line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func FBSnapshotVerifyLayer(layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), file: String = __FILE__, line: UInt = __LINE__) {
|
||||||
|
let envReferenceImageDirectory = NSProcessInfo.processInfo().environment["FB_REFERENCE_IMAGE_DIR"] as? String
|
||||||
|
var error: NSError?
|
||||||
|
var comparisonSuccess = false
|
||||||
|
|
||||||
|
if let envReferenceImageDirectory = envReferenceImageDirectory {
|
||||||
|
for suffix in suffixes {
|
||||||
|
let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)"
|
||||||
|
comparisonSuccess = compareSnapshotOfLayer(layer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: 0, error: &error)
|
||||||
|
if comparisonSuccess || recordMode {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line)
|
||||||
|
assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assert(assertion: Bool, message: String, file: String, line: UInt) {
|
||||||
|
if !assertion {
|
||||||
|
XCTFail(message, file: file, line: line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.h
generated
Normal file
37
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.h
generated
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by Gabriel Handford on 3/1/09.
|
||||||
|
// Copyright 2009-2013. All rights reserved.
|
||||||
|
// Created by John Boiles on 10/20/11.
|
||||||
|
// Copyright (c) 2011. All rights reserved
|
||||||
|
// Modified by Felix Schulze on 2/11/13.
|
||||||
|
// Copyright 2013. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface UIImage (Compare)
|
||||||
|
|
||||||
|
- (BOOL)compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance;
|
||||||
|
|
||||||
|
@end
|
||||||
134
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.m
generated
Normal file
134
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.m
generated
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// Created by Gabriel Handford on 3/1/09.
|
||||||
|
// Copyright 2009-2013. All rights reserved.
|
||||||
|
// Created by John Boiles on 10/20/11.
|
||||||
|
// Copyright (c) 2011. All rights reserved
|
||||||
|
// Modified by Felix Schulze on 2/11/13.
|
||||||
|
// Copyright 2013. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UIImage+Compare.h"
|
||||||
|
|
||||||
|
// This makes debugging much more fun
|
||||||
|
typedef union {
|
||||||
|
uint32_t raw;
|
||||||
|
unsigned char bytes[4];
|
||||||
|
struct {
|
||||||
|
char red;
|
||||||
|
char green;
|
||||||
|
char blue;
|
||||||
|
char alpha;
|
||||||
|
} __attribute__ ((packed)) pixels;
|
||||||
|
} FBComparePixel;
|
||||||
|
|
||||||
|
@implementation UIImage (Compare)
|
||||||
|
|
||||||
|
- (BOOL)compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance
|
||||||
|
{
|
||||||
|
NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size.");
|
||||||
|
|
||||||
|
CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage));
|
||||||
|
CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
|
||||||
|
|
||||||
|
// The images have the equal size, so we could use the smallest amount of bytes because of byte padding
|
||||||
|
size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage));
|
||||||
|
size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow;
|
||||||
|
void *referenceImagePixels = calloc(1, referenceImageSizeBytes);
|
||||||
|
void *imagePixels = calloc(1, referenceImageSizeBytes);
|
||||||
|
|
||||||
|
if (!referenceImagePixels || !imagePixels) {
|
||||||
|
free(referenceImagePixels);
|
||||||
|
free(imagePixels);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels,
|
||||||
|
referenceImageSize.width,
|
||||||
|
referenceImageSize.height,
|
||||||
|
CGImageGetBitsPerComponent(self.CGImage),
|
||||||
|
minBytesPerRow,
|
||||||
|
CGImageGetColorSpace(self.CGImage),
|
||||||
|
(CGBitmapInfo)kCGImageAlphaPremultipliedLast
|
||||||
|
);
|
||||||
|
CGContextRef imageContext = CGBitmapContextCreate(imagePixels,
|
||||||
|
imageSize.width,
|
||||||
|
imageSize.height,
|
||||||
|
CGImageGetBitsPerComponent(image.CGImage),
|
||||||
|
minBytesPerRow,
|
||||||
|
CGImageGetColorSpace(image.CGImage),
|
||||||
|
(CGBitmapInfo)kCGImageAlphaPremultipliedLast
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!referenceImageContext || !imageContext) {
|
||||||
|
CGContextRelease(referenceImageContext);
|
||||||
|
CGContextRelease(imageContext);
|
||||||
|
free(referenceImagePixels);
|
||||||
|
free(imagePixels);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage);
|
||||||
|
CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage);
|
||||||
|
|
||||||
|
CGContextRelease(referenceImageContext);
|
||||||
|
CGContextRelease(imageContext);
|
||||||
|
|
||||||
|
BOOL imageEqual = YES;
|
||||||
|
|
||||||
|
// Do a fast compare if we can
|
||||||
|
if (tolerance == 0) {
|
||||||
|
imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0);
|
||||||
|
} else {
|
||||||
|
// Go through each pixel in turn and see if it is different
|
||||||
|
const NSInteger pixelCount = self.size.width * self.size.height;
|
||||||
|
|
||||||
|
FBComparePixel *p1 = referenceImagePixels;
|
||||||
|
FBComparePixel *p2 = imagePixels;
|
||||||
|
|
||||||
|
NSInteger numDiffPixels = 0;
|
||||||
|
for (int n = 0; n < pixelCount; ++n) {
|
||||||
|
// If this pixel is different, increment the pixel diff count and see
|
||||||
|
// if we have hit our limit.
|
||||||
|
if (p1->raw != p2->raw) {
|
||||||
|
numDiffPixels ++;
|
||||||
|
|
||||||
|
CGFloat percent = (CGFloat)numDiffPixels / pixelCount;
|
||||||
|
if (percent > tolerance) {
|
||||||
|
imageEqual = NO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p1++;
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(referenceImagePixels);
|
||||||
|
free(imagePixels);
|
||||||
|
|
||||||
|
return imageEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
37
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.h
generated
Normal file
37
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.h
generated
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by Gabriel Handford on 3/1/09.
|
||||||
|
// Copyright 2009-2013. All rights reserved.
|
||||||
|
// Created by John Boiles on 10/20/11.
|
||||||
|
// Copyright (c) 2011. All rights reserved
|
||||||
|
// Modified by Felix Schulze on 2/11/13.
|
||||||
|
// Copyright 2013. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface UIImage (Diff)
|
||||||
|
|
||||||
|
- (UIImage *)diffWithImage:(UIImage *)image;
|
||||||
|
|
||||||
|
@end
|
||||||
56
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.m
generated
Normal file
56
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.m
generated
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Created by Gabriel Handford on 3/1/09.
|
||||||
|
// Copyright 2009-2013. All rights reserved.
|
||||||
|
// Created by John Boiles on 10/20/11.
|
||||||
|
// Copyright (c) 2011. All rights reserved
|
||||||
|
// Modified by Felix Schulze on 2/11/13.
|
||||||
|
// Copyright 2013. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UIImage+Diff.h"
|
||||||
|
|
||||||
|
@implementation UIImage (Diff)
|
||||||
|
|
||||||
|
- (UIImage *)diffWithImage:(UIImage *)image
|
||||||
|
{
|
||||||
|
if (!image) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
CGSize imageSize = CGSizeMake(MAX(self.size.width, image.size.width), MAX(self.size.height, image.size.height));
|
||||||
|
UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0);
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
|
||||||
|
CGContextSetAlpha(context, 0.5);
|
||||||
|
CGContextBeginTransparencyLayer(context, NULL);
|
||||||
|
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
|
||||||
|
CGContextSetBlendMode(context, kCGBlendModeDifference);
|
||||||
|
CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor);
|
||||||
|
CGContextFillRect(context, CGRectMake(0, 0, self.size.width, self.size.height));
|
||||||
|
CGContextEndTransparencyLayer(context);
|
||||||
|
UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
return returnImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
29
Example/Pods/FBSnapshotTestCase/LICENSE
generated
Normal file
29
Example/Pods/FBSnapshotTestCase/LICENSE
generated
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
BSD License
|
||||||
|
|
||||||
|
For the FBSnapshotTestCase software
|
||||||
|
|
||||||
|
Copyright (c) 2013, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* Neither the name Facebook nor the names of its contributors may be used to
|
||||||
|
endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
97
Example/Pods/FBSnapshotTestCase/README.md
generated
Normal file
97
Example/Pods/FBSnapshotTestCase/README.md
generated
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
FBSnapshotTestCase
|
||||||
|
======================
|
||||||
|
|
||||||
|
[](https://travis-ci.org/facebook/ios-snapshot-test-case) [](http://cocoadocs.org/docsets/FBSnapshotTestCase/)
|
||||||
|
|
||||||
|
What it does
|
||||||
|
------------
|
||||||
|
|
||||||
|
A "snapshot test case" takes a configured `UIView` or `CALayer` and uses the
|
||||||
|
`renderInContext:` method to get an image snapshot of its contents. It
|
||||||
|
compares this snapshot to a "reference image" stored in your source code
|
||||||
|
repository and fails the test if the two images don't match.
|
||||||
|
|
||||||
|
Why?
|
||||||
|
----
|
||||||
|
|
||||||
|
At Facebook we write a lot of UI code. As you might imagine, each type of
|
||||||
|
feed story is rendered using a subclass of `UIView`. There are a lot of edge
|
||||||
|
cases that we want to handle correctly:
|
||||||
|
|
||||||
|
- What if there is more text than can fit in the space available?
|
||||||
|
- What if an image doesn't match the size of an image view?
|
||||||
|
- What should the highlighted state look like?
|
||||||
|
|
||||||
|
It's straightforward to test logic code, but less obvious how you should test
|
||||||
|
views. You can do a lot of rectangle asserts, but these are hard to understand
|
||||||
|
or visualize. Looking at an image diff shows you exactly what changed and how
|
||||||
|
it will look to users.
|
||||||
|
|
||||||
|
We developed `FBSnapshotTestCase` to make snapshot tests easy.
|
||||||
|
|
||||||
|
Installation with CocoaPods
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
1. Add the following lines to your Podfile:
|
||||||
|
|
||||||
|
```
|
||||||
|
target "Tests" do
|
||||||
|
pod 'FBSnapshotTestCase'
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
If you support iOS 7 use `FBSnapshotTestCase/Core` instead, which doesn't contain Swift support.
|
||||||
|
|
||||||
|
Replace "Tests" with the name of your test project.
|
||||||
|
|
||||||
|
2. Define `FB_REFERENCE_IMAGE_DIR` in your scheme. This should
|
||||||
|
point to the directory where you want reference images to be stored. At Facebook,
|
||||||
|
we normally use this:
|
||||||
|
|
||||||
|
|Name|Value|
|
||||||
|
|:---|:----|
|
||||||
|
|`FB_REFERENCE_IMAGE_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages`|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Creating a snapshot test
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
1. Subclass `FBSnapshotTestCase` instead of `XCTestCase`.
|
||||||
|
2. From within your test, use `FBSnapshotVerifyView`.
|
||||||
|
3. Run the test once with `self.recordMode = YES;` in the test's `-setUp`
|
||||||
|
method. (This creates the reference images on disk.)
|
||||||
|
4. Remove the line enabling record mode and run the test.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Automatically names reference images on disk according to test class and
|
||||||
|
selector.
|
||||||
|
- Prints a descriptive error message to the console on failure. (Bonus:
|
||||||
|
failure message includes a one-line command to see an image diff if
|
||||||
|
you have [Kaleidoscope](http://www.kaleidoscopeapp.com) installed.)
|
||||||
|
- Supply an optional "identifier" if you want to perform multiple snapshots
|
||||||
|
in a single test method.
|
||||||
|
- Support for `CALayer` via `FBSnapshotVerifyLayer`.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
Your unit test must be an "application test", not a "logic test." (That is, it
|
||||||
|
must be run within the Simulator so that it has access to UIKit.) In Xcode 5
|
||||||
|
and later new projects only offer application tests, but older projects will
|
||||||
|
have separate targets for the two types.
|
||||||
|
|
||||||
|
Authors
|
||||||
|
-------
|
||||||
|
|
||||||
|
`FBSnapshotTestCase` was written at Facebook by
|
||||||
|
[Jonathan Dann](https://facebook.com/j.p.dann) with significant contributions by
|
||||||
|
[Todd Krabach](https://facebook.com/toddkrabach).
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
`FBSnapshotTestCase` is BSD-licensed. See `LICENSE`.
|
||||||
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Symbolic link
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h
|
||||||
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Symbolic link
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
|
||||||
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Symbolic link
1
Example/Pods/Headers/Private/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h
|
||||||
1
Example/Pods/Headers/Private/FBSnapshotTestCase/UIImage+Compare.h
generated
Symbolic link
1
Example/Pods/Headers/Private/FBSnapshotTestCase/UIImage+Compare.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.h
|
||||||
1
Example/Pods/Headers/Private/FBSnapshotTestCase/UIImage+Diff.h
generated
Symbolic link
1
Example/Pods/Headers/Private/FBSnapshotTestCase/UIImage+Diff.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/ALView+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/ALView+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/ALView+PureLayout.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/NSArray+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/NSArray+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/NSLayoutConstraint+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/NSLayoutConstraint+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/PureLayout+Internal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/PureLayout+Internal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayout+Internal.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayout.h
|
||||||
1
Example/Pods/Headers/Private/PureLayout/PureLayoutDefines.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PureLayout/PureLayoutDefines.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayoutDefines.h
|
||||||
1
Example/Pods/Headers/Private/TabBarPicker/TabBarItem.h
generated
Symbolic link
1
Example/Pods/Headers/Private/TabBarPicker/TabBarItem.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarItem.h
|
||||||
1
Example/Pods/Headers/Private/TabBarPicker/TabBarPicker.h
generated
Symbolic link
1
Example/Pods/Headers/Private/TabBarPicker/TabBarPicker.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarPicker.h
|
||||||
1
Example/Pods/Headers/Private/TabBarPicker/TabBarSubItem.h
generated
Symbolic link
1
Example/Pods/Headers/Private/TabBarPicker/TabBarSubItem.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarSubItem.h
|
||||||
1
Example/Pods/Headers/Private/pop/FloatConversion.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/FloatConversion.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/WebCore/FloatConversion.h
|
||||||
1
Example/Pods/Headers/Private/pop/POP.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POP.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POP.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAction.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAction.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAction.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimatableProperty.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimatableProperty.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimatableProperty.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationEvent.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationEvent.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationEvent.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationEventInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationEventInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationEventInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationExtras.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationExtras.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationExtras.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationPrivate.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationPrivate.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationPrivate.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationRuntime.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationRuntime.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationRuntime.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationTracer.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationTracer.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationTracer.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimationTracerInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimationTracerInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationTracerInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimator.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimator.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimator.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPAnimatorPrivate.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPAnimatorPrivate.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimatorPrivate.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPBasicAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPBasicAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPBasicAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPBasicAnimationInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPBasicAnimationInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPBasicAnimationInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPCGUtils.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPCGUtils.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPCGUtils.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPCustomAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPCustomAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPCustomAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPDecayAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPDecayAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPDecayAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPDecayAnimationInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPDecayAnimationInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPDecayAnimationInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPDefines.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPDefines.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPDefines.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPGeometry.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPGeometry.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPGeometry.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPLayerExtras.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPLayerExtras.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPLayerExtras.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPMath.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPMath.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPMath.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPPropertyAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPPropertyAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPPropertyAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPPropertyAnimationInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPPropertyAnimationInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPPropertyAnimationInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPSpringAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPSpringAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPSpringAnimation.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPSpringAnimationInternal.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPSpringAnimationInternal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPSpringAnimationInternal.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPSpringSolver.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPSpringSolver.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPSpringSolver.h
|
||||||
1
Example/Pods/Headers/Private/pop/POPVector.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/POPVector.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPVector.h
|
||||||
1
Example/Pods/Headers/Private/pop/TransformationMatrix.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/TransformationMatrix.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/WebCore/TransformationMatrix.h
|
||||||
1
Example/Pods/Headers/Private/pop/UnitBezier.h
generated
Symbolic link
1
Example/Pods/Headers/Private/pop/UnitBezier.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/WebCore/UnitBezier.h
|
||||||
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Symbolic link
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestCase.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h
|
||||||
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Symbolic link
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h
|
||||||
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Symbolic link
1
Example/Pods/Headers/Public/FBSnapshotTestCase/FBSnapshotTestController.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h
|
||||||
1
Example/Pods/Headers/Public/FBSnapshotTestCase/UIImage+Compare.h
generated
Symbolic link
1
Example/Pods/Headers/Public/FBSnapshotTestCase/UIImage+Compare.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Compare.h
|
||||||
1
Example/Pods/Headers/Public/FBSnapshotTestCase/UIImage+Diff.h
generated
Symbolic link
1
Example/Pods/Headers/Public/FBSnapshotTestCase/UIImage+Diff.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../FBSnapshotTestCase/FBSnapshotTestCase/UIImage+Diff.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/ALView+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/ALView+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/ALView+PureLayout.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/NSArray+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/NSArray+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/NSLayoutConstraint+PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/NSLayoutConstraint+PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/PureLayout+Internal.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/PureLayout+Internal.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayout+Internal.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/PureLayout.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/PureLayout.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayout.h
|
||||||
1
Example/Pods/Headers/Public/PureLayout/PureLayoutDefines.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PureLayout/PureLayoutDefines.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../PureLayout/PureLayout/PureLayout/PureLayoutDefines.h
|
||||||
1
Example/Pods/Headers/Public/TabBarPicker/TabBarItem.h
generated
Symbolic link
1
Example/Pods/Headers/Public/TabBarPicker/TabBarItem.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarItem.h
|
||||||
1
Example/Pods/Headers/Public/TabBarPicker/TabBarPicker.h
generated
Symbolic link
1
Example/Pods/Headers/Public/TabBarPicker/TabBarPicker.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarPicker.h
|
||||||
1
Example/Pods/Headers/Public/TabBarPicker/TabBarSubItem.h
generated
Symbolic link
1
Example/Pods/Headers/Public/TabBarPicker/TabBarSubItem.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/TabBarSubItem.h
|
||||||
1
Example/Pods/Headers/Public/pop/POP.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POP.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POP.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimatableProperty.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimatableProperty.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimatableProperty.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimation.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimationEvent.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimationEvent.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationEvent.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimationExtras.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimationExtras.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationExtras.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimationTracer.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimationTracer.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimationTracer.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPAnimator.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPAnimator.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPAnimator.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPBasicAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPBasicAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPBasicAnimation.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPCustomAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPCustomAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPCustomAnimation.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPDecayAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPDecayAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPDecayAnimation.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPDefines.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPDefines.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPDefines.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPGeometry.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPGeometry.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPGeometry.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPLayerExtras.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPLayerExtras.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPLayerExtras.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPPropertyAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPPropertyAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPPropertyAnimation.h
|
||||||
1
Example/Pods/Headers/Public/pop/POPSpringAnimation.h
generated
Symbolic link
1
Example/Pods/Headers/Public/pop/POPSpringAnimation.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../pop/pop/POPSpringAnimation.h
|
||||||
25
Example/Pods/Local Podspecs/TabBarPicker.podspec.json
generated
Normal file
25
Example/Pods/Local Podspecs/TabBarPicker.podspec.json
generated
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "TabBarPicker",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"summary": "A short description of TabBarPicker.",
|
||||||
|
"description": " An optional longer description of TabBarPicker\n\n * Markdown format.\n * Don't worry about the indent, we strip it!\n",
|
||||||
|
"homepage": "https://github.com/<GITHUB_USERNAME>/TabBarPicker",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": {
|
||||||
|
"Giuseppe Nucifora": "me@giuseppenucifora.com"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"git": "https://github.com/<GITHUB_USERNAME>/TabBarPicker.git",
|
||||||
|
"tag": "0.1.0"
|
||||||
|
},
|
||||||
|
"platforms": {
|
||||||
|
"ios": "7.0"
|
||||||
|
},
|
||||||
|
"requires_arc": true,
|
||||||
|
"source_files": "Pod/Classes/**/*",
|
||||||
|
"resource_bundles": {
|
||||||
|
"TabBarPicker": [
|
||||||
|
"Pod/Assets/*.png"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Example/Pods/Manifest.lock
generated
Normal file
27
Example/Pods/Manifest.lock
generated
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
PODS:
|
||||||
|
- FBSnapshotTestCase (2.0.2):
|
||||||
|
- FBSnapshotTestCase/SwiftSupport (= 2.0.2)
|
||||||
|
- FBSnapshotTestCase/Core (2.0.2)
|
||||||
|
- FBSnapshotTestCase/SwiftSupport (2.0.2):
|
||||||
|
- FBSnapshotTestCase/Core
|
||||||
|
- pop (1.0.7)
|
||||||
|
- PureLayout (2.0.6)
|
||||||
|
- TabBarPicker (0.1.0)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- FBSnapshotTestCase
|
||||||
|
- pop (~> 1.0)
|
||||||
|
- PureLayout
|
||||||
|
- TabBarPicker (from `../`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
TabBarPicker:
|
||||||
|
:path: ../
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
FBSnapshotTestCase: fd500d5b282c4ec60215d26d0b58b0cf271dd0d6
|
||||||
|
pop: 628ffc631644601567ee8bfaaaea493ebd7d0923
|
||||||
|
PureLayout: f25f0bb904d5ccfe6e31da3cb869185259f02e0d
|
||||||
|
TabBarPicker: f26d10a5d9f460b5a5a2d5ce5b48635c802577c5
|
||||||
|
|
||||||
|
COCOAPODS: 0.37.2
|
||||||
1815
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
Normal file
1815
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0640"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "8CA46A24F79F8A2591154DC8"
|
||||||
|
BuildableName = "TabBarPicker.bundle"
|
||||||
|
BlueprintName = "Pods-TabBarPicker_Example-TabBarPicker-TabBarPicker"
|
||||||
|
ReferencedContainer = "container:Pods.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
59
Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-TabBarPicker_Example-TabBarPicker.xcscheme
generated
Normal file
59
Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-TabBarPicker_Example-TabBarPicker.xcscheme
generated
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0640"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "AE841CD8269D52D367EBAEBB"
|
||||||
|
BuildableName = "TabBarPicker.framework"
|
||||||
|
BlueprintName = "Pods-TabBarPicker_Example-TabBarPicker"
|
||||||
|
ReferencedContainer = "container:Pods.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0640"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "C26F15991223F90FD04DB84A"
|
||||||
|
BuildableName = "TabBarPicker.bundle"
|
||||||
|
BlueprintName = "Pods-TabBarPicker_Tests-TabBarPicker-TabBarPicker"
|
||||||
|
ReferencedContainer = "container:Pods.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
59
Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-TabBarPicker_Tests-TabBarPicker.xcscheme
generated
Normal file
59
Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-TabBarPicker_Tests-TabBarPicker.xcscheme
generated
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0640"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "561939E4515B71341136E16E"
|
||||||
|
BuildableName = "TabBarPicker.framework"
|
||||||
|
BlueprintName = "Pods-TabBarPicker_Tests-TabBarPicker"
|
||||||
|
ReferencedContainer = "container:Pods.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
9
Example/Pods/PureLayout/LICENSE
generated
Executable file
9
Example/Pods/PureLayout/LICENSE
generated
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
This code is distributed under the terms and conditions of the MIT license.
|
||||||
|
|
||||||
|
Copyright (c) 2014-2015 Tyler Fox
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
253
Example/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h
generated
Executable file
253
Example/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h
generated
Executable file
@ -0,0 +1,253 @@
|
|||||||
|
//
|
||||||
|
// ALView+PureLayout.h
|
||||||
|
// v2.0.5
|
||||||
|
// https://github.com/smileyborg/PureLayout
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012 Richard Turton
|
||||||
|
// Copyright (c) 2013-2015 Tyler Fox
|
||||||
|
//
|
||||||
|
// This code is distributed under the terms and conditions of the MIT license.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PureLayoutDefines.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - ALView+PureLayout
|
||||||
|
|
||||||
|
/**
|
||||||
|
A category on UIView/NSView that provides a simple yet powerful interface for creating Auto Layout constraints.
|
||||||
|
*/
|
||||||
|
@interface ALView (PureLayout)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Factory & Initializer Methods
|
||||||
|
|
||||||
|
/** Creates and returns a new view that does not convert the autoresizing mask into constraints. */
|
||||||
|
+ (instancetype)newAutoLayoutView;
|
||||||
|
|
||||||
|
/** Initializes and returns a new view that does not convert the autoresizing mask into constraints. */
|
||||||
|
- (instancetype)initForAutoLayout;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Create Constraints Without Installing
|
||||||
|
|
||||||
|
/** Prevents constraints created in the given constraints block from being automatically installed (activated).
|
||||||
|
The constraints created from calls to the PureLayout API in the block are returned in a single array. */
|
||||||
|
+ (NSArray *)autoCreateConstraintsWithoutInstalling:(ALConstraintsBlock)block;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Set Priority For Constraints
|
||||||
|
|
||||||
|
/** Sets the constraint priority to the given value for all constraints created using the PureLayout API within the given constraints block.
|
||||||
|
NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added without using the PureLayout API! */
|
||||||
|
+ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(ALConstraintsBlock)block;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Set Identifier For Constraints
|
||||||
|
|
||||||
|
#if __PureLayout_MinBaseSDK_iOS_8_0
|
||||||
|
|
||||||
|
/** Sets the identifier for all constraints created using the PureLayout API within the given constraints block.
|
||||||
|
NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added without using the PureLayout API! */
|
||||||
|
+ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(ALConstraintsBlock)block;
|
||||||
|
|
||||||
|
#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Center & Align in Superview
|
||||||
|
|
||||||
|
/** Centers the view in its superview. */
|
||||||
|
- (NSArray *)autoCenterInSuperview;
|
||||||
|
|
||||||
|
/** Aligns the view to the same axis of its superview. */
|
||||||
|
- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis;
|
||||||
|
|
||||||
|
#if __PureLayout_MinBaseSDK_iOS_8_0
|
||||||
|
|
||||||
|
/** Centers the view in its superview's margins. Available in iOS 8.0 and later. */
|
||||||
|
- (NSArray *)autoCenterInSuperviewMargins;
|
||||||
|
|
||||||
|
/** Aligns the view to the corresponding margin axis of its superview. Available in iOS 8.0 and later. */
|
||||||
|
- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis;
|
||||||
|
|
||||||
|
#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Pin Edges to Superview
|
||||||
|
|
||||||
|
/** Pins the given edge of the view to the same edge of its superview. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge;
|
||||||
|
|
||||||
|
/** Pins the given edge of the view to the same edge of its superview with an inset. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset;
|
||||||
|
|
||||||
|
/** Pins the given edge of the view to the same edge of its superview with an inset as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
/** Pins the edges of the view to the edges of its superview with the given edge insets. */
|
||||||
|
- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets;
|
||||||
|
|
||||||
|
/** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */
|
||||||
|
- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge;
|
||||||
|
|
||||||
|
#if __PureLayout_MinBaseSDK_iOS_8_0
|
||||||
|
|
||||||
|
/** Pins the given edge of the view to the corresponding margin of its superview. Available in iOS 8.0 and later. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge;
|
||||||
|
|
||||||
|
/** Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. Available in iOS 8.0 and later. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
/** Pins the edges of the view to the margins of its superview. Available in iOS 8.0 and later. */
|
||||||
|
- (NSArray *)autoPinEdgesToSuperviewMargins;
|
||||||
|
|
||||||
|
/** Pins 3 of the 4 edges of the view to the margins of its superview excluding one edge. Available in iOS 8.0 and later. */
|
||||||
|
- (NSArray *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge;
|
||||||
|
|
||||||
|
#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Pin Edges
|
||||||
|
|
||||||
|
/** Pins an edge of the view to a given edge of another view. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView;
|
||||||
|
|
||||||
|
/** Pins an edge of the view to a given edge of another view with an offset. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset;
|
||||||
|
|
||||||
|
/** Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Align Axes
|
||||||
|
|
||||||
|
/** Aligns an axis of the view to the same axis of another view. */
|
||||||
|
- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView;
|
||||||
|
|
||||||
|
/** Aligns an axis of the view to the same axis of another view with an offset. */
|
||||||
|
- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withOffset:(CGFloat)offset;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Match Dimensions
|
||||||
|
|
||||||
|
/** Matches a dimension of the view to a given dimension of another view. */
|
||||||
|
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView;
|
||||||
|
|
||||||
|
/** Matches a dimension of the view to a given dimension of another view with an offset. */
|
||||||
|
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset;
|
||||||
|
|
||||||
|
/** Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
/** Matches a dimension of the view to a multiple of a given dimension of another view. */
|
||||||
|
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier;
|
||||||
|
|
||||||
|
/** Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Set Dimensions
|
||||||
|
|
||||||
|
/** Sets the view to a specific size. */
|
||||||
|
- (NSArray *)autoSetDimensionsToSize:(CGSize)size;
|
||||||
|
|
||||||
|
/** Sets the given dimension of the view to a specific size. */
|
||||||
|
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size;
|
||||||
|
|
||||||
|
/** Sets the given dimension of the view to a specific size as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Set Content Compression Resistance & Hugging
|
||||||
|
|
||||||
|
/** Sets the priority of content compression resistance for an axis.
|
||||||
|
NOTE: This method must be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */
|
||||||
|
- (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis;
|
||||||
|
|
||||||
|
/** Sets the priority of content hugging for an axis.
|
||||||
|
NOTE: This method must be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */
|
||||||
|
- (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Constrain Any Attributes
|
||||||
|
|
||||||
|
/** Constrains an attribute of the view to a given attribute of another view. */
|
||||||
|
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView;
|
||||||
|
|
||||||
|
/** Constrains an attribute of the view to a given attribute of another view with an offset. */
|
||||||
|
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset;
|
||||||
|
|
||||||
|
/** Constrains an attribute of the view to a given attribute of another view with an offset as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
/** Constrains an attribute of the view to a given attribute of another view with a multiplier. */
|
||||||
|
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier;
|
||||||
|
|
||||||
|
/** Constrains an attribute of the view to a given attribute of another view with a multiplier as a maximum or minimum. */
|
||||||
|
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Pin to Layout Guides (iOS only)
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
|
||||||
|
/** Pins the top edge of the view to the top layout guide of the given view controller with an inset. Available on iOS only. */
|
||||||
|
- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset;
|
||||||
|
|
||||||
|
/** Pins the top edge of the view to the top layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */
|
||||||
|
- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
/** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset. Available on iOS only. */
|
||||||
|
- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset;
|
||||||
|
|
||||||
|
/** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */
|
||||||
|
- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation;
|
||||||
|
|
||||||
|
#endif /* TARGET_OS_IPHONE */
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark Deprecated Methods
|
||||||
|
|
||||||
|
/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints.
|
||||||
|
Removes all explicit constraints that affect the view.
|
||||||
|
WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method.
|
||||||
|
NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */
|
||||||
|
- (void)autoRemoveConstraintsAffectingView __attribute__((deprecated));
|
||||||
|
|
||||||
|
/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints.
|
||||||
|
Removes all constraints that affect the view, optionally including implicit constraints.
|
||||||
|
WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method.
|
||||||
|
NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */
|
||||||
|
- (void)autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints __attribute__((deprecated));
|
||||||
|
|
||||||
|
/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints.
|
||||||
|
Recursively removes all explicit constraints that affect the view and its subviews.
|
||||||
|
WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method.
|
||||||
|
NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */
|
||||||
|
- (void)autoRemoveConstraintsAffectingViewAndSubviews __attribute__((deprecated));
|
||||||
|
|
||||||
|
/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints.
|
||||||
|
Recursively removes all constraints from the view and its subviews, optionally including implicit constraints.
|
||||||
|
WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method.
|
||||||
|
NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */
|
||||||
|
- (void)autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints __attribute__((deprecated));
|
||||||
|
|
||||||
|
@end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user