Browse Source

iOS Snapshot tests (#6081)

Add snapshot tests
Yogev Ben David 4 years ago
parent
commit
95290ed1ee
No account linked to committer's email address
36 changed files with 618 additions and 47 deletions
  1. 1
    0
      package.json
  2. 7
    1
      playground/ios/NavigationTests/RNNTestRootViewCreator.m
  3. 6
    0
      playground/ios/Podfile
  4. 8
    4
      playground/ios/Podfile.lock
  5. 1
    1
      playground/ios/SnapshotTests/Info.plist
  6. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_pop@2x.png
  7. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_push@2x.png
  8. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_root@2x.png
  9. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_pop@2x.png
  10. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_push@2x.png
  11. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_root@2x.png
  12. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_pop@2x.png
  13. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_push@2x.png
  14. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_root@2x.png
  15. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_pop@2x.png
  16. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_push@2x.png
  17. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_root@2x.png
  18. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_pop@2x.png
  19. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_push@2x.png
  20. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_root@2x.png
  21. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_pop@2x.png
  22. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_push@2x.png
  23. BIN
      playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_root@2x.png
  24. 73
    0
      playground/ios/SnapshotTests/StackOptionsTest.m
  25. 8
    0
      playground/ios/SnapshotTests/Utils/CommandsHandlerCreator.h
  26. 38
    0
      playground/ios/SnapshotTests/Utils/CommandsHandlerCreator.m
  27. 11
    0
      playground/ios/SnapshotTests/Utils/LayoutCreator.h
  28. 37
    0
      playground/ios/SnapshotTests/Utils/LayoutCreator.m
  29. 264
    0
      playground/ios/playground.xcodeproj/project.pbxproj
  30. 92
    0
      playground/ios/playground.xcodeproj/xcshareddata/xcschemes/SnapshotTests.xcscheme
  31. 7
    0
      playground/ios/playground/TestingAppDelegate.h
  32. 11
    0
      playground/ios/playground/TestingAppDelegate.m
  33. 2
    1
      playground/ios/playground/main.m
  34. 0
    39
      playground/ios/playgroundTests/playgroundTests.m
  35. 1
    1
      scripts/test-all.js
  36. 51
    0
      scripts/test-snapshot.js

+ 1
- 0
package.json View File

@@ -32,6 +32,7 @@
32 32
     "test-js": "node ./scripts/test-js",
33 33
     "pod-install": "pod install --project-directory=playground/ios",
34 34
     "test-unit-ios": "node ./scripts/test-unit --ios",
35
+    "test-snapshot-ios": "node ./scripts/test-snapshot --ios",
35 36
     "test-unit-android": "node ./scripts/test-unit --android",
36 37
     "pretest-e2e-android": "npm run build",
37 38
     "test-e2e-android": "node ./scripts/test-e2e --android",

+ 7
- 1
playground/ios/NavigationTests/RNNTestRootViewCreator.m View File

@@ -3,8 +3,14 @@
3 3
 @implementation RNNTestRootViewCreator
4 4
 
5 5
 - (RNNReactView *)createRootView:(NSString *)name rootViewId:(NSString *)rootViewId ofType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
6
-	UIView *view = [[UIView alloc] init];
6
+	UIView *view = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
7
+	UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
8
+	label.textAlignment = NSTextAlignmentCenter;
9
+	label.center = [view convertPoint:view.center fromView:view.superview];;
10
+	label.text = rootViewId;
11
+	[view addSubview:label];
7 12
 	view.tag = [rootViewId intValue];
13
+	view.backgroundColor = UIColor.redColor;
8 14
 	return view;
9 15
 }
10 16
 

+ 6
- 0
playground/ios/Podfile View File

@@ -54,3 +54,9 @@ target 'NavigationIOS12Tests' do
54 54
   pod 'OCMock'
55 55
 end
56 56
 
57
+target 'SnapshotTests' do
58
+  all_pods
59
+  pod 'OCMock'
60
+  use_frameworks!
61
+  pod 'iOSSnapshotTestCase/Core'
62
+end

+ 8
- 4
playground/ios/Podfile.lock View File

@@ -19,6 +19,7 @@ PODS:
19 19
     - DoubleConversion
20 20
     - glog
21 21
   - glog (0.3.5)
22
+  - iOSSnapshotTestCase/Core (6.2.0)
22 23
   - OCMock (3.5)
23 24
   - RCTRequired (0.61.5)
24 25
   - RCTTypeSafety (0.61.5):
@@ -220,7 +221,7 @@ PODS:
220 221
     - ReactCommon/jscallinvoker (= 0.61.5)
221 222
   - ReactNativeKeyboardTrackingView (5.6.1):
222 223
     - React
223
-  - ReactNativeNavigation (6.0.1):
224
+  - ReactNativeNavigation (6.3.1):
224 225
     - React
225 226
     - React-RCTImage
226 227
     - React-RCTText
@@ -232,6 +233,7 @@ DEPENDENCIES:
232 233
   - FBReactNativeSpec (from `../../node_modules/react-native/Libraries/FBReactNativeSpec`)
233 234
   - Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
234 235
   - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
236
+  - iOSSnapshotTestCase/Core
235 237
   - OCMock
236 238
   - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
237 239
   - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
@@ -262,6 +264,7 @@ DEPENDENCIES:
262 264
 SPEC REPOS:
263 265
   trunk:
264 266
     - boost-for-react-native
267
+    - iOSSnapshotTestCase
265 268
     - OCMock
266 269
 
267 270
 EXTERNAL SOURCES:
@@ -327,6 +330,7 @@ SPEC CHECKSUMS:
327 330
   FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
328 331
   Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
329 332
   glog: 1f3da668190260b06b429bb211bfbee5cd790c28
333
+  iOSSnapshotTestCase: 9ab44cb5aa62b84d31847f40680112e15ec579a6
330 334
   OCMock: 4ab4577fc941af31f4a0398f6e7e230cf21fc72a
331 335
   RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
332 336
   RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
@@ -348,9 +352,9 @@ SPEC CHECKSUMS:
348 352
   React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
349 353
   ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
350 354
   ReactNativeKeyboardTrackingView: a240a6a0dba852bb107109a7ec7e98b884055977
351
-  ReactNativeNavigation: 33657becf06c9c3a805ecb50dce8010fb887a1bb
355
+  ReactNativeNavigation: d9bb71088ef37aa6af58f3172f890a1ae08861d6
352 356
   Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
353 357
 
354
-PODFILE CHECKSUM: 781f49751a12b13af3e83d5dfc4b122aa5770543
358
+PODFILE CHECKSUM: 480983e790dd4e9f99b1673fbb65606d9fe8ce71
355 359
 
356
-COCOAPODS: 1.8.4
360
+COCOAPODS: 1.9.1

playground/ios/playgroundTests/Info.plist → playground/ios/SnapshotTests/Info.plist View File

@@ -13,7 +13,7 @@
13 13
 	<key>CFBundleName</key>
