Browse Source

v2 tdd styles - topBarBackgroundColor, RNNNavigationOptions, style refactor (#1574)

* created RNNNavigationOptions

* created RNNRootViewControllerTest and added a test for the topBarBackgroundColor style

* working

* process navigationOptions colors

* created a test for new RNNRootViewController functionality

* changed RNNRootViewController to init with name, navigationOptions and container id, instead of node

* changed RNNRootViewController to get a new type - RNNavigationOptions

* refactored statusBarHidden test and implementation, all tests pass

* added setup to RNNRootViewControllerTest.m and refactored tests

* added test for title and implemented static title

* minor fixes

* removed redundant eslint config
bogobogo 7 years ago
parent
commit
2632399bfd

+ 5
- 1
lib/ios/RNNControllerFactory.m View File

@@ -4,6 +4,7 @@
4 4
 #import "RNNRootViewController.h"
5 5
 #import "RNNSideMenuController.h"
6 6
 #import "RNNSideMenuChildVC.h"
7
+#import "RNNNavigationOptions.h"
7 8
 
8 9
 
9 10
 @implementation RNNControllerFactory {
@@ -75,7 +76,10 @@
75 76
 }
76 77
 
77 78
 - (RNNRootViewController*)createContainer:(RNNLayoutNode*)node {
78
-	return [[RNNRootViewController alloc] initWithNode:node rootViewCreator:_creator eventEmitter:_eventEmitter];
79
+	NSString* name = node.data[@"name"];
80
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"navigationOptions"]];
81
+	NSString* containerId = node.nodeId;
82
+	return [[RNNRootViewController alloc] initWithName:name withOptions:options withContainerId:containerId rootViewCreator:_creator eventEmitter:_eventEmitter];
79 83
 }
80 84
 
