瀏覽代碼

Added tests for Presenters (#4155)

Added unit test coverage on iOS
Yogev Ben David 6 年之前
父節點
當前提交
9e29c183fe
No account linked to committer's email address

+ 26
- 0
lib/ios/OCMock/NSNotificationCenter+OCMAdditions.h 查看文件

@@ -0,0 +1,26 @@
1
+/*
2
+ *  Copyright (c) 2009-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@class OCObserverMockObject;
20
+
21
+
22
+@interface NSNotificationCenter(OCMAdditions)
23
+
24
+- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender;
25
+
26
+@end

+ 58
- 0
lib/ios/OCMock/OCMArg.h 查看文件

@@ -0,0 +1,58 @@
1
+/*
2
+ *  Copyright (c) 2009-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@interface OCMArg : NSObject 
20
+
21
+// constraining arguments
22
+
23
++ (id)any;
24
++ (SEL)anySelector;
25
++ (void *)anyPointer;
26
++ (id __autoreleasing *)anyObjectRef;
27
++ (id)isNil;
28
++ (id)isNotNil;
29
++ (id)isEqual:(id)value;
30
++ (id)isNotEqual:(id)value;
31
++ (id)isKindOfClass:(Class)cls;
32
++ (id)checkWithSelector:(SEL)selector onObject:(id)anObject;
33
++ (id)checkWithBlock:(BOOL (^)(id obj))block;
34
+
35
+// manipulating arguments
36
+
37
++ (id *)setTo:(id)value;
38
++ (void *)setToValue:(NSValue *)value;
39
++ (id)invokeBlock;
40
++ (id)invokeBlockWithArgs:(id)first,... NS_REQUIRES_NIL_TERMINATION;
41
+
42
++ (id)defaultValue;
43
+
44
+// internal use only
45
+
46
++ (id)resolveSpecialValues:(NSValue *)value;
47
+
48
+@end
49
+
50
+#define OCMOCK_ANY [OCMArg any]
51
+
52
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
53
+  #define OCMOCK_VALUE(variable) \
54
+    ({ __typeof__(variable) __v = (variable); [NSValue value:&__v withObjCType:@encode(__typeof__(__v))]; })
55
+#else
56
+  #define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))]
57
+#endif
58
+

+ 71
- 0
lib/ios/OCMock/OCMConstraint.h 查看文件

@@ -0,0 +1,71 @@
1
+/*
2
+ *  Copyright (c) 2007-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+
20
+@interface OCMConstraint : NSObject 
21
+
22
++ (instancetype)constraint;
23
+- (BOOL)evaluate:(id)value;
24
+
25
+// if you are looking for any, isNil, etc, they have moved to OCMArg
26
+
27
+// try to use [OCMArg checkWith...] instead of the constraintWith... methods below
28
+
29
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject;
30
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue;
31
+
32
+
33
+@end
34
+
35
+@interface OCMAnyConstraint : OCMConstraint
36
+@end
37
+
38
+@interface OCMIsNilConstraint : OCMConstraint
39
+@end
40
+
41
+@interface OCMIsNotNilConstraint : OCMConstraint
42
+@end
43
+
44
+@interface OCMIsNotEqualConstraint : OCMConstraint
45
+{
46
+	@public
47
+	id testValue;
48
+}
49
+
50
+@end
51
+
52
+@interface OCMInvocationConstraint : OCMConstraint
53
+{
54
+	@public
55
+	NSInvocation *invocation;
56
+}
57
+
58
+@end
59
+
60
+@interface OCMBlockConstraint : OCMConstraint
61
+{
62
+	BOOL (^block)(id);
63
+}
64
+
65
+- (instancetype)initWithConstraintBlock:(BOOL (^)(id))block;
66
+
67
+@end
68
+
69
+
70
+#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self]
71
+#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)]

+ 27
- 0
lib/ios/OCMock/OCMFunctions.h 查看文件

@@ -0,0 +1,27 @@
1
+/*
2
+ *  Copyright (c) 2014-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+
20
+#if defined(__cplusplus)
21
+#define OCMOCK_EXTERN extern "C"
22
+#else
23
+#define OCMOCK_EXTERN extern
24
+#endif
25
+
26
+
27
+OCMOCK_EXTERN BOOL OCMIsObjectType(const char *objCType);

+ 38
- 0
lib/ios/OCMock/OCMLocation.h 查看文件

@@ -0,0 +1,38 @@
1
+/*
2
+ *  Copyright (c) 2014-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+#import "OCMFunctions.h"
19
+
20
+
21
+@interface OCMLocation : NSObject
22
+{
23
+    id          testCase;
24
+    NSString    *file;
25
+    NSUInteger  line;
26
+}
27
+
28
++ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
29
+
30
+- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
31
+
32
+- (id)testCase;
33
+- (NSString *)file;
34
+- (NSUInteger)line;
35
+
36
+@end
37
+
38
+OCMOCK_EXTERN OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);

+ 48
- 0
lib/ios/OCMock/OCMMacroState.h 查看文件

@@ -0,0 +1,48 @@
1
+/*
2
+ *  Copyright (c) 2014-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@class OCMLocation;
20
+@class OCMRecorder;
21
+@class OCMStubRecorder;
22
+@class OCMockObject;
23
+
24
+
25
+@interface OCMMacroState : NSObject
26
+{
27
+    OCMRecorder *recorder;
28
+}
29
+
30
++ (void)beginStubMacro;
31
++ (OCMStubRecorder *)endStubMacro;
32
+
33
++ (void)beginExpectMacro;
34
++ (OCMStubRecorder *)endExpectMacro;
35
+
36
++ (void)beginRejectMacro;
37
++ (OCMStubRecorder *)endRejectMacro;
38
+
39
++ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation;
40
++ (void)endVerifyMacro;
41
+
42
++ (OCMMacroState *)globalState;
43
+
44
+- (OCMRecorder *)recorder;
45
+
46
+- (void)switchToClassMethod;
47
+
48
+@end

+ 39
- 0
lib/ios/OCMock/OCMRecorder.h 查看文件

@@ -0,0 +1,39 @@
1
+/*
2
+ *  Copyright (c) 2014-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@class OCMockObject;
20
+@class OCMInvocationMatcher;
21
+
22
+
23
+@interface OCMRecorder : NSProxy
24
+{
25
+    OCMockObject         *mockObject;
26
+    OCMInvocationMatcher *invocationMatcher;
27
+}
28
+
29
+- (instancetype)init;
30
+- (instancetype)initWithMockObject:(OCMockObject *)aMockObject;
31
+
32
+- (void)setMockObject:(OCMockObject *)aMockObject;
33
+
34
+- (OCMInvocationMatcher *)invocationMatcher;
35
+
36
+- (id)classMethod;
37
+- (id)ignoringNonObjectArgs;
38
+
39
+@end

+ 64
- 0
lib/ios/OCMock/OCMStubRecorder.h 查看文件

@@ -0,0 +1,64 @@
1
+/*
2
+ *  Copyright (c) 2004-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <OCMock/OCMRecorder.h>
18
+#import <OCMock/OCMFunctions.h>
19
+#import <objc/runtime.h>
20
+
21
+@interface OCMStubRecorder : OCMRecorder
22
+
23
+- (id)andReturn:(id)anObject;
24
+- (id)andReturnValue:(NSValue *)aValue;
25
+- (id)andThrow:(NSException *)anException;
26
+- (id)andPost:(NSNotification *)aNotification;
27
+- (id)andCall:(SEL)selector onObject:(id)anObject;
28
+- (id)andDo:(void (^)(NSInvocation *invocation))block;
29
+- (id)andForwardToRealObject;
30
+
31
+@end
32
+
33
+
34
+@interface OCMStubRecorder (Properties)
35
+
36
+#define andReturn(aValue) _andReturn(({                                             \
37
+  __typeof__(aValue) _val = (aValue);                                               \
38
+  NSValue *_nsval = [NSValue value:&_val withObjCType:@encode(__typeof__(_val))];   \
39
+  if (OCMIsObjectType(@encode(__typeof(_val)))) {                                   \
40
+      objc_setAssociatedObject(_nsval, "OCMAssociatedBoxedValue", *(__unsafe_unretained id *) (void *) &_val, OBJC_ASSOCIATION_RETAIN); \
41
+  }                                                                                 \
42
+  _nsval;                                                                           \
43
+}))
44
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andReturn)(NSValue *);
45
+
46
+#define andThrow(anException) _andThrow(anException)
47
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andThrow)(NSException *);
48
+
49
+#define andPost(aNotification) _andPost(aNotification)
50
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andPost)(NSNotification *);
51
+
52
+#define andCall(anObject, aSelector) _andCall(anObject, aSelector)
53
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andCall)(id, SEL);
54
+
55
+#define andDo(aBlock) _andDo(aBlock)
56
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andDo)(void (^)(NSInvocation *));
57
+
58
+#define andForwardToRealObject() _andForwardToRealObject()
59
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andForwardToRealObject)(void);
60
+
61
+@end
62
+
63
+
64
+

+ 113
- 0
lib/ios/OCMock/OCMock.h 查看文件

@@ -0,0 +1,113 @@
1
+/*
2
+ *  Copyright (c) 2004-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <OCMock/OCMockObject.h>
18
+#import <OCMock/OCMRecorder.h>
19
+#import <OCMock/OCMStubRecorder.h>
20
+#import <OCMock/OCMConstraint.h>
21
+#import <OCMock/OCMArg.h>
22
+#import <OCMock/OCMLocation.h>
23
+#import <OCMock/OCMMacroState.h>
24
+#import <OCMock/NSNotificationCenter+OCMAdditions.h>
25
+#import <OCMock/OCMFunctions.h>
26
+
27
+
28
+#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
29
+
30
+#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
31
+
32
+#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol]
33
+
34
+#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol]
35
+
36
+#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj]
37
+
38
+#define OCMObserverMock() [OCMockObject observerMock]
39
+
40
+
41
+#define OCMStub(invocation) \
42
+({ \
43
+    _OCMSilenceWarnings( \
44
+        [OCMMacroState beginStubMacro]; \
45
+        OCMStubRecorder *recorder = nil; \
46
+        @try{ \
47
+            invocation; \
48
+        }@finally{ \
49
+            recorder = [OCMMacroState endStubMacro]; \
50
+        } \
51
+        recorder; \
52
+    ); \
53
+})
54
+
55
+#define OCMExpect(invocation) \
56
+({ \
57
+    _OCMSilenceWarnings( \
58
+        [OCMMacroState beginExpectMacro]; \
59
+        OCMStubRecorder *recorder = nil; \
60
+        @try{ \
61
+            invocation; \
62
+        }@finally{ \
63
+            recorder = [OCMMacroState endExpectMacro]; \
64
+        } \
65
+        recorder; \
66
+    ); \
67
+})
68
+
69
+#define OCMReject(invocation) \
70
+({ \
71
+    _OCMSilenceWarnings( \
72
+        [OCMMacroState beginRejectMacro]; \
73
+        OCMStubRecorder *recorder = nil; \
74
+        @try{ \
75
+            invocation; \
76
+        }@finally{ \
77
+            recorder = [OCMMacroState endRejectMacro]; \
78
+        } \
79
+        recorder; \
80
+    ); \
81
+})
82
+
83
+#define ClassMethod(invocation) \
84
+    _OCMSilenceWarnings( \
85
+        [[OCMMacroState globalState] switchToClassMethod]; \
86
+        invocation; \
87
+    );
88
+
89
+
90
+#define OCMVerifyAll(mock) [mock verifyAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
91
+
92
+#define OCMVerifyAllWithDelay(mock, delay) [mock verifyWithDelay:delay atLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
93
+
94
+#define OCMVerify(invocation) \
95
+({ \
96
+    _OCMSilenceWarnings( \
97
+        [OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \
98
+        @try{ \
99
+            invocation; \
100
+        }@finally{ \
101
+            [OCMMacroState endVerifyMacro]; \
102
+        } \
103
+    ); \
104
+})
105
+
106
+#define _OCMSilenceWarnings(macro) \
107
+({ \
108
+    _Pragma("clang diagnostic push") \
109
+    _Pragma("clang diagnostic ignored \"-Wunused-value\"") \
110
+    _Pragma("clang diagnostic ignored \"-Wunused-getter-return-value\"") \
111
+    macro \
112
+    _Pragma("clang diagnostic pop") \
113
+})

+ 74
- 0
lib/ios/OCMock/OCMockObject.h 查看文件

@@ -0,0 +1,74 @@
1
+/*
2
+ *  Copyright (c) 2004-2016 Erik Doernenburg and contributors
3
+ *
4
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ *  not use these files except in compliance with the License. You may obtain
6
+ *  a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ *  Unless required by applicable law or agreed to in writing, software
11
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ *  License for the specific language governing permissions and limitations
14
+ *  under the License.
15
+ */
16
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@class OCMLocation;
20
+@class OCMInvocationStub;
21
+@class OCMStubRecorder;
22
+@class OCMInvocationMatcher;
23
+@class OCMInvocationExpectation;
24
+
25
+
26
+@interface OCMockObject : NSProxy
27
+{
28
+	BOOL			isNice;
29
+	BOOL			expectationOrderMatters;
30
+	NSMutableArray	*stubs;
31
+	NSMutableArray	*expectations;
32
+	NSMutableArray	*exceptions;
33
+    NSMutableArray  *invocations;
34
+}
35
+
36
++ (id)mockForClass:(Class)aClass;
37
++ (id)mockForProtocol:(Protocol *)aProtocol;
38
++ (id)partialMockForObject:(NSObject *)anObject;
39
+
40
++ (id)niceMockForClass:(Class)aClass;
41
++ (id)niceMockForProtocol:(Protocol *)aProtocol;
42
+
43
++ (id)observerMock;
44
+
45
+- (instancetype)init;
46
+
47
+- (void)setExpectationOrderMatters:(BOOL)flag;
48
+
49
+- (id)stub;
50
+- (id)expect;
51
+- (id)reject;
52
+
53
+- (id)verify;
54
+- (id)verifyAtLocation:(OCMLocation *)location;
55
+
56
+- (void)verifyWithDelay:(NSTimeInterval)delay;
57
+- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location;
58
+
59
+- (void)stopMocking;
60
+
61
+// internal use only
62
+
63
+- (void)addStub:(OCMInvocationStub *)aStub;
64
+- (void)addExpectation:(OCMInvocationExpectation *)anExpectation;
65
+
66
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
67
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
68
+- (BOOL)handleSelector:(SEL)sel;
69
+
70
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher;
71
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location;
72
+
73
+@end
74
+

+ 10
- 4
lib/ios/RNNNavigationControllerPresenter.m 查看文件

@@ -11,7 +11,7 @@
11 11
 	
12 12
 	
13 13
 	RNNNavigationController* navigationController = self.bindedViewController;
14
-
14
+	
15 15
 	[navigationController rnn_setInteractivePopGestureEnabled:[options.popGesture getWithDefaultValue:YES]];
16 16
 	[navigationController rnn_setRootBackgroundImage:[options.rootBackgroundImage getWithDefaultValue:nil]];
17 17
 	[navigationController rnn_setNavigationBarTestID:[options.topBar.testID getWithDefaultValue:nil]];
@@ -25,10 +25,16 @@
25 25
 	[navigationController setTopBarBackgroundColor:[options.topBar.background.color getWithDefaultValue:nil]];
26 26
 	[navigationController rnn_setNavigationBarLargeTitleVisible:[options.topBar.largeTitle.visible getWithDefaultValue:NO]];
27 27
 	[navigationController rnn_setNavigationBarLargeTitleFontFamily:[options.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.largeTitle.fontSize getWithDefaultValue:nil] color:[options.topBar.largeTitle.color getWithDefaultValue:nil]];
28
-	[navigationController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""];
29 28
 	[navigationController rnn_setNavigationBarFontFamily:[options.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.title.fontSize getWithDefaultValue:nil] color:[options.topBar.title.color getWithDefaultValue:nil]];
30 29
 }