14 14
 	<string>$(PRODUCT_NAME)</string>
15 15
 	<key>CFBundlePackageType</key>
16
-	<string>BNDL</string>
16
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
17 17
 	<key>CFBundleShortVersionString</key>
18 18
 	<string>1.0</string>
19 19
 	<key>CFBundleVersion</key>

BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_opaque_background_root@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_tansparent_background_root@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_change_root@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_title_font_root@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_translucent_background_root@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_pop@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_push@2x.png View File


BIN
playground/ios/SnapshotTests/ReferenceImages_64/StackOptionsTest/testStack_topBar_visibility_root@2x.png View File


+ 73
- 0
playground/ios/SnapshotTests/StackOptionsTest.m View File

@@ -0,0 +1,73 @@
1
+#import <XCTest/XCTest.h>
2
+#import "LayoutCreator.h"
3
+#import "CommandsHandlerCreator.h"
4
+#import <FBSnapshotTestCase/FBSnapshotTestCase.h>
5
+
6
+@interface StackOptionsTest : FBSnapshotTestCase
7
+@property (nonatomic, strong) RNNCommandsHandler* commandsHandler;
8
+@property (nonatomic, strong) UIWindow* window;
9
+@end
10
+
11
+@implementation StackOptionsTest
12
+
13
+- (void)setUp {
14
+	[super setUp];
15
+	_window = [[[UIApplication sharedApplication] delegate] window];
16
+	_commandsHandler = [CommandsHandlerCreator createWithWindow:_window];
17
+	self.usesDrawViewHierarchyInRect = YES;
18
+	
19
+//	Uncomment next line to record new snapshots
20
+//	self.recordMode = YES;
21
+}
22
+
23
+- (void)tearDown {
24
+	[super tearDown];
25
+	_window.rootViewController = nil;
26
+}
27
+
28
+#define RNNStackFlow(NAME, FIRST, SECOND, ...)\
29
+[self setRoot:[LayoutCreator component:@"FirstComponent" options:FIRST] testName:@#NAME]; \
30
+[self push:[LayoutCreator component:@"SecondComponent" options:SECOND] testName:@#NAME]; \
31
+[self pop:@"SecondComponent" testName:@#NAME]; \
32
+
33
+
34
+- (void)testStack_topBar {
35
+	RNNStackFlow(opaque background, @{@"topBar": @{@"background": @{@"color": @(0xFFFF00FF)}}}, @{@"topBar": @{@"background": @{@"color": @(0xFFFF0000)}}});
36
+	RNNStackFlow(tansparent background, @{@"topBar": @{@"background": @{@"color": @(0x00FFFFFF)}}}, @{@"topBar": @{@"background": @{@"color": @(0xFFFF0000)}}});
37
+	RNNStackFlow(translucent background, @{@"topBar": @{@"background": @{@"translucent": @(1)}}}, @{@"topBar": @{@"background": @{@"translucent": @(0)}}});
38
+	RNNStackFlow(title change, @{@"topBar": @{@"title": @{@"text": @"First Component"}}}, @{@"topBar": @{@"title": @{@"text": @"Second Component"}}});
39
+	RNNStackFlow(visibility, @{@"topBar": @{@"visible": @(0)}}, @{@"topBar": @{@"visible": @(1)}});
40
+	RNNStackFlow(title font, @{@"topBar": @{@"title": @{@"text": @"First Component"}}}, (@{@"topBar": @{@"title": @{@"text": @"Second Component", @"fontFamily": @"Arial", @"color": @(0xFFFF00FF), @"fontSize": @(15)}}}));
41
+}
42
+
43
+- (void)setRoot:(NSDictionary *)firstComponent testName:(NSString *)testName {
44
+	NSDictionary* root = [LayoutCreator stack:@{} children:@[firstComponent]];
45
+	NSString* rootTestName = [NSString stringWithFormat:@"%@_root", testName];
46
+	[_commandsHandler setRoot:@{@"root": root}
47
+					commandId:@"SetRoot"
48
+				   completion:^{}];
49
+	FBSnapshotVerifyView(_window, rootTestName);
50
+}
51
+
52
+- (void)push:(NSDictionary *)secondComponent testName:(NSString *)testName {
53
+	NSString* pushTestName = [NSString stringWithFormat:@"%@_push", testName];
54
+	[_commandsHandler push:@"FirstComponent"
55
+				 commandId:@"push"
56
+					layout:secondComponent
57
+				completion:^{}
58
+				 rejection:^(NSString *code, NSString *message, NSError *error) {}];
59
+	FBSnapshotVerifyView(_window, pushTestName);
60
+}
61
+
62
+- (void)pop:(NSString *)componentId testName:(NSString *)testName {
63
+	NSString* popTestName = [NSString stringWithFormat:@"%@_pop", testName];
64
+	[_commandsHandler pop:componentId
65
+				commandId:@"pop"
66
+			 mergeOptions:@{}
67
+			   completion:^{}
68
+				rejection:^(NSString *code, NSString *message, NSError *error) {}];
69
+	FBSnapshotVerifyView(_window, popTestName);
70
+}
71
+
72
+
73
+@end

+ 8
- 0
playground/ios/SnapshotTests/Utils/CommandsHandlerCreator.h View File

@@ -0,0 +1,8 @@
1
+#import <Foundation/Foundation.h>
2
+#import <ReactNativeNavigation/RNNCommandsHandler.h>
3
+
4
+@interface CommandsHandlerCreator : NSObject
5
+
6
++ (RNNCommandsHandler *)createWithWindow:(UIWindow *)window;
7
+
8
+@end

+ 38
- 0
playground/ios/SnapshotTests/Utils/CommandsHandlerCreator.m View File

@@ -0,0 +1,38 @@
1
+#import "CommandsHandlerCreator.h"
2
+#import "RNNTestRootViewCreator.h"
3
+#import <ReactNativeNavigation/RNNEventEmitter.h>
4
+#import <ReactNativeNavigation/RNNOverlayManager.h>
5
+#import <ReactNativeNavigation/RNNModalManager.h>
6
+#import <ReactNativeNavigation/RNNControllerFactory.h>
7
+
8
+@implementation CommandsHandlerCreator
9
+
10
++ (RNNCommandsHandler *)createWithWindow:(UIWindow *)window {
11
+	RNNTestRootViewCreator* creator = [RNNTestRootViewCreator new];
12
+	RNNEventEmitter* eventEmmiter = [RNNEventEmitter new];
13
+	RNNOverlayManager* overlayManager = [RNNOverlayManager new];
14
+	RNNModalManager* modalManager = [RNNModalManager new];
15
+	RNNControllerFactory* controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:creator eventEmitter:eventEmmiter store:nil componentRegistry:nil andBridge:nil bottomTabsAttachModeFactory:[BottomTabsAttachModeFactory new]];
16
+	RNNCommandsHandler* commandsHandler = [[RNNCommandsHandler alloc] initWithControllerFactory:controllerFactory eventEmitter:eventEmmiter modalManager:modalManager overlayManager:overlayManager mainWindow:window];
17
+	[commandsHandler setReadyToReceiveCommands:YES];
18
+	[commandsHandler setDefaultOptions:@{
19
+		@"animations": @{
20
+				@"push": @{
21
+						@"enabled": @(0)
22
+				},
23
+				@"pop": @{
24
+						@"enabled": @(0)
25
+				}
26
+		},
27
+		@"topBar": @{
28
+				@"drawBehind": @(1)
29
+		},
30
+		@"layout": @{
31
+				@"componentBackgroundColor": @(0xFF00FF00)
32
+		}
33
+	} completion:^{}];
34
+	
35
+	return commandsHandler;
36
+}
37
+
38
+@end

+ 11
- 0
playground/ios/SnapshotTests/Utils/LayoutCreator.h View File

@@ -0,0 +1,11 @@
1
+#import <Foundation/Foundation.h>
2
+
3
+@interface LayoutCreator : NSObject
4
+
5
++ (NSDictionary *)component:(NSString *)componentId options:(NSDictionary *)options;
6
+
7
++ (NSDictionary *)parentWithID:(NSString *)componentId type:(NSString *)type options:(NSDictionary *)options children:(NSArray<NSDictionary *> *)children;
8
+
9
++ (NSDictionary *)stack:(NSDictionary *)options children:(NSArray<NSDictionary *> *)children;
10
+
11
+@end

+ 37
- 0
playground/ios/SnapshotTests/Utils/LayoutCreator.m View File

@@ -0,0 +1,37 @@
1
+#import "LayoutCreator.h"
2
+
3
+@implementation LayoutCreator
4
+
5
++ (NSDictionary *)component:(NSString *)componentId options:(NSDictionary *)options {
6
+	return @{
7
+		@"type": @"Component",
8
+		@"id": componentId,
9
+		@"data": @{
10
+				@"options": options
11
+		}
12
+	};
13
+}
14
+
15
++ (NSDictionary *)parentWithID:(NSString *)componentId type:(NSString *)type options:(NSDictionary *)options children:(NSArray<NSDictionary *> *)children {
16
+	return @{
17
+		@"type": type,
18
+		@"id": componentId,
19
+		@"data": @{
20
+				@"options": options
21
+		},
22
+		@"children": children
23
+	};
24
+}
25
+
26
++ (NSDictionary *)stack:(NSDictionary *)options children:(NSArray<NSDictionary *> *)children {
27
+	return @{
28
+		@"type": @"Stack",
29
+		@"id": @"StackID",
30
+		@"data": @{
31
+				@"options": options
32
+		},
33
+		@"children": children
34
+	};
35
+}
36
+
37
+@end

+ 264
- 0
playground/ios/playground.xcodeproj/project.pbxproj View File

@@ -17,6 +17,12 @@
17 17
 		5022EDCE2405524700852BA6 /* RNNBottomTabsAppearancePresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5022EDCB240551EE00852BA6 /* RNNBottomTabsAppearancePresenterTest.m */; };
18 18
 		50451D35204451A900695F00 /* RNNCustomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 50451D34204451A800695F00 /* RNNCustomViewController.m */; };