81 85
 - (UINavigationController*)createContainerStack:(RNNLayoutNode*)node {

+ 15
- 0
lib/ios/RNNNavigationOptions.h View File

@@ -0,0 +1,15 @@
1
+#import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+
4
+@interface RNNNavigationOptions : NSObject
5
+
6
+@property (nonatomic, strong) NSNumber* topBarBackgroundColor;
7
+@property (nonatomic, strong) NSNumber* statusBarHidden;
8
+@property (nonatomic, strong) NSString* title;
9
+
10
+-(instancetype)initWithDict:(NSDictionary *)navigationOptions;
11
+
12
+-(void)apply:(UIViewController*)viewController;
13
+
14
+@end
15
+

+ 30
- 0
lib/ios/RNNNavigationOptions.m View File

@@ -0,0 +1,30 @@
1
+#import "RNNNavigationOptions.h"
2
+#import <React/RCTConvert.h>
3
+
4
+@implementation RNNNavigationOptions
5
+
6
+
7
+-(instancetype)initWithDict:(NSDictionary *)navigationOptions {
8
+	self = [super init];
9
+	self.topBarBackgroundColor = [navigationOptions objectForKey:@"topBarBackgroundColor"];
10
+	self.statusBarHidden = [navigationOptions objectForKey:@"statusBarHidden"];
11
+	self.title = [navigationOptions objectForKey:@"title"];
12
+	return self;
13
+}
14
+
15
+-(void)apply:(UIViewController*)viewController{
16
+	if (self.topBarBackgroundColor) {
17
+		UIColor* backgroundColor = [RCTConvert UIColor:self.topBarBackgroundColor];
18
+		viewController.navigationController.navigationBar.barTintColor = backgroundColor;
19
+	}
20
+	if (self.title) {
21
+		viewController.navigationItem.title = self.title;
22
+	}
23
+	
24
+
25
+}
26
+
27
+
28
+
29
+
30
+@end

+ 4
- 1
lib/ios/RNNRootViewController.h View File

@@ -4,10 +4,13 @@
4 4
 #import "RNNLayoutNode.h"
5 5
 #import "RNNRootViewCreator.h"
6 6
 #import "RNNEventEmitter.h"
7
+#import "RNNNavigationOptions.h"
7 8
 
8 9
 @interface RNNRootViewController : UIViewController
9 10
 
10
--(instancetype)initWithNode:(RNNLayoutNode*)node
11
+-(instancetype)initWithName:(NSString*)name
12
+				withOptions:(RNNNavigationOptions*)options
13
+			withContainerId:(NSString*)containerId
11 14
 			rootViewCreator:(id<RNNRootViewCreator>)creator
12 15
 			   eventEmitter:(RNNEventEmitter*)eventEmitter;
13 16
 

+ 13
- 7
lib/ios/RNNRootViewController.m View File

@@ -1,21 +1,25 @@
1 1
 
2 2
 #import "RNNRootViewController.h"
3
+#import <React/RCTConvert.h>
4
+
3 5
 
4 6
 @interface RNNRootViewController()
5 7
 @property (nonatomic, strong) NSString* containerId;
6 8
 @property (nonatomic, strong) NSString* containerName;
7 9
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
8 10
 @property (nonatomic) BOOL _statusBarHidden;
11
+@property (nonatomic, strong) RNNNavigationOptions* navigationOptions;
12
+
9 13
 @end
10 14
 
11 15
 @implementation RNNRootViewController
12 16
 
13
--(instancetype)initWithNode:(RNNLayoutNode*)node rootViewCreator:(id<RNNRootViewCreator>)creator eventEmitter:(RNNEventEmitter*)eventEmitter {
17
+-(instancetype)initWithName:(NSString*)name withOptions:(RNNNavigationOptions*)options withContainerId:(NSString*)containerId rootViewCreator:(id<RNNRootViewCreator>)creator eventEmitter:(RNNEventEmitter*)eventEmitter {
14 18
 	self = [super init];
15
-	self.containerId = node.nodeId;
16
-	self.containerName = node.data[@"name"];
19
+	self.containerId = containerId;
20
+	self.containerName = name;
21
+	self.navigationOptions = options;
17 22
 	self.eventEmitter = eventEmitter;
18
-	
19 23
 	self.view = [creator createRootView:self.containerName rootViewId:self.containerId];
20 24
 	
21 25
 	[[NSNotificationCenter defaultCenter] addObserver:self
@@ -23,14 +27,12 @@
23 27
 												 name:RCTJavaScriptWillStartLoadingNotification
24 28
 											   object:nil];
25 29
 	
26
-	self.navigationItem.title = node.data[@"navigationOptions"][@"title"];
27
-	self._statusBarHidden = [(NSNumber*)node.data[@"navigationOptions"][@"statusBarHidden"] boolValue];
28 30
 	
29 31
 	return self;
30 32
 }
31 33
 
32 34
 - (BOOL)prefersStatusBarHidden {
33
-	return self._statusBarHidden; // || self.navigationController.isNavigationBarHidden;
35
+	return [self.navigationOptions.statusBarHidden boolValue]; // || self.navigationController.isNavigationBarHidden;
34 36
 }
35 37
 
36 38
 
@@ -44,6 +46,10 @@
44 46
 	[self.eventEmitter sendContainerStop:self.containerId];
45 47
 }
46 48
 
49
+-(void)viewWillAppear:(BOOL)animated{
50
+	[super viewWillAppear:animated];
51
+	[self.navigationOptions apply:self];
52
+}
47 53
 /**
48 54
  *	fix for #877, #878
49 55
  */

+ 20
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

@@ -89,6 +89,10 @@
89 89
 		7BEF0D191E437684003E96B0 /* RNNRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BEF0D171E437684003E96B0 /* RNNRootViewController.m */; };
90 90
 		7BEF0D1C1E43771B003E96B0 /* RNNLayoutNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BEF0D1A1E43771B003E96B0 /* RNNLayoutNode.h */; };
91 91
 		7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BEF0D1B1E43771B003E96B0 /* RNNLayoutNode.m */; };
92
+		E83BAD681F2734B500A9F3DD /* RNNNavigationOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */; };
93
+		E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */; };
94
+		E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */; };
95
+		E83BAD7C1F27643000A9F3DD /* RNNTestRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */; };
92 96
 /* End PBXBuildFile section */