31 30
 
31
+- (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
32
+	[super applyOptionsOnWillMoveToParentViewController:options];
33
+	
34
+	RNNNavigationController* navigationController = self.bindedViewController;
35
+	[navigationController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""];
36
+}
37
+
32 38
 - (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigationOptions *)resolvedOptions {
33 39
 	[super mergeOptions:options resolvedOptions:resolvedOptions];
34 40
 	
@@ -85,13 +91,13 @@
85 91
 	
86 92
 	if (options.topBar.backButton.icon.hasValue) {
87 93
 		[navigationController rnn_setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES] ? [withDefault.topBar.backButton.title getWithDefaultValue:nil] : @""];
88
-
94
+		
89 95
 	}
90 96
 	
91 97
 	[navigationController rnn_setNavigationBarLargeTitleFontFamily:[withDefault.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.largeTitle.fontSize getWithDefaultValue:nil] color:[withDefault.topBar.largeTitle.color getWithDefaultValue:nil]];
92 98
 	
93 99
 	[navigationController rnn_setNavigationBarFontFamily:[withDefault.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.title.fontSize getWithDefaultValue:nil] color:[withDefault.topBar.title.color getWithDefaultValue:nil]];
94
-
100
+	
95 101
 }
96 102
 
97 103
 @end