19 19
 		50647FE323E3196800B92025 /* RNNExternalViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 50647FE223E3196800B92025 /* RNNExternalViewControllerTests.m */; };
20
+		50650A23242FB0F800688104 /* CommandsHandlerCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 50650A22242FB0F800688104 /* CommandsHandlerCreator.m */; };
21
+		5078DF39242BE8AA007B0B4F /* TestingAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5078DF38242BE8AA007B0B4F /* TestingAppDelegate.m */; };
22
+		507C80E5242912AD00F765F7 /* RNNTestRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = E58D263D2385888C003F36BA /* RNNTestRootViewCreator.m */; };
23
+		507C80E7242914C800F765F7 /* StackOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E4888A2427DA4800B11A8E /* StackOptionsTest.m */; };
24
+		507C80E8242A1E6F00F765F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
25
+		507C80EC242BC6FB00F765F7 /* LayoutCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 507C80EB242BC6FB00F765F7 /* LayoutCreator.m */; };
20 26
 		50996C6823AA477400008F89 /* RNNRootViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50996C6723AA477400008F89 /* RNNRootViewControllerTest.m */; };
21 27
 		50996C6923AA487800008F89 /* RNNTestRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = E58D263D2385888C003F36BA /* RNNTestRootViewCreator.m */; };
22 28
 		50BCB27623F1A2B100D6C8E5 /* TopBarAppearancePresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50BCB27523F1A26600D6C8E5 /* TopBarAppearancePresenterTest.m */; };
@@ -25,6 +31,7 @@
25 31
 		50CF233D240695B10098042D /* RNNBottomTabsController+Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 50CF233C240695B10098042D /* RNNBottomTabsController+Helpers.m */; };
26 32
 		67C681D42B662A53F29C19DA /* Pods_NavigationIOS12Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEE0B5D45FD34FBABC6586CF /* Pods_NavigationIOS12Tests.framework */; };
27 33
 		9D204F3DC4FBCD81583BF99F /* Pods_playground.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A3340545EAAF11C1F146864 /* Pods_playground.framework */; };
34
+		B9EA50B19EF52C45E9399616 /* Pods_SnapshotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE0C1AD81D2043249E7FE924 /* Pods_SnapshotTests.framework */; };
28 35
 		E5046080227748EA00212BD8 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E504607F227748EA00212BD8 /* JavaScriptCore.framework */; };
29 36
 		E58D26462385888C003F36BA /* UIViewController+LayoutProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E58D26252385888B003F36BA /* UIViewController+LayoutProtocolTest.m */; };
30 37
 		E58D26472385888C003F36BA /* RNNRootViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E58D26262385888B003F36BA /* RNNRootViewControllerTest.m */; };
@@ -57,6 +64,13 @@
57 64
 /* End PBXBuildFile section */
58 65
 
59 66
 /* Begin PBXContainerItemProxy section */