93 97
 
94 98
 /* Begin PBXContainerItemProxy section */
@@ -199,6 +203,12 @@
199 203
 		7BEF0D1A1E43771B003E96B0 /* RNNLayoutNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNLayoutNode.h; sourceTree = "<group>"; };
200 204
 		7BEF0D1B1E43771B003E96B0 /* RNNLayoutNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNLayoutNode.m; sourceTree = "<group>"; };
201 205
 		D8AFADBD1BEE6F3F00A4592D /* libReactNativeNavigation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeNavigation.a; sourceTree = BUILT_PRODUCTS_DIR; };
206
+		E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptionsTest.m; sourceTree = "<group>"; };
207
+		E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNNavigationOptions.h; sourceTree = "<group>"; };
208
+		E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptions.m; sourceTree = "<group>"; };
209
+		E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNRootViewControllerTest.m; sourceTree = "<group>"; };
210
+		E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNTestRootViewCreator.h; sourceTree = "<group>"; };
211
+		E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNTestRootViewCreator.m; sourceTree = "<group>"; };
202 212
 /* End PBXFileReference section */
203 213
 
204 214
 /* Begin PBXFrameworksBuildPhase section */
@@ -321,6 +331,8 @@
321 331
 				263905D51E4C94970023D7D3 /* RNNSideMenuController.m */,
322 332
 				263905E41E4CAC950023D7D3 /* RNNSideMenuChildVC.h */,
323 333
 				263905E51E4CAC950023D7D3 /* RNNSideMenuChildVC.m */,
334
+				E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */,
335
+				E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */,
324 336
 			);
325 337
 			name = Controllers;
326 338
 			sourceTree = "<group>";
@@ -334,6 +346,10 @@
334 346
 				7B49FEC91E95098500DEB3EA /* RNNCommandsHandlerTest.m */,
335 347
 				7B49FECA1E95098500DEB3EA /* RNNNavigationStackManagerTest.m */,
336 348
 				7B49FEBF1E95090800DEB3EA /* Info.plist */,
349
+				E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */,
350
+				E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */,
351
+				E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */,
352
+				E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */,
337 353
 			);
338 354
 			path = ReactNativeNavigationTests;
339 355
 			sourceTree = "<group>";
@@ -532,10 +548,13 @@
532 548
 			isa = PBXSourcesBuildPhase;
533 549
 			buildActionMask = 2147483647;
534 550
 			files = (
551
+				E83BAD7C1F27643000A9F3DD /* RNNTestRootViewCreator.m in Sources */,
535 552
 				7B49FECE1E95098500DEB3EA /* RNNCommandsHandlerTest.m in Sources */,
553
+				E83BAD681F2734B500A9F3DD /* RNNNavigationOptionsTest.m in Sources */,
536 554
 				7B49FECF1E95098500DEB3EA /* RNNNavigationStackManagerTest.m in Sources */,
537 555
 				7B49FECB1E95098500DEB3EA /* RNNControllerFactoryTest.m in Sources */,
538 556
 				7B49FECD1E95098500DEB3EA /* RNNModalManagerTest.m in Sources */,
557
+				E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */,
539 558
 				7B49FECC1E95098500DEB3EA /* RNNStoreTest.m in Sources */,
540 559
 			);
541 560
 			runOnlyForDeploymentPostprocessing = 0;
@@ -556,6 +575,7 @@
556 575
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
557 576
 				7BA500751E2544B9001B9E1B /* ReactNativeNavigation.m in Sources */,
558 577
 				263905B21E4C6F440023D7D3 /* MMDrawerController.m in Sources */,
578
+				E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */,
559 579
 				7BBFE5441E25330E002A6182 /* RNNBridgeModule.m in Sources */,
560 580
 				261F0E651E6EC94900989DE2 /* RNNModalManager.m in Sources */,
561 581
 				7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */,

+ 0
- 30
lib/ios/ReactNativeNavigationTests/RNNControllerFactoryTest.m View File

@@ -142,37 +142,7 @@
142 142
 }
143 143
 