+ 4
- 2
lib/ios/RNNTabBarController.h 查看文件

@@ -1,15 +1,17 @@
1 1
 #import <UIKit/UIKit.h>
2 2
 #import "RNNParentProtocol.h"
3 3
 #import "RNNEventEmitter.h"
4
+#import "RNNTabBarPresenter.h"
4 5
 
5 6
 @interface RNNTabBarController : UITabBarController <RNNParentProtocol, UITabBarControllerDelegate>
6 7
 
7
-- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options presenter:(RNNBasePresenter *)presenter eventEmitter:(RNNEventEmitter *)eventEmitter;
8
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options presenter:(RNNTabBarPresenter *)presenter eventEmitter:(RNNEventEmitter *)eventEmitter;
8 9
 
9 10
 - (void)setSelectedIndexByComponentID:(NSString *)componentID;
10 11
 
11 12
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
12
-@property (nonatomic, retain) RNNViewControllerPresenter* presenter;
13
+@property (nonatomic, retain) RNNTabBarPresenter* presenter;
13 14
 @property (nonatomic, strong) RNNNavigationOptions* options;
15
+@property (nonatomic, strong) RNNEventEmitter *eventEmitter;
14 16
 
15 17
 @end

+ 5
- 24
lib/ios/RNNTabBarController.m 查看文件

@@ -1,17 +1,13 @@
1
-
2 1
 #import "RNNTabBarController.h"
3 2
 
4
-#define kTabBarHiddenDuration 0.3
5
-
6 3
 @implementation RNNTabBarController {
7 4
 	NSUInteger _currentTabIndex;
8
-	RNNEventEmitter *_eventEmitter;
9 5
 }
10 6
 
11 7
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
12 8
 			  childViewControllers:(NSArray *)childViewControllers
13 9
 						   options:(RNNNavigationOptions *)options
14
-						 presenter:(RNNBasePresenter *)presenter
10
+						 presenter:(RNNTabBarPresenter *)presenter
15 11
 					  eventEmitter:(RNNEventEmitter *)eventEmitter {
16 12
 	self = [self initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options presenter:presenter];
17 13
 	
@@ -23,26 +19,16 @@
23 19
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
24 20
 			  childViewControllers:(NSArray *)childViewControllers
25 21
 						   options:(RNNNavigationOptions *)options
26
-						 presenter:(RNNViewControllerPresenter *)presenter {
22
+						 presenter:(RNNTabBarPresenter *)presenter {
27 23
 	self = [super init];
28 24
 	
29 25
 	self.delegate = self;
30 26
 	self.options = options;
31
-	
32 27
 	self.layoutInfo = layoutInfo;
33
-	
34 28
 	self.presenter = presenter;
35 29
 	[self.presenter bindViewController:self];
36
-	
37 30
 	[self setViewControllers:childViewControllers];
38
-		
39
-	return self;
40
-}
41
-
42
-- (instancetype)initWithEventEmitter:(id)eventEmitter {
43
-	self = [super init];
44
-	_eventEmitter = eventEmitter;
45
-	self.delegate = self;
31
+	
46 32
 	return self;
47 33
 }
48 34
 
@@ -66,11 +52,6 @@
66 52
 	[((UIViewController<RNNLayoutProtocol> *)self.parentViewController) mergeOptions:options];
67 53
 }
68 54
 
69
-- (void)viewWillAppear:(BOOL)animated {
70
-	[super viewWillAppear:animated];
71
-	[_presenter applyOptions:self.options];
72
-}
73
-
74 55
 - (UITabBarItem *)tabBarItem {
75 56
 	return super.tabBarItem ? super.tabBarItem : self.viewControllers.lastObject.tabBarItem;
76 57
 }
@@ -81,9 +62,9 @@
81 62
 
82 63
 - (void)setSelectedIndexByComponentID:(NSString *)componentID {
83 64
 	for (id child in self.childViewControllers) {
84
-		UIViewController<RNNParentProtocol>* vc = child;
65
+		UIViewController<RNNLayoutProtocol>* vc = child;
85 66
 
86
-		if ([vc.layoutInfo.componentId isEqualToString:componentID]) {
67
+		if ([vc conformsToProtocol:@protocol(RNNLayoutProtocol)] && [vc.layoutInfo.componentId isEqualToString:componentID]) {
87 68
 			[self setSelectedIndex:[self.childViewControllers indexOfObject:child]];
88 69
 		}
89 70
 	}

+ 42
- 4
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj 查看文件

@@ -63,6 +63,7 @@
63 63
 		390AD478200F499D00A8250D /* RNNSwizzles.m in Sources */ = {isa = PBXBuildFile; fileRef = 390AD476200F499D00A8250D /* RNNSwizzles.m */; };
64 64
 		4534E72520CB6724009F8185 /* RNNLargeTitleOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */; };
65 65
 		4534E72620CB6724009F8185 /* RNNLargeTitleOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */; };
66
+		501214C9217741A000435148 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 501214C8217741A000435148 /* libOCMock.a */; };
66 67
 		501223D72173590F000F5F98 /* RNNNavigationControllerPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 501223D52173590F000F5F98 /* RNNNavigationControllerPresenter.h */; };