67
+		507C80DF2429111F00F765F7 /* PBXContainerItemProxy */ = {
68
+			isa = PBXContainerItemProxy;
69
+			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
70
+			proxyType = 1;
71
+			remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
72
+			remoteInfo = playground;
73
+		};
60 74
 		50996C6223AA46DD00008F89 /* PBXContainerItemProxy */ = {
61 75
 			isa = PBXContainerItemProxy;
62 76
 			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@@ -84,6 +98,7 @@
84 98
 		4259AF43A23D928FE78B4A3A /* Pods-NavigationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationTests.debug.xcconfig"; path = "Target Support Files/Pods-NavigationTests/Pods-NavigationTests.debug.xcconfig"; sourceTree = "<group>"; };
85 99
 		4A3340545EAAF11C1F146864 /* Pods_playground.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_playground.framework; sourceTree = BUILT_PRODUCTS_DIR; };
86 100
 		4AE37ACF6BFBAB211EE8E7E9 /* Pods-NavigationIOS12Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationIOS12Tests.release.xcconfig"; path = "Target Support Files/Pods-NavigationIOS12Tests/Pods-NavigationIOS12Tests.release.xcconfig"; sourceTree = "<group>"; };
101
+		4C14E49C47AA48BEDE90A218 /* Pods-SnapshotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SnapshotTests.debug.xcconfig"; path = "Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests.debug.xcconfig"; sourceTree = "<group>"; };
87 102
 		500E9FE62406A4E200C61231 /* BottomTabPresenterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BottomTabPresenterTest.m; sourceTree = "<group>"; };
88 103
 		501C86B7239FE9C400E0B631 /* UIImage+Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+Utils.h"; sourceTree = "<group>"; };
89 104
 		501C86B8239FE9C400E0B631 /* UIImage+Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Utils.m"; sourceTree = "<group>"; };
@@ -93,6 +108,14 @@
93 108
 		50451D33204451A800695F00 /* RNNCustomViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNNCustomViewController.h; path = ../../../lib/ios/RNNCustomViewController.h; sourceTree = "<group>"; };
94 109
 		50451D34204451A800695F00 /* RNNCustomViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNNCustomViewController.m; path = ../../../lib/ios/RNNCustomViewController.m; sourceTree = "<group>"; };
95 110
 		50647FE223E3196800B92025 /* RNNExternalViewControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNExternalViewControllerTests.m; sourceTree = "<group>"; };
111
+		50650A21242FB0F800688104 /* CommandsHandlerCreator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommandsHandlerCreator.h; sourceTree = "<group>"; };
112
+		50650A22242FB0F800688104 /* CommandsHandlerCreator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CommandsHandlerCreator.m; sourceTree = "<group>"; };
113
+		5078DF37242BE8AA007B0B4F /* TestingAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestingAppDelegate.h; sourceTree = "<group>"; };
114
+		5078DF38242BE8AA007B0B4F /* TestingAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestingAppDelegate.m; sourceTree = "<group>"; };
115
+		507C80DA2429111F00F765F7 /* SnapshotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnapshotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
116
+		507C80DE2429111F00F765F7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
117
+		507C80EA242BC6FB00F765F7 /* LayoutCreator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutCreator.h; sourceTree = "<group>"; };
118
+		507C80EB242BC6FB00F765F7 /* LayoutCreator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LayoutCreator.m; sourceTree = "<group>"; };
96 119
 		50996C5D23AA46DD00008F89 /* NavigationIOS12Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NavigationIOS12Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
97 120
 		50996C6123AA46DD00008F89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98 121
 		50996C6723AA477400008F89 /* RNNRootViewControllerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNRootViewControllerTest.m; sourceTree = "<group>"; };
@@ -101,11 +124,13 @@
101 124
 		50C9A8D3240FB9D000BD699F /* RNNComponentViewController+Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RNNComponentViewController+Utils.m"; sourceTree = "<group>"; };
102 125
 		50CF233B240695B10098042D /* RNNBottomTabsController+Helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNNBottomTabsController+Helpers.h"; sourceTree = "<group>"; };
103 126
 		50CF233C240695B10098042D /* RNNBottomTabsController+Helpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RNNBottomTabsController+Helpers.m"; sourceTree = "<group>"; };
127
+		50E4888A2427DA4800B11A8E /* StackOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StackOptionsTest.m; sourceTree = "<group>"; };
104 128
 		7F8E255E2E08F6ECE7DF6FE3 /* Pods-playground.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-playground.release.xcconfig"; path = "Target Support Files/Pods-playground/Pods-playground.release.xcconfig"; sourceTree = "<group>"; };
105 129
 		84E32151E3A71C2B7328BCB4 /* Pods_NavigationTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NavigationTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
106 130
 		B484A10A046B0046B98A76B5 /* Pods-playground.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-playground.debug.xcconfig"; path = "Target Support Files/Pods-playground/Pods-playground.debug.xcconfig"; sourceTree = "<group>"; };
107 131
 		C9E7FB91365E7BEF959ADB5F /* Pods-NavigationIOS12Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationIOS12Tests.debug.xcconfig"; path = "Target Support Files/Pods-NavigationIOS12Tests/Pods-NavigationIOS12Tests.debug.xcconfig"; sourceTree = "<group>"; };
108 132
 		D95A99C17C65D674BA9DF26B /* Pods-NavigationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NavigationTests.release.xcconfig"; path = "Target Support Files/Pods-NavigationTests/Pods-NavigationTests.release.xcconfig"; sourceTree = "<group>"; };
133
+		DC6478E8C795582800285530 /* Pods-SnapshotTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SnapshotTests.release.xcconfig"; path = "Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests.release.xcconfig"; sourceTree = "<group>"; };
109 134
 		DEE0B5D45FD34FBABC6586CF /* Pods_NavigationIOS12Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NavigationIOS12Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
110 135
 		E504607F227748EA00212BD8 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
111 136
 		E58D261B238587F4003F36BA /* NavigationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NavigationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -140,6 +165,7 @@
140 165
 		E58D26422385888C003F36BA /* RNNBasePresenterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNBasePresenterTest.m; sourceTree = "<group>"; };
141 166
 		E58D26432385888C003F36BA /* RNNModalManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNModalManagerTest.m; sourceTree = "<group>"; };
142 167
 		E58D26452385888C003F36BA /* RNNTestNoColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNTestNoColor.m; sourceTree = "<group>"; };
168
+		FE0C1AD81D2043249E7FE924 /* Pods_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
143 169
 /* End PBXFileReference section */
144 170
 
145 171
 /* Begin PBXFrameworksBuildPhase section */
@@ -153,6 +179,14 @@
153 179
 			);
154 180
 			runOnlyForDeploymentPostprocessing = 0;
155 181
 		};
182
+		507C80D72429111F00F765F7 /* Frameworks */ = {
183
+			isa = PBXFrameworksBuildPhase;
184
+			buildActionMask = 2147483647;
185
+			files = (
186
+				B9EA50B19EF52C45E9399616 /* Pods_SnapshotTests.framework in Frameworks */,
187
+			);
188
+			runOnlyForDeploymentPostprocessing = 0;
189
+		};
156 190
 		50996C5A23AA46DD00008F89 /* Frameworks */ = {
157 191
 			isa = PBXFrameworksBuildPhase;
158 192
 			buildActionMask = 2147483647;
@@ -179,6 +213,8 @@
179 213
 				13B07FB01A68108700A75B9A /* AppDelegate.m */,
180 214
 				50451D33204451A800695F00 /* RNNCustomViewController.h */,
181 215
 				50451D34204451A800695F00 /* RNNCustomViewController.m */,
216
+				5078DF37242BE8AA007B0B4F /* TestingAppDelegate.h */,
217
+				5078DF38242BE8AA007B0B4F /* TestingAppDelegate.m */,
182 218
 				13B07FB51A68108700A75B9A /* Images.xcassets */,
183 219
 				13B07FB61A68108700A75B9A /* Info.plist */,
184 220
 				13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
@@ -196,10 +232,33 @@
196 232
 				D95A99C17C65D674BA9DF26B /* Pods-NavigationTests.release.xcconfig */,
197 233
 				C9E7FB91365E7BEF959ADB5F /* Pods-NavigationIOS12Tests.debug.xcconfig */,
198 234
 				4AE37ACF6BFBAB211EE8E7E9 /* Pods-NavigationIOS12Tests.release.xcconfig */,
235
+				4C14E49C47AA48BEDE90A218 /* Pods-SnapshotTests.debug.xcconfig */,
236
+				DC6478E8C795582800285530 /* Pods-SnapshotTests.release.xcconfig */,
199 237
 			);