144 144
 
145
-- (void)testNavigationOptions_default {
146
-	UIViewController *ans = [self.factory createLayoutAndSaveToStore: @{@"id": @"cntId_2",
147
-																		@"type": @"Container",
148
-																		@"data": @{@"navigationOptions": @{}},
149
-																		@"children": @[]}];
150
-	XCTAssertFalse([ans prefersStatusBarHidden]);
151
-}
152
-
153
-- (void)testNavigationOptions_true {
154
-	UIViewController *ans = [self.factory createLayoutAndSaveToStore: @{@"id": @"cntId_2",
155
-																	    @"type": @"Container",
156
-																		@"data": @{
157
-																			@"navigationOptions": @{
158
-																					@"statusBarHidden": @(1)
159
-																					}
160
-																			},
161
-																		@"children": @[]}];
162
-	XCTAssertTrue([ans prefersStatusBarHidden]);
163
-}
164 145
 
165
-- (void)testNavigationOptions_false {
166
-	UIViewController *ans = [self.factory createLayoutAndSaveToStore: @{@"id": @"cntId_2",
167
-																		@"type": @"Container",
168
-																		@"data": @{
169
-																				@"navigationOptions": @{
170
-																						@"statusBarHidden": @(0)
171
-																						}
172
-																				},
173
-																		@"children": @[]}];
174
-	XCTAssertFalse([ans prefersStatusBarHidden]);
175
-}
176 146
 