67 68
 		501223D82173590F000F5F98 /* RNNNavigationControllerPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 501223D62173590F000F5F98 /* RNNNavigationControllerPresenter.m */; };
68 69
 		501224062173592D000F5F98 /* RNNTabBarPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 501224042173592D000F5F98 /* RNNTabBarPresenter.h */; };
@@ -98,9 +99,11 @@
98 99
 		502CB43A20CBCA180019B2FE /* RNNBridgeManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 502CB43920CBCA140019B2FE /* RNNBridgeManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
99 100
 		502CB46E20CD1DDA0019B2FE /* RNNBackButtonOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */; };
100 101
 		502CB46F20CD1DDA0019B2FE /* RNNBackButtonOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */; };
102
+		502F0E142178CF8200367CC3 /* UIViewController+RNNOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 502F0E132178CF8200367CC3 /* UIViewController+RNNOptionsTest.m */; };
103
+		502F0E162178D09600367CC3 /* RNNBottomTabPresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 502F0E152178D09600367CC3 /* RNNBottomTabPresenterTest.m */; };
101 104
 		5038A374216CDDB6009280BC /* UIViewController+SideMenuController.h in Headers */ = {isa = PBXBuildFile; fileRef = 5038A372216CDDB6009280BC /* UIViewController+SideMenuController.h */; };
102 105
 		5038A375216CDDB6009280BC /* UIViewController+SideMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5038A373216CDDB6009280BC /* UIViewController+SideMenuController.m */; };
103
-		5038A377216CF252009280BC /* RNNBottomTabsOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5038A376216CF252009280BC /* RNNBottomTabsOptionsTest.m */; };
106
+		5038A377216CF252009280BC /* UITabBarController+RNNOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5038A376216CF252009280BC /* UITabBarController+RNNOptionsTest.m */; };
104 107
 		5038A379216D01F6009280BC /* RNNBottomTabOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5038A378216D01F6009280BC /* RNNBottomTabOptionsTest.m */; };
105 108
 		5038A3B1216DF41B009280BC /* UIViewController+RNNOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5038A3AF216DF41B009280BC /* UIViewController+RNNOptions.h */; };
106 109
 		5038A3B2216DF41B009280BC /* UIViewController+RNNOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5038A3B0216DF41B009280BC /* UIViewController+RNNOptions.m */; };
@@ -204,6 +207,8 @@
204 207
 		50887C1620ECC5C200D06111 /* RNNButtonOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50887C1420ECC5C200D06111 /* RNNButtonOptions.m */; };
205 208
 		50887CA920F26BFE00D06111 /* RNNOverlayWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 50887CA720F26BFD00D06111 /* RNNOverlayWindow.m */; };
206 209
 		50887CAA20F26BFE00D06111 /* RNNOverlayWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 50887CA820F26BFE00D06111 /* RNNOverlayWindow.h */; };
210
+		509B2480217873FF00C83C23 /* UINavigationController+RNNOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 509B247F217873FF00C83C23 /* UINavigationController+RNNOptionsTest.m */; };
211
+		509B258F2178BE7A00C83C23 /* RNNNavigationControllerPresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 509B258E2178BE7A00C83C23 /* RNNNavigationControllerPresenterTest.m */; };
207 212
 		50A00C37200F84D6000F01A6 /* RNNOverlayOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50A00C35200F84D6000F01A6 /* RNNOverlayOptions.h */; };
208 213
 		50A00C38200F84D6000F01A6 /* RNNOverlayOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50A00C36200F84D6000F01A6 /* RNNOverlayOptions.m */; };
209 214
 		50BE951220B5A787004F5DF5 /* RNNStatusBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50BE951020B5A787004F5DF5 /* RNNStatusBarOptions.m */; };
@@ -376,6 +381,7 @@
376 381
 		390AD476200F499D00A8250D /* RNNSwizzles.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSwizzles.m; sourceTree = "<group>"; };
377 382
 		4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNLargeTitleOptions.h; sourceTree = "<group>"; };
378 383
 		4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNLargeTitleOptions.m; sourceTree = "<group>"; };
384
+		501214C8217741A000435148 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = "<group>"; };
379 385
 		501223D52173590F000F5F98 /* RNNNavigationControllerPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNNavigationControllerPresenter.h; sourceTree = "<group>"; };
380 386
 		501223D62173590F000F5F98 /* RNNNavigationControllerPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationControllerPresenter.m; sourceTree = "<group>"; };
381 387
 		501224042173592D000F5F98 /* RNNTabBarPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTabBarPresenter.h; sourceTree = "<group>"; };
@@ -411,9 +417,11 @@
411 417
 		502CB43920CBCA140019B2FE /* RNNBridgeManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBridgeManagerDelegate.h; sourceTree = "<group>"; };
412 418
 		502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBackButtonOptions.h; sourceTree = "<group>"; };
413 419
 		502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBackButtonOptions.m; sourceTree = "<group>"; };
420
+		502F0E132178CF8200367CC3 /* UIViewController+RNNOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+RNNOptionsTest.m"; sourceTree = "<group>"; };
421
+		502F0E152178D09600367CC3 /* RNNBottomTabPresenterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBottomTabPresenterTest.m; sourceTree = "<group>"; };
414 422
 		5038A372216CDDB6009280BC /* UIViewController+SideMenuController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SideMenuController.h"; sourceTree = "<group>"; };
415 423
 		5038A373216CDDB6009280BC /* UIViewController+SideMenuController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+SideMenuController.m"; sourceTree = "<group>"; };
416
-		5038A376216CF252009280BC /* RNNBottomTabsOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBottomTabsOptionsTest.m; sourceTree = "<group>"; };
424
+		5038A376216CF252009280BC /* UITabBarController+RNNOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITabBarController+RNNOptionsTest.m"; sourceTree = "<group>"; };
417 425
 		5038A378216D01F6009280BC /* RNNBottomTabOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBottomTabOptionsTest.m; sourceTree = "<group>"; };
418 426
 		5038A3AF216DF41B009280BC /* UIViewController+RNNOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+RNNOptions.h"; sourceTree = "<group>"; };
419 427
 		5038A3B0216DF41B009280BC /* UIViewController+RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+RNNOptions.m"; sourceTree = "<group>"; };
@@ -517,6 +525,8 @@
517 525
 		50887C1420ECC5C200D06111 /* RNNButtonOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNButtonOptions.m; sourceTree = "<group>"; };
518 526
 		50887CA720F26BFD00D06111 /* RNNOverlayWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNOverlayWindow.m; sourceTree = "<group>"; };
519 527
 		50887CA820F26BFE00D06111 /* RNNOverlayWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNOverlayWindow.h; sourceTree = "<group>"; };
528
+		509B247F217873FF00C83C23 /* UINavigationController+RNNOptionsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UINavigationController+RNNOptionsTest.m"; sourceTree = "<group>"; };
529
+		509B258E2178BE7A00C83C23 /* RNNNavigationControllerPresenterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationControllerPresenterTest.m; sourceTree = "<group>"; };
520 530
 		50A00C35200F84D6000F01A6 /* RNNOverlayOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNOverlayOptions.h; sourceTree = "<group>"; };
521 531
 		50A00C36200F84D6000F01A6 /* RNNOverlayOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOverlayOptions.m; sourceTree = "<group>"; };
522 532
 		50BE951020B5A787004F5DF5 /* RNNStatusBarOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNStatusBarOptions.m; sourceTree = "<group>"; };
@@ -633,6 +643,7 @@
633 643
 				7B49FEE91E950A7A00DEB3EA /* libRCTVibration.a in Frameworks */,