200 238
 			path = Pods;
201 239
 			sourceTree = "<group>";
202 240
 		};
241
+		507C80DB2429111F00F765F7 /* SnapshotTests */ = {
242
+			isa = PBXGroup;
243
+			children = (
244
+				507C80E9242BC6E200F765F7 /* Utils */,
245
+				50E4888A2427DA4800B11A8E /* StackOptionsTest.m */,
246
+				507C80DE2429111F00F765F7 /* Info.plist */,
247
+			);
248
+			path = SnapshotTests;
249
+			sourceTree = "<group>";
250
+		};
251
+		507C80E9242BC6E200F765F7 /* Utils */ = {
252
+			isa = PBXGroup;
253
+			children = (
254
+				507C80EA242BC6FB00F765F7 /* LayoutCreator.h */,
255
+				507C80EB242BC6FB00F765F7 /* LayoutCreator.m */,
256
+				50650A21242FB0F800688104 /* CommandsHandlerCreator.h */,
257
+				50650A22242FB0F800688104 /* CommandsHandlerCreator.m */,
258
+			);
259
+			path = Utils;
260
+			sourceTree = "<group>";
261
+		};
203 262
 		50996C5E23AA46DD00008F89 /* NavigationIOS12Tests */ = {
204 263
 			isa = PBXGroup;
205 264
 			children = (
@@ -224,6 +283,7 @@
224 283
 				832341AE1AAA6A7D00B99B32 /* Libraries */,
225 284
 				E58D261C238587F4003F36BA /* NavigationTests */,
226 285
 				50996C5E23AA46DD00008F89 /* NavigationIOS12Tests */,
286
+				507C80DB2429111F00F765F7 /* SnapshotTests */,
227 287
 				83CBBA001A601CBA00E9B192 /* Products */,
228 288
 				E504607E227748E900212BD8 /* Frameworks */,
229 289
 				4620213833CA57C55B227B23 /* Pods */,
@@ -239,6 +299,7 @@
239 299
 				13B07F961A680F5B00A75B9A /* playground.app */,
240 300
 				E58D261B238587F4003F36BA /* NavigationTests.xctest */,
241 301
 				50996C5D23AA46DD00008F89 /* NavigationIOS12Tests.xctest */,
302
+				507C80DA2429111F00F765F7 /* SnapshotTests.xctest */,
242 303
 			);
243 304
 			name = Products;
244 305
 			sourceTree = "<group>";
@@ -252,6 +313,7 @@
252 313
 				4A3340545EAAF11C1F146864 /* Pods_playground.framework */,
253 314
 				84E32151E3A71C2B7328BCB4 /* Pods_NavigationTests.framework */,
254 315
 				DEE0B5D45FD34FBABC6586CF /* Pods_NavigationIOS12Tests.framework */,
316
+				FE0C1AD81D2043249E7FE924 /* Pods_SnapshotTests.framework */,
255 317
 			);
256 318
 			name = Frameworks;
257 319
 			sourceTree = "<group>";
@@ -342,6 +404,26 @@
342 404
 			productReference = 13B07F961A680F5B00A75B9A /* playground.app */;
343 405
 			productType = "com.apple.product-type.application";
344 406
 		};
407
+		507C80D92429111F00F765F7 /* SnapshotTests */ = {
408
+			isa = PBXNativeTarget;
409
+			buildConfigurationList = 507C80E12429111F00F765F7 /* Build configuration list for PBXNativeTarget "SnapshotTests" */;
410
+			buildPhases = (
411
+				59AF7E19C5E8CA48E2ADBB81 /* [CP] Check Pods Manifest.lock */,
412
+				507C80D62429111F00F765F7 /* Sources */,
413
+				507C80D72429111F00F765F7 /* Frameworks */,
414
+				507C80D82429111F00F765F7 /* Resources */,
415
+				1093A79180788A805F6D391C /* [CP] Embed Pods Frameworks */,
416
+			);
417
+			buildRules = (
418
+			);
419
+			dependencies = (
420
+				507C80E02429111F00F765F7 /* PBXTargetDependency */,
421
+			);
422
+			name = SnapshotTests;
423
+			productName = SnapshotTests;
424
+			productReference = 507C80DA2429111F00F765F7 /* SnapshotTests.xctest */;
425
+			productType = "com.apple.product-type.bundle.unit-test";
426
+		};
345 427
 		50996C5C23AA46DD00008F89 /* NavigationIOS12Tests */ = {
346 428
 			isa = PBXNativeTarget;
347 429
 			buildConfigurationList = 50996C6623AA46DD00008F89 /* Build configuration list for PBXNativeTarget "NavigationIOS12Tests" */;
@@ -396,6 +478,11 @@
396 478
 						DevelopmentTeam = XPHGA2FMQQ;
397 479
 						ProvisioningStyle = Automatic;
398 480
 					};
481
+					507C80D92429111F00F765F7 = {
482
+						CreatedOnToolsVersion = 11.2.1;
483
+						ProvisioningStyle = Automatic;
484
+						TestTargetID = 13B07F861A680F5B00A75B9A;
485
+					};
399 486
 					50996C5C23AA46DD00008F89 = {
400 487
 						CreatedOnToolsVersion = 11.2.1;
401 488
 						ProvisioningStyle = Automatic;
@@ -426,6 +513,7 @@
426 513
 				13B07F861A680F5B00A75B9A /* playground */,
427 514
 				E58D261A238587F4003F36BA /* NavigationTests */,
428 515
 				50996C5C23AA46DD00008F89 /* NavigationIOS12Tests */,
516
+				507C80D92429111F00F765F7 /* SnapshotTests */,
429 517
 			);
430 518
 		};
431 519
 /* End PBXProject section */
@@ -440,6 +528,13 @@
440 528
 			);
441 529
 			runOnlyForDeploymentPostprocessing = 0;
442 530
 		};