177 147
 - (void)testCreateLayout_addContainerToStore {
178 148
 	NSString *containerId = @"cntId";

+ 20
- 0
lib/ios/ReactNativeNavigationTests/RNNNavigationOptionsTest.m View File

@@ -0,0 +1,20 @@
1
+#import <XCTest/XCTest.h>
2
+#import "RNNNavigationOptions.h"
3
+
4
+@interface RNNNavigationOptionsTest : XCTestCase
5
+
6
+@end
7
+
8
+@implementation RNNNavigationOptionsTest
9
+
10
+- (void)setUp {
11
+    [super setUp];
12
+}
13
+
14
+-(void)testInitCreatesInstanceType{
15
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
16
+	XCTAssertTrue([options isKindOfClass:[RNNNavigationOptions class]]);
17
+}
18
+
19
+
20
+@end

+ 87
- 0
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

@@ -0,0 +1,87 @@
1
+#import <XCTest/XCTest.h>
2
+#import "RNNRootViewController.h"
3
+#import "RNNReactRootViewCreator.h"
4
+#import "RNNTestRootViewCreator.h"
5
+#import <React/RCTConvert.h>
6
+#import "RNNNavigationOptions.h"
7
+
8
+@interface RNNRootViewControllerTest : XCTestCase
9
+
10
+@property (nonatomic, strong) id<RNNRootViewCreator> creator;
11
+@property (nonatomic, strong) NSString* pageName;
12
+@property (nonatomic, strong) NSString* containerId;
13
+@property (nonatomic, strong) id emitter;
14
+@property (nonatomic, strong) RNNNavigationOptions* options;
15
+@property (nonatomic, strong) RNNRootViewController* uut;
16
+@end
17
+
18
+@implementation RNNRootViewControllerTest
19
+
20
+- (void)setUp {
21
+    [super setUp];
22
+	self.creator = [[RNNTestRootViewCreator alloc] init];
23
+	self.pageName = @"somename";
24
+	self.containerId = @"cntId";
25
+	self.emitter = nil;
26
+	self.options = [RNNNavigationOptions new];
27
+	self.uut = [[RNNRootViewController alloc] initWithName:self.pageName withOptions:self.options withContainerId:self.containerId rootViewCreator:self.creator eventEmitter:self.emitter];
28
+}
29
+
30
+-(void)testTopBarBackgroundColor_validColor{
31
+	NSNumber* inputColor = @(0xFFFF0000);
32
+	self.options.topBarBackgroundColor = inputColor;
33
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
34
+	[self.uut viewWillAppear:false];
35
+	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
36
+	
37
+	XCTAssertTrue([self.uut.navigationController.navigationBar.barTintColor isEqual:expectedColor]);
38
+}
39
+
40
+-(void)testTopBarBackgroundColorWithoutNavigationController{
41
+	NSNumber* inputColor = @(0xFFFF0000);
42
+	self.options.topBarBackgroundColor = inputColor;
43
+	
44
+	XCTAssertNoThrow([self.uut viewWillAppear:false]);
45
+}
46
+
47
+- (void)testStatusBarHidden_default {
48
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
49
+	[self.uut viewWillAppear:false];
50
+
51
+	XCTAssertFalse([self.uut prefersStatusBarHidden]);
52
+}
53
+
54
+- (void)testStatusBarHidden_true {
55
+	self.options.statusBarHidden = @(1);
56
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
57
+	[self.uut viewWillAppear:false];
58
+	
59
+	XCTAssertTrue([self.uut prefersStatusBarHidden]);
60
+}
61
+
62
+- (void)testStatusBarHidden_false {
63
+	self.options.statusBarHidden = @(0);
64
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
65
+	[self.uut viewWillAppear:false];
66
+	
67
+	XCTAssertFalse([self.uut prefersStatusBarHidden]);
68
+}
69
+
70
+-(void)testTitle_string{
71
+	NSString* title =@"some title";
72
+	self.options.title= title;
73
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
74
+	
75
+	[self.uut viewWillAppear:false];
76
+	XCTAssertTrue([self.uut.navigationItem.title isEqual:title]);
77
+}
78
+
79
+-(void)testTitle_default{
80
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
81
+	
82
+	[self.uut viewWillAppear:false];
83
+	XCTAssertNil(self.uut.navigationItem.title);
84
+}
85
+
86
+
87
+@end

+ 6
- 0
lib/ios/ReactNativeNavigationTests/RNNTestRootViewCreator.h View File

@@ -0,0 +1,6 @@
1
+#import <Foundation/Foundation.h>
2
+#import "RNNRootViewCreator.h"
3
+
4
+@interface RNNTestRootViewCreator : NSObject <RNNRootViewCreator>
5
+
6
+@end

+ 10
- 0
lib/ios/ReactNativeNavigationTests/RNNTestRootViewCreator.m View File

@@ -0,0 +1,10 @@
1
+#import "RNNTestRootViewCreator.h"
2
+
3
+@implementation RNNTestRootViewCreator
4
+
5
+- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId {
6
+	UIView *view = [[UIView alloc] init];
7
+	return view;
8
+}
9
+
10
+@end

+ 13
- 0
lib/src/commands/LayoutTreeCrawler.js View File

@@ -1,4 +1,5 @@
1 1
 import _ from 'lodash';
2
+import { processColor } from 'react-native';
2 3
 import LayoutTypes from './LayoutTypes';
3 4
 
4 5
 export default class LayoutTreeCrawler {
@@ -24,6 +25,18 @@ export default class LayoutTreeCrawler {
24 25
     this.store.setPropsForContainerId(node.id, node.data.passProps);
25 26
     const clazz = this.store.getOriginalContainerClassForName(node.data.name);
26 27
     node.data.navigationOptions = _.cloneDeep(_.get(clazz, 'navigationOptions', {}));
28
+    this._processNavigationOptionsColors(node.data.navigationOptions);
29
+  }
30
+
31
+  _processNavigationOptionsColors(navigationOptions) {
32
+    _.forEach(navigationOptions, (value, key) => {
33
+      if (_.endsWith(key, 'Color')) {
34
+        navigationOptions[key] = processColor(value);
35
+      }
36
+      if (_.isPlainObject(value)) {
37
+        this._processNavigationOptionsColors(value);
38
+      }
39
+    });
27 40
   }
28 41
 
29 42
   _assertKnownLayoutType(type) {

+ 83
- 0
lib/src/commands/LayoutTreeCrawler.test.js View File

@@ -84,4 +84,87 @@ describe('LayoutTreeCrawler', () => {
84 84
     uut.crawl(node);
85 85
     expect(node.data.navigationOptions).toEqual({});
86 86
   });
87
+
88
+  describe('navigation options', () => {
89
+    let navigationOptions;
90
+    let MyContainer;
91
+    let node;
92
+
93
+    beforeEach(() => {
94
+      navigationOptions = {};
95
+      MyContainer = class {
96
+        static navigationOptions = navigationOptions;
97
+      };
98
+      node = { type: LayoutTypes.Container, data: { name: 'theContainerName' } };
99
+      store.setOriginalContainerClassForName('theContainerName', MyContainer);
100
+    });
101
+
102
+    it('processes colors into numeric AARRGGBB', () => {
103
+      navigationOptions.someKeyColor = 'red';
104
+      uut.crawl(node);
105
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xffff0000);
106
+
107
+      navigationOptions.someKeyColor = 'yellow';
108
+      uut.crawl(node);
109
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xffffff00);
110
+    });
111
+
112
+    it('processes numeric colors', () => {
113
+      navigationOptions.someKeyColor = '#123456';
114
+      uut.crawl(node);
115
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xff123456);
116
+
117
+      navigationOptions.someKeyColor = 0x123456ff; // wut
118
+      uut.crawl(node);
119
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xff123456);
120
+    });
121
+
122
+    it('process colors with rgb functions', () => {
123
+      navigationOptions.someKeyColor = 'rgb(255, 0, 255)';
124
+      uut.crawl(node);
125
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xffff00ff);
126
+    });
127
+
128
+    it('process colors with special words', () => {
129
+      navigationOptions.someKeyColor = 'fuchsia';
130
+      uut.crawl(node);
131
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xffff00ff);
132
+    });
133
+
134
+    it('process colors with hsla functions', () => {
135
+      navigationOptions.someKeyColor = 'hsla(360, 100%, 100%, 1.0)';
136
+      uut.crawl(node);
137
+      expect(node.data.navigationOptions.someKeyColor).toEqual(0xffffffff);
138
+    });
139
+
140
+    it('unknown colors return undefined', () => {
141
+      navigationOptions.someKeyColor = 'wut';
142
+      uut.crawl(node);
143
+      expect(node.data.navigationOptions.someKeyColor).toEqual(undefined);
144
+    });
145
+
146
+    it('any keys ending with Color', () => {
147
+      navigationOptions.otherKeyColor = 'red';
148
+      navigationOptions.yetAnotherColor = 'blue';
149
+      navigationOptions.andAnotherColor = 'rgb(0, 255, 0)';
150
+      uut.crawl(node);
151
+      expect(node.data.navigationOptions.otherKeyColor).toEqual(0xffff0000);
152
+      expect(node.data.navigationOptions.yetAnotherColor).toEqual(0xff0000ff);
153
+      expect(node.data.navigationOptions.andAnotherColor).toEqual(0xff00ff00);
154
+    });
155
+
156
+    it('keys ending with Color case sensitive', () => {
157
+      navigationOptions.otherKey_color = 'red';
158
+      uut.crawl(node);
159
+      expect(node.data.navigationOptions.otherKey_color).toEqual('red');
160
+    });
161
+
162
+    it('any nested recursive keys ending with Color', () => {
163
+      navigationOptions.innerObj = { theKeyColor: 'red' };
164
+      navigationOptions.innerObj.innerMostObj = { anotherColor: 'yellow' };
165
+      uut.crawl(node);
166
+      expect(node.data.navigationOptions.innerObj.theKeyColor).toEqual(0xffff0000);
167
+      expect(node.data.navigationOptions.innerObj.innerMostObj.anotherColor).toEqual(0xffffff00);
168
+    });
169
+  });
87 170
 });

+ 3
- 1
playground/src/containers/OptionsScreen.js View File

@@ -11,7 +11,9 @@ import Navigation from 'react-native-navigation';
11 11
 
12 12
 class OptionsScreen extends Component {
13 13
   static navigationOptions = {
14
-    title: 'Static Title'
14
+    title: 'Static Title',
15
+    topBarBackgroundColor: "red",
16
+    statusBarHidden: true
15 17
   }
16 18
 
17 19
   constructor(props) {