634 644
 				7B49FEEA1E950A7A00DEB3EA /* libRCTWebSocket.a in Frameworks */,
635 645
 				7B49FEEB1E950A7A00DEB3EA /* libReact.a in Frameworks */,
646
+				501214C9217741A000435148 /* libOCMock.a in Frameworks */,
636 647
 				7B49FEEC1E950A7A00DEB3EA /* libyoga.a in Frameworks */,
637 648
 				7B49FEC01E95090800DEB3EA /* libReactNativeNavigation.a in Frameworks */,
638 649
 			);
@@ -989,7 +1000,8 @@
989 1000
 				505EDD31214E4BE80071C7DE /* RNNNavigationControllerTest.m */,
990 1001
 				506F630C216A599300AD0D0A /* RNNTabBarControllerTest.m */,
991 1002
 				506F630E216A5AD700AD0D0A /* RNNViewControllerPresenterTest.m */,
992
-				5038A376216CF252009280BC /* RNNBottomTabsOptionsTest.m */,
1003
+				509B258E2178BE7A00C83C23 /* RNNNavigationControllerPresenterTest.m */,
1004
+				502F0E152178D09600367CC3 /* RNNBottomTabPresenterTest.m */,
993 1005
 				5038A378216D01F6009280BC /* RNNBottomTabOptionsTest.m */,
994 1006
 				7B49FEBF1E95090800DEB3EA /* Info.plist */,
995 1007
 				E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */,
@@ -997,6 +1009,9 @@
997 1009
 				E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */,
998 1010
 				E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */,
999 1011
 				E8DA243C1F973C1900CD552B /* RNNTransitionStateHolderTest.m */,
1012
+				502F0E132178CF8200367CC3 /* UIViewController+RNNOptionsTest.m */,
1013
+				5038A376216CF252009280BC /* UITabBarController+RNNOptionsTest.m */,
1014
+				509B247F217873FF00C83C23 /* UINavigationController+RNNOptionsTest.m */,
1000 1015
 			);
1001 1016
 			path = ReactNativeNavigationTests;
1002 1017
 			sourceTree = "<group>";