531
+		507C80D82429111F00F765F7 /* Resources */ = {
532
+			isa = PBXResourcesBuildPhase;
533
+			buildActionMask = 2147483647;
534
+			files = (
535
+			);
536
+			runOnlyForDeploymentPostprocessing = 0;
537
+		};
443 538
 		50996C5B23AA46DD00008F89 /* Resources */ = {
444 539
 			isa = PBXResourcesBuildPhase;
445 540
 			buildActionMask = 2147483647;
@@ -493,6 +588,96 @@
493 588
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
494 589
 			showEnvVarsInLog = 0;
495 590
 		};
591
+		1093A79180788A805F6D391C /* [CP] Embed Pods Frameworks */ = {
592
+			isa = PBXShellScriptBuildPhase;
593
+			buildActionMask = 2147483647;
594
+			files = (
595
+			);
596
+			inputPaths = (
597
+				"${PODS_ROOT}/Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests-frameworks.sh",
598
+				"${BUILT_PRODUCTS_DIR}/DoubleConversion/DoubleConversion.framework",
599
+				"${BUILT_PRODUCTS_DIR}/FBReactNativeSpec/FBReactNativeSpec.framework",
600
+				"${BUILT_PRODUCTS_DIR}/Folly/folly.framework",
601
+				"${BUILT_PRODUCTS_DIR}/RCTTypeSafety/RCTTypeSafety.framework",
602
+				"${BUILT_PRODUCTS_DIR}/React-Core/React.framework",
603
+				"${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework",
604
+				"${BUILT_PRODUCTS_DIR}/React-RCTActionSheet/RCTActionSheet.framework",
605
+				"${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework",
606
+				"${BUILT_PRODUCTS_DIR}/React-RCTBlob/RCTBlob.framework",
607
+				"${BUILT_PRODUCTS_DIR}/React-RCTImage/RCTImage.framework",
608
+				"${BUILT_PRODUCTS_DIR}/React-RCTLinking/RCTLinking.framework",
609
+				"${BUILT_PRODUCTS_DIR}/React-RCTNetwork/RCTNetwork.framework",
610
+				"${BUILT_PRODUCTS_DIR}/React-RCTSettings/RCTSettings.framework",
611
+				"${BUILT_PRODUCTS_DIR}/React-RCTText/RCTText.framework",
612
+				"${BUILT_PRODUCTS_DIR}/React-RCTVibration/RCTVibration.framework",
613
+				"${BUILT_PRODUCTS_DIR}/React-cxxreact/cxxreact.framework",
614
+				"${BUILT_PRODUCTS_DIR}/React-jsi/jsi.framework",
615
+				"${BUILT_PRODUCTS_DIR}/React-jsiexecutor/jsireact.framework",
616
+				"${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework",
617
+				"${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework",
618
+				"${BUILT_PRODUCTS_DIR}/ReactNativeKeyboardTrackingView/ReactNativeKeyboardTrackingView.framework",
619
+				"${BUILT_PRODUCTS_DIR}/ReactNativeNavigation/ReactNativeNavigation.framework",
620
+				"${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework",
621
+				"${BUILT_PRODUCTS_DIR}/glog/glog.framework",
622
+				"${BUILT_PRODUCTS_DIR}/OCMock/OCMock.framework",
623
+				"${BUILT_PRODUCTS_DIR}/iOSSnapshotTestCase/FBSnapshotTestCase.framework",
624
+			);
625
+			name = "[CP] Embed Pods Frameworks";
626
+			outputPaths = (
627
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DoubleConversion.framework",
628
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBReactNativeSpec.framework",
629
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/folly.framework",
630
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTTypeSafety.framework",
631
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
632
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework",
633
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTActionSheet.framework",
634
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework",
635
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTBlob.framework",
636
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTImage.framework",
637
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTLinking.framework",
638
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTNetwork.framework",
639
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTSettings.framework",
640
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTText.framework",
641
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTVibration.framework",
642
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cxxreact.framework",
643
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsi.framework",
644
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsireact.framework",
645
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework",
646
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework",
647
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeKeyboardTrackingView.framework",
648
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeNavigation.framework",
649
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework",
650
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
651
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OCMock.framework",
652
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSnapshotTestCase.framework",
653
+			);
654
+			runOnlyForDeploymentPostprocessing = 0;
655
+			shellPath = /bin/sh;
656
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests-frameworks.sh\"\n";
657
+			showEnvVarsInLog = 0;
658
+		};
659
+		59AF7E19C5E8CA48E2ADBB81 /* [CP] Check Pods Manifest.lock */ = {
660
+			isa = PBXShellScriptBuildPhase;
661
+			buildActionMask = 2147483647;
662
+			files = (
663
+			);
664
+			inputFileListPaths = (
665
+			);
666
+			inputPaths = (
667
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
668
+				"${PODS_ROOT}/Manifest.lock",
669
+			);
670
+			name = "[CP] Check Pods Manifest.lock";
671
+			outputFileListPaths = (
672
+			);
673
+			outputPaths = (
674
+				"$(DERIVED_FILE_DIR)/Pods-SnapshotTests-checkManifestLockResult.txt",
675
+			);
676
+			runOnlyForDeploymentPostprocessing = 0;
677
+			shellPath = /bin/sh;
678
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
679
+			showEnvVarsInLog = 0;
680
+		};
496 681
 		7019F906475029978A0A826C /* [CP] Check Pods Manifest.lock */ = {
497 682
 			isa = PBXShellScriptBuildPhase;
498 683
 			buildActionMask = 2147483647;
@@ -741,11 +926,24 @@
741 926
 			buildActionMask = 2147483647;
742 927
 			files = (
743 928
 				50451D35204451A900695F00 /* RNNCustomViewController.m in Sources */,
929
+				5078DF39242BE8AA007B0B4F /* TestingAppDelegate.m in Sources */,
744 930
 				13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
745 931
 				13B07FC11A68108700A75B9A /* main.m in Sources */,
746 932
 			);
747 933
 			runOnlyForDeploymentPostprocessing = 0;
748 934
 		};
935
+		507C80D62429111F00F765F7 /* Sources */ = {
936
+			isa = PBXSourcesBuildPhase;
937
+			buildActionMask = 2147483647;
938
+			files = (
939
+				507C80E8242A1E6F00F765F7 /* AppDelegate.m in Sources */,
940
+				507C80EC242BC6FB00F765F7 /* LayoutCreator.m in Sources */,
941
+				507C80E7242914C800F765F7 /* StackOptionsTest.m in Sources */,
942
+				507C80E5242912AD00F765F7 /* RNNTestRootViewCreator.m in Sources */,
943
+				50650A23242FB0F800688104 /* CommandsHandlerCreator.m in Sources */,
944
+			);
945
+			runOnlyForDeploymentPostprocessing = 0;
946
+		};
749 947
 		50996C5923AA46DD00008F89 /* Sources */ = {
750 948
 			isa = PBXSourcesBuildPhase;
751 949
 			buildActionMask = 2147483647;
@@ -800,6 +998,11 @@
800 998
 /* End PBXSourcesBuildPhase section */
801 999
 
802 1000
 /* Begin PBXTargetDependency section */
1001
+		507C80E02429111F00F765F7 /* PBXTargetDependency */ = {
1002
+			isa = PBXTargetDependency;
1003
+			target = 13B07F861A680F5B00A75B9A /* playground */;
1004
+			targetProxy = 507C80DF2429111F00F765F7 /* PBXContainerItemProxy */;
1005
+		};
803 1006
 		50996C6323AA46DD00008F89 /* PBXTargetDependency */ = {
804 1007
 			isa = PBXTargetDependency;
805 1008
 			target = 13B07F861A680F5B00A75B9A /* playground */;
@@ -873,6 +1076,58 @@
873 1076
 			};
874 1077
 			name = Release;
875 1078
 		};
1079
+		507C80E22429111F00F765F7 /* Debug */ = {
1080
+			isa = XCBuildConfiguration;
1081
+			baseConfigurationReference = 4C14E49C47AA48BEDE90A218 /* Pods-SnapshotTests.debug.xcconfig */;
1082
+			buildSettings = {
1083
+				BUNDLE_LOADER = "$(TEST_HOST)";
1084
+				CLANG_ANALYZER_NONNULL = YES;
1085
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1086
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
1087
+				CLANG_ENABLE_OBJC_WEAK = YES;
1088
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1089
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1090
+				CODE_SIGN_STYLE = Automatic;
1091
+				DEBUG_INFORMATION_FORMAT = dwarf;
1092
+				GCC_C_LANGUAGE_STANDARD = gnu11;
1093
+				INFOPLIST_FILE = SnapshotTests/Info.plist;
1094
+				IPHONEOS_DEPLOYMENT_TARGET = 13.2;
1095
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1096
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
1097
+				MTL_FAST_MATH = YES;
1098
+				PRODUCT_BUNDLE_IDENTIFIER = rn.SnapshotTests;
1099
+				PRODUCT_NAME = "$(TARGET_NAME)";
1100
+				TARGETED_DEVICE_FAMILY = "1,2";
1101
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/playground.app/playground";
1102
+			};
1103
+			name = Debug;
1104
+		};
1105
+		507C80E32429111F00F765F7 /* Release */ = {
1106
+			isa = XCBuildConfiguration;
1107
+			baseConfigurationReference = DC6478E8C795582800285530 /* Pods-SnapshotTests.release.xcconfig */;
1108
+			buildSettings = {
1109
+				BUNDLE_LOADER = "$(TEST_HOST)";
1110
+				CLANG_ANALYZER_NONNULL = YES;
1111
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1112
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
1113
+				CLANG_ENABLE_OBJC_WEAK = YES;
1114
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1115
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1116
+				CODE_SIGN_STYLE = Automatic;
1117
+				COPY_PHASE_STRIP = NO;
1118
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1119
+				GCC_C_LANGUAGE_STANDARD = gnu11;
1120
+				INFOPLIST_FILE = SnapshotTests/Info.plist;
1121
+				IPHONEOS_DEPLOYMENT_TARGET = 13.2;
1122
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1123
+				MTL_FAST_MATH = YES;
1124
+				PRODUCT_BUNDLE_IDENTIFIER = rn.SnapshotTests;
1125
+				PRODUCT_NAME = "$(TARGET_NAME)";
1126
+				TARGETED_DEVICE_FAMILY = "1,2";
1127
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/playground.app/playground";
1128
+			};
1129
+			name = Release;
1130
+		};
876 1131
 		50996C6423AA46DD00008F89 /* Debug */ = {
877 1132
 			isa = XCBuildConfiguration;
878 1133
 			baseConfigurationReference = C9E7FB91365E7BEF959ADB5F /* Pods-NavigationIOS12Tests.debug.xcconfig */;
@@ -1092,6 +1347,15 @@
1092 1347
 			defaultConfigurationIsVisible = 0;
1093 1348
 			defaultConfigurationName = Debug;
1094 1349
 		};