@@ -1004,6 +1019,7 @@
1004 1019
 		7B49FED01E950A7A00DEB3EA /* Frameworks */ = {
1005 1020
 			isa = PBXGroup;
1006 1021
 			children = (
1022
+				501214C8217741A000435148 /* libOCMock.a */,
1007 1023
 				7B49FED11E950A7A00DEB3EA /* libcxxreact.a */,
1008 1024
 				7B49FED21E950A7A00DEB3EA /* libjschelpers.a */,
1009 1025
 				7B49FED31E950A7A00DEB3EA /* libRCTActionSheet.a */,
@@ -1346,8 +1362,10 @@
1346 1362
 			isa = PBXSourcesBuildPhase;
1347 1363
 			buildActionMask = 2147483647;
1348 1364
 			files = (
1349
-				5038A377216CF252009280BC /* RNNBottomTabsOptionsTest.m in Sources */,
1365
+				502F0E142178CF8200367CC3 /* UIViewController+RNNOptionsTest.m in Sources */,
1366
+				5038A377216CF252009280BC /* UITabBarController+RNNOptionsTest.m in Sources */,
1350 1367
 				E83BAD7C1F27643000A9F3DD /* RNNTestRootViewCreator.m in Sources */,
1368
+				502F0E162178D09600367CC3 /* RNNBottomTabPresenterTest.m in Sources */,
1351 1369
 				504753782109C13C00FFFBE6 /* RNNOverlayManagerTest.m in Sources */,
1352 1370
 				506F630F216A5AD700AD0D0A /* RNNViewControllerPresenterTest.m in Sources */,
1353 1371
 				7B49FECE1E95098500DEB3EA /* RNNCommandsHandlerTest.m in Sources */,
@@ -1355,8 +1373,10 @@
1355 1373
 				E83BAD681F2734B500A9F3DD /* RNNNavigationOptionsTest.m in Sources */,
1356 1374
 				505EDD32214E4BE80071C7DE /* RNNNavigationControllerTest.m in Sources */,
1357 1375
 				7B49FECF1E95098500DEB3EA /* RNNNavigationStackManagerTest.m in Sources */,
1376
+				509B2480217873FF00C83C23 /* UINavigationController+RNNOptionsTest.m in Sources */,
1358 1377
 				506F630D216A599300AD0D0A /* RNNTabBarControllerTest.m in Sources */,
1359 1378
 				7B49FECB1E95098500DEB3EA /* RNNControllerFactoryTest.m in Sources */,
1379
+				509B258F2178BE7A00C83C23 /* RNNNavigationControllerPresenterTest.m in Sources */,
1360 1380
 				7B49FECD1E95098500DEB3EA /* RNNModalManagerTest.m in Sources */,
1361 1381
 				E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */,
1362 1382
 				E8DA243D1F973C1900CD552B /* RNNTransitionStateHolderTest.m in Sources */,
@@ -1515,9 +1535,18 @@
1515 1535
 				CLANG_ANALYZER_NONNULL = YES;
1516 1536
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1517 1537
 				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1538
+				FRAMEWORK_SEARCH_PATHS = (
1539
+					"$(inherited)",
1540
+					"$(PROJECT_DIR)",
1541
+				);
1542
+				HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/**";
1518 1543
 				INFOPLIST_FILE = ReactNativeNavigationTests/Info.plist;
1519 1544
 				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
1520 1545
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1546
+				LIBRARY_SEARCH_PATHS = (
1547
+					"$(inherited)",
1548
+					"$(PROJECT_DIR)",
1549
+				);
1521 1550
 				OTHER_LDFLAGS = (
1522 1551
 					"-l\"c++\"",
1523 1552
 					"-ObjC",
@@ -1533,9 +1562,18 @@
1533 1562
 				CLANG_ANALYZER_NONNULL = YES;
1534 1563
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1535 1564
 				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1565
+				FRAMEWORK_SEARCH_PATHS = (
1566
+					"$(inherited)",
1567
+					"$(PROJECT_DIR)",
1568
+				);
1569
+				HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/**";
1536 1570
 				INFOPLIST_FILE = ReactNativeNavigationTests/Info.plist;
1537 1571
 				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
1538 1572
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1573
+				LIBRARY_SEARCH_PATHS = (
1574
+					"$(inherited)",
1575
+					"$(PROJECT_DIR)",
1576
+				);
1539 1577
 				OTHER_LDFLAGS = (
1540 1578
 					"-l\"c++\"",
1541 1579
 					"-ObjC",

+ 1
- 62
lib/ios/ReactNativeNavigationTests/RNNBottomTabOptionsTest.m 查看文件

@@ -14,67 +14,6 @@
14 14
 //	self.uut = [[RNNBottomTabOptions alloc] initEmptyOptions];
15 15
 }
16 16
 
17
-//- (void)test_tabBarTextFontFamily_validFont {
18
-//	UIViewController* viewController = [UIViewController new];
19
-//
20
-//	NSString* inputFont = @"HelveticaNeue";
21
-//	UIFont* expectedFont = [UIFont fontWithName:inputFont size:10];
22
-//
23
-//	self.uut.fontFamily = inputFont;
24
-//	self.uut.text = @"Tab 1";
25
-//
26
-//	[self.uut applyOn:viewController];
27
-//
28
-//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
29
-//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
30
-//}
31
-//
32
-//- (void)test_tabBarTextFontSize_withoutTextFontFamily_withoutTextColor {
33
-//	UIViewController* viewController = [UIViewController new];
34
-//
35
-//	UIFont* expectedFont = [UIFont systemFontOfSize:15];
36
-//
37
-//	self.uut.fontSize = @(15);
38
-//	self.uut.text = @"Tab 1";
39
-//
40
-//	[self.uut applyOn:viewController];
41
-//
42
-//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
43
-//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
44
-//}
45
-//
46
-//- (void)test_tabBarTextFontSize_withoutTextFontFamily {
47
-//	UIViewController* viewController = [UIViewController new];
48
-//	
49
-//	UIFont* expectedFont = [UIFont systemFontOfSize:15];
50
-//
51
-//	self.uut.fontSize = @(15);
52
-//	self.uut.text = @"Tab 1";
53
-//
54
-//	[self.uut applyOn:viewController];
55
-//
56
-//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
57
-//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
58
-//}
59
-//
60
-//- (void)test_tabBarTextFontSize_withTextFontFamily_withTextColor {
61
-//	UIViewController* viewController = [UIViewController new];
62
-//
63
-//	NSString* inputFont = @"HelveticaNeue";
64
-//	UIFont* expectedFont = [UIFont fontWithName:inputFont size:15];
65
-//
66
-//	self.uut.fontSize = @(15);
67
-//	self.uut.text = @"Tab 1";
68
-//	self.uut.fontFamily = inputFont;
69
-//	self.uut.textColor = @(4279979127);
70
-//	[self.uut applyOn:viewController];
71
-//
72
-//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
73
-//	UIColor* color = attributes[NSForegroundColorAttributeName];
74
-//	UIColor* expectedColor = [RCTConvert UIColor:@(4279979127)];
75
-//
76
-//	XCTAssertTrue([color isEqual:expectedColor]);
77
-//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
78
-//}
17
+
79 18
 
80 19
 @end

+ 81
- 0
lib/ios/ReactNativeNavigationTests/RNNBottomTabPresenterTest.m 查看文件

@@ -0,0 +1,81 @@
1
+#import <XCTest/XCTest.h>
2
+#import "RNNBottomTabPresenter.h"
3
+
4
+@interface RNNBottomTabPresenterTest : XCTestCase
5
+
6
+@property (nonatomic, strong) RNNBottomTabPresenter *uut;
7
+@property (nonatomic, strong) RNNNavigationOptions *options;
8
+@property (nonatomic, strong) id bindedViewController;
9
+
10
+@end
11
+
12
+@implementation RNNBottomTabPresenterTest
13
+
14
+- (void)setUp {
15
+    [super setUp];
16
+}
17
+
18
+//- (void)test_tabBarTextFontFamily_validFont {
19
+//	UIViewController* viewController = [UIViewController new];
20
+//
21
+//	NSString* inputFont = @"HelveticaNeue";
22
+//	UIFont* expectedFont = [UIFont fontWithName:inputFont size:10];
23
+//
24
+//	self.uut.fontFamily = inputFont;
25
+//	self.uut.text = @"Tab 1";
26
+//
27
+//	[self.uut rnn_set];
28
+//
29
+//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
30
+//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
31
+//}
32
+
33
+//- (void)test_tabBarTextFontSize_withoutTextFontFamily_withoutTextColor {
34
+//	UIViewController* viewController = [UIViewController new];
35
+//
36
+//	UIFont* expectedFont = [UIFont systemFontOfSize:15];
37
+//
38
+//	self.uut.fontSize = @(15);
39
+//	self.uut.text = @"Tab 1";
40
+//
41
+//	[self.uut applyOn:viewController];
42
+//
43
+//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
44
+//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
45
+//}
46
+//
47
+//- (void)test_tabBarTextFontSize_withoutTextFontFamily {
48
+//	UIViewController* viewController = [UIViewController new];
49
+//
50
+//	UIFont* expectedFont = [UIFont systemFontOfSize:15];
51
+//
52
+//	self.uut.fontSize = @(15);
53
+//	self.uut.text = @"Tab 1";
54
+//
55
+//	[self.uut applyOn:viewController];
56
+//
57
+//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
58
+//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
59
+//}
60
+//
61
+//- (void)test_tabBarTextFontSize_withTextFontFamily_withTextColor {
62
+//	UIViewController* viewController = [UIViewController new];
63
+//
64
+//	NSString* inputFont = @"HelveticaNeue";
65
+//	UIFont* expectedFont = [UIFont fontWithName:inputFont size:15];
66
+//
67
+//	self.uut.fontSize = @(15);
68
+//	self.uut.text = @"Tab 1";
69
+//	self.uut.fontFamily = inputFont;
70
+//	self.uut.textColor = @(4279979127);
71
+//	[self.uut applyOn:viewController];
72
+//
73
+//	NSDictionary* attributes = [viewController.tabBarItem titleTextAttributesForState:UIControlStateNormal];
74
+//	UIColor* color = attributes[NSForegroundColorAttributeName];
75
+//	UIColor* expectedColor = [RCTConvert UIColor:@(4279979127)];
76
+//
77
+//	XCTAssertTrue([color isEqual:expectedColor]);
78
+//	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
79
+//}
80
+
81
+@end

+ 0
- 70
lib/ios/ReactNativeNavigationTests/RNNBottomTabsOptionsTest.m 查看文件

@@ -1,70 +0,0 @@
1
-#import <XCTest/XCTest.h>
2
-#import "RNNBottomTabsOptions.h"
3
-
4
-@interface RNNBottomTabsOptionsTest : XCTestCase
5
-
6
-@property (nonatomic, retain) RNNBottomTabsOptions* uut;
7
-
8
-@end
9
-
10
-@implementation RNNBottomTabsOptionsTest
11
-
12
-- (void)setUp {
13
-    [super setUp];
14
-//	self.uut = [[RNNBottomTabsOptions alloc] initEmptyOptions];
15
-}
16
-
17
-//- (void)test_tabBarTranslucent_true {
18
-//	UITabBarController* tabBarController = [UITabBarController new];
19
-//	
20
-//	self.uut.translucent = @(1);
21
-//	[self.uut applyOnTabBarController:tabBarController];
22
-//	
23
-//	XCTAssertTrue(tabBarController.tabBar.translucent);
24
-//}
25
-//
26
-//- (void)test_tabBarTranslucent_false {
27
-//	UITabBarController* tabBarController = [UITabBarController new];
28
-//	
29
-//	self.uut.translucent = @(0);
30
-//	[self.uut applyOnTabBarController:tabBarController];
31
-//	
32
-//	XCTAssertFalse(tabBarController.tabBar.translucent);
33
-//}
34
-//
35
-//- (void)test_tabBarHideShadow_default {
36
-//	UITabBarController* tabBarController = [UITabBarController new];
37
-//	[self.uut applyOnTabBarController:tabBarController];
38
-//	
39
-//	XCTAssertFalse(tabBarController.tabBar.clipsToBounds);
40
-//}
41
-//
42
-//- (void)test_tabBarHideShadow_true {
43
-//	UITabBarController* tabBarController = [UITabBarController new];
44
-//	
45
-//	self.uut.hideShadow = @(1);
46
-//	[self.uut applyOnTabBarController:tabBarController];
47
-//	
48
-//	XCTAssertTrue(tabBarController.tabBar.clipsToBounds);
49
-//}
50
-//
51
-//- (void)test_tabBarHideShadow_false {
52
-//	UITabBarController* tabBarController = [UITabBarController new];
53
-//	
54
-//	self.uut.hideShadow = @(0);
55
-//	[self.uut applyOnTabBarController:tabBarController];
56
-//	
57
-//	XCTAssertFalse(tabBarController.tabBar.clipsToBounds);
58
-//}
59
-//
60
-//- (void)test_tabBarBackgroundColor {
61
-//	UITabBarController* tabBarController = [UITabBarController new];
62
-//	
63
-//	self.uut.backgroundColor = @(0xFFFF0000);
64
-//	[self.uut applyOnTabBarController:tabBarController];
65
-//	
66
-//	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
67
-//	XCTAssertTrue([tabBarController.tabBar.barTintColor isEqual:expectedColor]);
68
-//}
69
-
70
-@end

+ 56
- 0
lib/ios/ReactNativeNavigationTests/RNNNavigationControllerPresenterTest.m 查看文件

@@ -0,0 +1,56 @@
1
+#import <XCTest/XCTest.h>
2
+#import <OCMock/OCMock.h>
3
+#import "RNNNavigationControllerPresenter.h"
4
+#import "UINavigationController+RNNOptions.h"
5
+#import "RNNNavigationController.h"
6
+
7
+@interface RNNNavigationControllerPresenterTest : XCTestCase
8
+
9
+@property (nonatomic, strong) RNNNavigationControllerPresenter *uut;
10
+@property (nonatomic, strong) RNNNavigationOptions *options;
11
+@property (nonatomic, strong) id bindedViewController;
12
+
13
+@end
14
+
15
+@implementation RNNNavigationControllerPresenterTest
16
+
17
+- (void)setUp {
18
+    [super setUp];
19
+	self.uut = [[RNNNavigationControllerPresenter alloc] init];
20
+	self.bindedViewController = [OCMockObject partialMockForObject:[RNNNavigationController new]];
21
+	[self.uut bindViewController:self.bindedViewController];
22
+	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
23
+}
24
+
25
+- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withDefaultValues {
26
+	[[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:nil];
27
+	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
28
+	[_bindedViewController verify];
29
+}
30
+
31
+- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withIcon {
32
+    Image* image = [[Image alloc] initWithValue:[UIImage new]];
33
+    self.options.topBar.backButton.icon = image;
34
+	[[_bindedViewController expect] rnn_setBackButtonIcon:image.get withColor:nil title:nil];
35
+	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
36
+	[_bindedViewController verify];
37
+}
38
+
39
+- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withTitle {
40
+    Text* title = [[Text alloc] initWithValue:@"Title"];
41
+    self.options.topBar.backButton.title = title;
42
+    [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:title.get];
43
+    [self.uut applyOptionsOnWillMoveToParentViewController:self.options];
44
+    [_bindedViewController verify];
45
+}
46
+
47
+- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withHideTitle {
48
+    Text* title = [[Text alloc] initWithValue:@"Title"];
49
+    self.options.topBar.backButton.title = title;
50
+    self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)];
51
+    [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:@""];
52
+    [self.uut applyOptionsOnWillMoveToParentViewController:self.options];
53
+    [_bindedViewController verify];
54
+}
55
+
56
+@end

+ 164
- 1
lib/ios/ReactNativeNavigationTests/RNNTabBarControllerTest.m 查看文件

@@ -1,7 +1,9 @@
1 1
 #import <XCTest/XCTest.h>
2 2
 #import "RNNTabBarController.h"
3 3
 #import "RNNNavigationOptions.h"
4
-#import "RNNViewControllerPresenter.h"
4
+#import "RNNTabBarPresenter.h"
5
+#import "RNNRootViewController.h"
6
+#import <OCMock/OCMock.h>
5 7
 
6 8
 @interface RNNTabBarControllerTest : XCTestCase
7 9
 
@@ -29,5 +31,166 @@
29 31
 	XCTAssertTrue(self.uut.viewControllers.count == 2);
30 32
 }
31 33
 
34
+- (void)testInitWithLayoutInfo_shouldInitializeDependencies {
35
+	RNNLayoutInfo* layoutInfo = [RNNLayoutInfo new];
36
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
37
+	RNNTabBarPresenter* presenter = [[RNNTabBarPresenter alloc] init];
38
+	NSArray* childViewControllers = @[[UIViewController new]];
39
+	
40
+	self.uut = [[RNNTabBarController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options presenter:presenter];
41
+	XCTAssertTrue(self.uut.layoutInfo == layoutInfo);
42
+	XCTAssertTrue(self.uut.options == options);
43
+	XCTAssertTrue(self.uut.presenter == presenter);
44
+	XCTAssertTrue(self.uut.childViewControllers.count == childViewControllers.count);
45
+}
46
+
47
+- (void)testInitWithEventEmmiter_shouldInitializeDependencies {
48
+	RNNLayoutInfo* layoutInfo = [RNNLayoutInfo new];
49
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
50
+	RNNTabBarPresenter* presenter = [[RNNTabBarPresenter alloc] init];
51
+	RNNEventEmitter* eventEmmiter = [RNNEventEmitter new];
52
+
53
+	NSArray* childViewControllers = @[[UIViewController new]];
54
+	
55
+	self.uut = [[RNNTabBarController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options presenter:presenter eventEmitter:eventEmmiter];
56
+	XCTAssertTrue(self.uut.layoutInfo == layoutInfo);
57
+	XCTAssertTrue(self.uut.options == options);
58
+	XCTAssertTrue(self.uut.presenter == presenter);
59
+	XCTAssertTrue(self.uut.childViewControllers.count == childViewControllers.count);
60
+	XCTAssertTrue(self.uut.eventEmitter == eventEmmiter);
61
+}
62
+
63
+- (void)testInitWithLayoutInfo_shouldSetDelegate {
64
+	self.uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:[[RNNNavigationOptions alloc] initWithDict:@{}] presenter:[[RNNViewControllerPresenter alloc] init]];
65
+	
66
+	XCTAssertTrue(self.uut.delegate == self.uut);
67
+}
68
+
69
+- (void)testWillMoveToParent_invokePresenterApplyOptionsOnWillMoveToParent {
70
+	id presenterMock = [OCMockObject partialMockForObject:[RNNTabBarPresenter new]];
71
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
72
+	self.uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:presenterMock];
73
+
74
+	[[presenterMock expect] applyOptionsOnWillMoveToParentViewController:options];
75
+	[self.uut willMoveToParentViewController:[UIViewController new]];
76
+	[presenterMock verify];
77
+}
78
+
79
+- (void)testWillMoveToParent_shouldNotInvokePresenterApplyOptionsOnWillMoveToNilParent {
80
+	id presenterMock = [OCMockObject partialMockForObject:[RNNTabBarPresenter new]];
81
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
82
+	self.uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:presenterMock];
83
+	
84
+	[[presenterMock reject] applyOptionsOnWillMoveToParentViewController:options];
85
+	[self.uut willMoveToParentViewController:nil];
86
+	[presenterMock verify];
87
+}
88
+
89
+- (void)testOnChildAppear_shouldInvokePresenterApplyOptionsWithResolvedOptions {
90
+	id presenterMock = [OCMockObject partialMockForObject:[RNNTabBarPresenter new]];
91
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
92
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:presenterMock];
93
+	
94
+	[[presenterMock expect] applyOptions:[OCMArg any]];
95
+	[uut onChildWillAppear];
96
+	[presenterMock verify];
97
+}
98
+
99
+- (void)testMergeOptions_shouldInvokePresenterMergeOptions {
100
+	id presenterMock = [OCMockObject partialMockForObject:[RNNTabBarPresenter new]];
101
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
102
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:presenterMock];
103
+	
104
+	[(RNNTabBarPresenter *)[presenterMock expect] mergeOptions:options resolvedOptions:nil];
105
+	[uut mergeOptions:options];
106
+	[presenterMock verify];
107
+}
108
+
109
+- (void)testMergeOptions_shouldInvokeParentMergeOptions {
110
+	id parentMock = [OCMockObject partialMockForObject:[RNNTabBarController new]];
111
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
112
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:[RNNTabBarPresenter new]];
113
+	[parentMock addChildViewController:uut];
114
+	
115
+	[(RNNTabBarController *)[parentMock expect] mergeOptions:options];
116
+	[uut mergeOptions:options];
117
+	[parentMock verify];
118
+}
119
+
120
+- (void)testOnChildAppear_shouldInvokeParentOnChildAppear {
121
+	id parentMock = [OCMockObject partialMockForObject:[RNNTabBarController new]];
122
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
123
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:nil options:options presenter:[RNNTabBarPresenter new]];
124
+	[parentMock addChildViewController:uut];
125
+	
126
+	[[parentMock expect] onChildWillAppear];
127
+	[uut onChildWillAppear];
128
+	[parentMock verify];
129
+}
130
+
131
+- (void)testGetCurrentChild_shouldInvokeSelectedViewControllerGetCurrentChild {
132
+	id childMock = [OCMockObject partialMockForObject:[RNNRootViewController new]];
133
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
134
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[childMock] options:options presenter:[RNNTabBarPresenter new]];
135
+	
136
+	[[childMock expect] getCurrentChild];
137
+	[uut getCurrentChild];
138
+	[childMock verify];
139
+}
140
+
141
+- (void)testGetCurrentChild_shouldInvokeOnSelectedViewController {
142
+	id childMock = [OCMockObject partialMockForObject:[RNNRootViewController new]];
143
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
144
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[[UIViewController new], childMock] options:options presenter:[RNNTabBarPresenter new]];
145
+	[uut setSelectedIndex:1];
146
+	
147
+	[[childMock expect] getCurrentChild];
148
+	[uut getCurrentChild];
149
+	[childMock verify];
150
+}
151
+
152
+- (void)testPreferredStatusBarStyle_shouldInvokeSelectedViewControllerPreferredStatusBarStyle {
153
+	id childMock = [OCMockObject partialMockForObject:[RNNRootViewController new]];
154
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
155
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[childMock] options:options presenter:[RNNTabBarPresenter new]];
156
+	
157
+	[[childMock expect] preferredStatusBarStyle];
158
+	[uut preferredStatusBarStyle];
159
+	[childMock verify];
160
+}
161
+
162
+- (void)testPreferredStatusBarStyle_shouldInvokeOnSelectedViewController {
163
+	id childMock = [OCMockObject partialMockForObject:[RNNRootViewController new]];
164
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
165
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[[UIViewController new], childMock] options:options presenter:[RNNTabBarPresenter new]];
166
+	[uut setSelectedIndex:1];
167
+	
168
+	[[childMock expect] preferredStatusBarStyle];
169
+	[uut preferredStatusBarStyle];
170
+	[childMock verify];
171
+}
172
+
173
+- (void)testTabBarControllerDidSelectViewControllerDelegate_shouldInvokeSendBottomTabSelectedEvent {
174
+	id eventEmmiterMock = [OCMockObject partialMockForObject:[RNNEventEmitter new]];
175
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{}];
176
+	UIViewController* vc = [UIViewController new];
177
+	UIViewController* vc2 = [UIViewController new];
178
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[vc, vc2] options:options presenter:[RNNTabBarPresenter new] eventEmitter:eventEmmiterMock];
179
+	[uut setSelectedIndex:1];
180
+	[[eventEmmiterMock expect] sendBottomTabSelected:[OCMArg any] unselected:[OCMArg any]];
181
+	[uut tabBarController:uut didSelectViewController:vc2];
182
+	[eventEmmiterMock verify];
183
+}
184
+
185
+- (void)testSetSelectedIndexByComponentID_ShouldSetSelectedIndexWithCorrectIndex {
186
+	RNNLayoutInfo* layoutInfo = [RNNLayoutInfo new];
187
+	layoutInfo.componentId = @"componentId";
188
+	
189
+	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:nil eventEmitter:nil presenter:nil options:nil];
190
+	
191
+	RNNTabBarController* uut = [[RNNTabBarController alloc] initWithLayoutInfo:nil childViewControllers:@[[UIViewController new], vc] options:nil presenter:[RNNTabBarPresenter new]];
192
+	[uut setSelectedIndexByComponentID:@"componentId"];
193
+	XCTAssertTrue(uut.selectedIndex == 1);
194
+}
32 195
 
33 196
 @end

+ 48
- 0
lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m 查看文件

@@ -0,0 +1,48 @@
1
+#import <XCTest/XCTest.h>
2
+#import "UITabBarController+RNNOptions.h"
3
+
4
+@interface UITabBarController_RNNOptionsTest : XCTestCase
5
+
6
+@property (nonatomic, retain) UITabBarController* uut;
7
+
8
+@end
9
+
10
+@implementation UITabBarController_RNNOptionsTest
11
+
12
+- (void)setUp {
13
+    [super setUp];
14
+	self.uut = [UITabBarController new];
15
+}
16
+
17
+- (void)test_tabBarTranslucent_true {
18
+	[self.uut rnn_setTabBarTranslucent:YES];
19
+	XCTAssertTrue(self.uut.tabBar.translucent);
20
+}
21
+
22
+- (void)test_tabBarTranslucent_false {
23
+	[self.uut rnn_setTabBarTranslucent:NO];
24
+	XCTAssertFalse(self.uut.tabBar.translucent);
25
+}
26
+
27
+- (void)test_tabBarHideShadow_default {
28
+	XCTAssertFalse(self.uut.tabBar.clipsToBounds);
29
+}
30
+
31
+- (void)test_tabBarHideShadow_true {
32
+	[self.uut rnn_setTabBarHideShadow:YES];
33
+	XCTAssertTrue(self.uut.tabBar.clipsToBounds);
34
+}
35
+
36
+- (void)test_tabBarHideShadow_false {
37
+	[self.uut rnn_setTabBarHideShadow:NO];
38
+	XCTAssertFalse(self.uut.tabBar.clipsToBounds);
39
+}
40
+
41
+- (void)test_tabBarBackgroundColor {
42
+	UIColor* tabBarBackgroundColor = [UIColor redColor];
43
+
44
+	[self.uut rnn_setTabBarBackgroundColor:tabBarBackgroundColor];
45
+	XCTAssertTrue([self.uut.tabBar.barTintColor isEqual:tabBarBackgroundColor]);
46
+}
47
+
48
+@end

+ 16
- 0
lib/ios/ReactNativeNavigationTests/UIViewController+RNNOptionsTest.m 查看文件

@@ -0,0 +1,16 @@
1
+#import <XCTest/XCTest.h>
2
+#import "UIViewController+RNNOptions.h"
3
+
4
+@interface UIViewController_RNNOptionsTest : XCTestCase
5
+
6
+@property (nonatomic, retain) UIViewController* uut;
7
+
8
+@end
9
+
10
+@implementation UIViewController_RNNOptionsTest
11
+
12
+- (void)setUp {
13
+    [super setUp];
14
+}
15
+
16
+@end

二進制
lib/ios/libOCMock.a 查看文件