1350
+		507C80E12429111F00F765F7 /* Build configuration list for PBXNativeTarget "SnapshotTests" */ = {
1351
+			isa = XCConfigurationList;
1352
+			buildConfigurations = (
1353
+				507C80E22429111F00F765F7 /* Debug */,
1354
+				507C80E32429111F00F765F7 /* Release */,
1355
+			);
1356
+			defaultConfigurationIsVisible = 0;
1357
+			defaultConfigurationName = Debug;
1358
+		};
1095 1359
 		50996C6623AA46DD00008F89 /* Build configuration list for PBXNativeTarget "NavigationIOS12Tests" */ = {
1096 1360
 			isa = XCConfigurationList;
1097 1361
 			buildConfigurations = (

+ 92
- 0
playground/ios/playground.xcodeproj/xcshareddata/xcschemes/SnapshotTests.xcscheme View File

@@ -0,0 +1,92 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1120"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+   </BuildAction>
9
+   <TestAction
10
+      buildConfiguration = "Debug"
11
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
12
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13
+      shouldUseLaunchSchemeArgsEnv = "NO">
14
+      <MacroExpansion>
15
+         <BuildableReference
16
+            BuildableIdentifier = "primary"
17
+            BlueprintIdentifier = "507C80D92429111F00F765F7"
18
+            BuildableName = "SnapshotTests.xctest"
19
+            BlueprintName = "SnapshotTests"
20
+            ReferencedContainer = "container:playground.xcodeproj">
21
+         </BuildableReference>
22
+      </MacroExpansion>
23
+      <EnvironmentVariables>
24
+         <EnvironmentVariable
25
+            key = "FB_REFERENCE_IMAGE_DIR"
26
+            value = "$(SOURCE_ROOT)/SnapshotTests/ReferenceImages"
27
+            isEnabled = "YES">
28
+         </EnvironmentVariable>
29
+         <EnvironmentVariable
30
+            key = "TEST_ENABLED"
31
+            value = "YES"
32
+            isEnabled = "YES">
33
+         </EnvironmentVariable>
34
+      </EnvironmentVariables>
35
+      <Testables>
36
+         <TestableReference
37
+            skipped = "NO">
38
+            <BuildableReference
39
+               BuildableIdentifier = "primary"
40
+               BlueprintIdentifier = "507C80D92429111F00F765F7"
41
+               BuildableName = "SnapshotTests.xctest"
42
+               BlueprintName = "SnapshotTests"
43
+               ReferencedContainer = "container:playground.xcodeproj">
44
+            </BuildableReference>
45
+         </TestableReference>
46
+      </Testables>
47
+   </TestAction>
48
+   <LaunchAction
49
+      buildConfiguration = "Debug"
50
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
51
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
52
+      launchStyle = "0"
53
+      useCustomWorkingDirectory = "NO"
54
+      ignoresPersistentStateOnLaunch = "NO"
55
+      debugDocumentVersioning = "YES"
56
+      debugServiceExtension = "internal"
57
+      allowLocationSimulation = "YES">
58
+      <BuildableProductRunnable
59
+         runnableDebuggingMode = "0">
60
+         <BuildableReference
61
+            BuildableIdentifier = "primary"
62
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
63
+            BuildableName = "playground.app"
64
+            BlueprintName = "playground"
65
+            ReferencedContainer = "container:playground.xcodeproj">
66
+         </BuildableReference>
67
+      </BuildableProductRunnable>
68
+   </LaunchAction>
69
+   <ProfileAction
70
+      buildConfiguration = "Release"
71
+      shouldUseLaunchSchemeArgsEnv = "YES"
72
+      savedToolIdentifier = ""
73
+      useCustomWorkingDirectory = "NO"
74
+      debugDocumentVersioning = "YES">
75
+      <MacroExpansion>
76
+         <BuildableReference
77
+            BuildableIdentifier = "primary"
78
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
79
+            BuildableName = "playground.app"
80
+            BlueprintName = "playground"
81
+            ReferencedContainer = "container:playground.xcodeproj">
82
+         </BuildableReference>
83
+      </MacroExpansion>
84
+   </ProfileAction>
85
+   <AnalyzeAction
86
+      buildConfiguration = "Debug">
87
+   </AnalyzeAction>
88
+   <ArchiveAction
89
+      buildConfiguration = "Release"
90
+      revealArchiveInOrganizer = "YES">
91
+   </ArchiveAction>
92
+</Scheme>

+ 7
- 0
playground/ios/playground/TestingAppDelegate.h View File

@@ -0,0 +1,7 @@
1
+#import <UIKit/UIKit.h>
2
+
3
+@interface TestingAppDelegate : UIResponder <UIApplicationDelegate>
4
+
5
+@property (nonatomic, strong) UIWindow *window;
6
+
7
+@end

+ 11
- 0
playground/ios/playground/TestingAppDelegate.m View File

@@ -0,0 +1,11 @@
1
+#import "TestingAppDelegate.h"
2
+
3
+@implementation TestingAppDelegate
4
+
5
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
6
+	_window = [UIWindow new];
7
+	_window.rootViewController = [UIViewController new];
8
+	[_window makeKeyAndVisible];
9
+}
10
+
11
+@end

+ 2
- 1
playground/ios/playground/main.m View File

@@ -10,6 +10,7 @@
10 10
 #import <UIKit/UIKit.h>
11 11
 
12 12
 #import "AppDelegate.h"
13
+#import "TestingAppDelegate.h"
13 14
 
14 15
 static bool isRunningTests()
15 16
 {
@@ -21,7 +22,7 @@ static bool isRunningTests()
21 22
 int main(int argc, char * argv[]) {
22 23
 	@autoreleasepool {
23 24
 		if (isRunningTests()) {
24
-			return UIApplicationMain(argc, argv, nil, nil);
25
+			return UIApplicationMain(argc, argv, nil, NSStringFromClass([TestingAppDelegate class]));
25 26
 		} else {
26 27
 			return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
27 28
 		}

+ 0
- 39
playground/ios/playgroundTests/playgroundTests.m View File

@@ -1,39 +0,0 @@
1
-//
2
-//  playgroundTests.m
3
-//  playgroundTests
4
-//
5
-//  Created by Yogev Ben David on 30/04/2018.
6
-//  Copyright © 2018 Wix. All rights reserved.
7
-//
8
-
9
-#import <XCTest/XCTest.h>
10
-
11
-@interface playgroundTests : XCTestCase
12
-
13
-@end
14
-
15
-@implementation playgroundTests
16
-
17
-- (void)setUp {
18
-    [super setUp];
19
-    // Put setup code here. This method is called before the invocation of each test method in the class.
20
-}
21
-
22
-- (void)tearDown {
23
-    // Put teardown code here. This method is called after the invocation of each test method in the class.
24
-    [super tearDown];
25
-}
26
-
27
-- (void)testExample {
28
-    // This is an example of a functional test case.
29
-    // Use XCTAssert and related functions to verify your tests produce the correct results.
30
-}
31
-
32
-- (void)testPerformanceExample {
33
-    // This is an example of a performance test case.
34
-    [self measureBlock:^{
35
-        // Put the code you want to measure the time of here.
36
-    }];
37
-}
38
-
39
-@end

+ 1
- 1
scripts/test-all.js View File

@@ -5,7 +5,7 @@ async function run() {
5 5
   exec.execSync(`npm run clean`);
6 6
   exec.execSync(`npm run test-js`);
7 7
   exec.execAsyncSilent(`npm run start`);
8
-  await exec.execAsyncAll(`npm run test-unit-android`, `npm run test-unit-ios`);
8
+  await exec.execAsyncAll(`npm run test-unit-android`, `npm run test-unit-ios`, `npm run test-snapshot-ios`);
9 9
   await exec.execAsyncAll(`npm run test-e2e-android`, `npm run test-e2e-ios`);
10 10
   exec.execSync(`npm run clean`);
11 11
   console.log('ALL PASSED!!!');

+ 51
- 0
scripts/test-snapshot.js View File

@@ -0,0 +1,51 @@
1
+const includes = require('lodash/includes');
2
+const exec = require('shell-utils').exec;
3
+
4
+const android = includes(process.argv, '--android');
5
+const release = includes(process.argv, '--release');
6
+
7
+function run() {
8
+  if (android) {
9
+    runAndroidSnapshotTests();
10
+  } else {
11
+    runIosSnapshotTests();
12
+  }
13
+}
14
+
15
+function runAndroidSnapshotTests() {
16
+
17
+}
18
+
19
+function runIosSnapshotTests() {
20
+  exec.execSync('npm run build');
21
+  exec.execSync('npm run pod-install');
22
+  testTarget('SnapshotTests', 'iPhone 11');
23
+}
24
+
25
+function testTarget(scheme, device, OS = 'latest') {
26
+  const conf = release ? `Release` : `Debug`;
27
+  exec.execSync(`cd ./playground/ios &&
28
+  RCT_NO_LAUNCH_PACKAGER=true
29
+  xcodebuild build build-for-testing
30
+  -scheme "${scheme}"
31
+  -workspace playground.xcworkspace
32
+  -sdk iphonesimulator
33
+  -configuration ${conf}
34
+  -derivedDataPath ./DerivedData/playground
35
+  -quiet
36
+  -UseModernBuildSystem=NO
37
+  ONLY_ACTIVE_ARCH=YES`);
38
+
39
+  exec.execSync(`cd ./playground/ios &&
40
+  RCT_NO_LAUNCH_PACKAGER=true
41
+  xcodebuild test-without-building
42
+  -scheme "${scheme}"
43
+  -workspace playground.xcworkspace
44
+  -sdk iphonesimulator
45
+  -configuration ${conf}
46
+  -destination 'platform=iOS Simulator,name=${device},OS=${OS}'
47
+  -derivedDataPath ./DerivedData/playground
48
+  ONLY_ACTIVE_ARCH=YES`);
49
+}
50
+
51
+run();