2015-07-13 15:16:29 +00:00
|
|
|
/**
|
2017-05-06 03:50:47 +00:00
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
2015-07-13 15:16:29 +00:00
|
|
|
*
|
2018-02-17 02:24:55 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2015-07-13 15:16:29 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
#import <XCTest/XCTest.h>
|
2016-11-24 17:44:51 +00:00
|
|
|
|
|
|
|
#import <React/RCTUIManager.h>
|
|
|
|
#import <React/UIView+React.h>
|
2015-07-13 15:16:29 +00:00
|
|
|
|
|
|
|
@interface RCTUIManager (Testing)
|
|
|
|
|
|
|
|
- (void)_manageChildren:(NSNumber *)containerReactTag
|
2015-07-17 10:53:15 +00:00
|
|
|
moveFromIndices:(NSArray *)moveFromIndices
|
|
|
|
moveToIndices:(NSArray *)moveToIndices
|
2015-07-13 15:16:29 +00:00
|
|
|
addChildReactTags:(NSArray *)addChildReactTags
|
|
|
|
addAtIndices:(NSArray *)addAtIndices
|
|
|
|
removeAtIndices:(NSArray *)removeAtIndices
|
2015-11-14 18:25:00 +00:00
|
|
|
registry:(NSMutableDictionary<NSNumber *, id<RCTComponent>> *)registry;
|
2015-07-13 15:16:29 +00:00
|
|
|
|
2015-11-14 18:25:00 +00:00
|
|
|
@property (nonatomic, readonly) NSMutableDictionary<NSNumber *, UIView *> *viewRegistry;
|
2015-07-13 15:16:29 +00:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface RCTUIManagerScenarioTests : XCTestCase
|
|
|
|
|
|
|
|
@property (nonatomic, readwrite, strong) RCTUIManager *uiManager;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation RCTUIManagerScenarioTests
|
|
|
|
|
|
|
|
- (void)setUp
|
|
|
|
{
|
|
|
|
[super setUp];
|
|
|
|
|
2015-08-17 14:35:34 +00:00
|
|
|
_uiManager = [RCTUIManager new];
|
2015-07-13 15:16:29 +00:00
|
|
|
|
|
|
|
// Register 20 views to use in the tests
|
|
|
|
for (NSInteger i = 1; i <= 20; i++) {
|
2015-08-17 14:35:34 +00:00
|
|
|
UIView *registeredView = [UIView new];
|
2015-08-24 10:14:33 +00:00
|
|
|
registeredView.reactTag = @(i);
|
2015-11-14 18:25:00 +00:00
|
|
|
_uiManager.viewRegistry[@(i)] = registeredView;
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
- (void)testManagingChildrenToAddViews
|
2015-07-13 15:16:29 +00:00
|
|
|
{
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *containerView = _uiManager.viewRegistry[@20];
|
2015-07-17 10:53:15 +00:00
|
|
|
NSMutableArray *addedViews = [NSMutableArray array];
|
2015-07-13 15:16:29 +00:00
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
NSArray *tagsToAdd = @[@1, @2, @3, @4, @5];
|
|
|
|
NSArray *addAtIndices = @[@0, @1, @2, @3, @4];
|
|
|
|
for (NSNumber *tag in tagsToAdd) {
|
|
|
|
[addedViews addObject:_uiManager.viewRegistry[tag]];
|
|
|
|
}
|
2015-07-13 15:16:29 +00:00
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
// Add views 1-5 to view 20
|
|
|
|
[_uiManager _manageChildren:@20
|
|
|
|
moveFromIndices:nil
|
|
|
|
moveToIndices:nil
|
|
|
|
addChildReactTags:tagsToAdd
|
|
|
|
addAtIndices:addAtIndices
|
|
|
|
removeAtIndices:nil
|
2015-11-14 18:25:00 +00:00
|
|
|
registry:(NSMutableDictionary<NSNumber *, id<RCTComponent>> *)_uiManager.viewRegistry];
|
2015-07-17 10:53:15 +00:00
|
|
|
|
2016-06-07 19:33:58 +00:00
|
|
|
[_uiManager.viewRegistry[@20] didUpdateReactSubviews];
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
XCTAssertTrue([[containerView reactSubviews] count] == 5,
|
|
|
|
@"Expect to have 5 react subviews after calling manage children \
|
|
|
|
with 5 tags to add, instead have %lu", (unsigned long)[[containerView reactSubviews] count]);
|
|
|
|
for (UIView *view in addedViews) {
|
|
|
|
XCTAssertTrue([view superview] == containerView,
|
|
|
|
@"Expected to have manage children successfully add children");
|
|
|
|
[view removeFromSuperview];
|
|
|
|
}
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
- (void)testManagingChildrenToRemoveViews
|
2015-07-13 15:16:29 +00:00
|
|
|
{
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *containerView = _uiManager.viewRegistry[@20];
|
2015-07-17 10:53:15 +00:00
|
|
|
NSMutableArray *removedViews = [NSMutableArray array];
|
2015-07-13 15:16:29 +00:00
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
NSArray *removeAtIndices = @[@0, @4, @8, @12, @16];
|
|
|
|
for (NSNumber *index in removeAtIndices) {
|
2015-08-24 10:14:33 +00:00
|
|
|
NSNumber *reactTag = @(index.integerValue + 2);
|
2015-07-17 10:53:15 +00:00
|
|
|
[removedViews addObject:_uiManager.viewRegistry[reactTag]];
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
2015-07-17 10:53:15 +00:00
|
|
|
for (NSInteger i = 2; i < 20; i++) {
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *view = _uiManager.viewRegistry[@(i)];
|
2016-06-07 15:36:07 +00:00
|
|
|
[containerView insertReactSubview:view atIndex:containerView.reactSubviews.count];
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
// Remove views 1-5 from view 20
|
|
|
|
[_uiManager _manageChildren:@20
|
|
|
|
moveFromIndices:nil
|
|
|
|
moveToIndices:nil
|
|
|
|
addChildReactTags:nil
|
|
|
|
addAtIndices:nil
|
|
|
|
removeAtIndices:removeAtIndices
|
2015-11-14 18:25:00 +00:00
|
|
|
registry:(NSMutableDictionary<NSNumber *, id<RCTComponent>> *)_uiManager.viewRegistry];
|
2015-07-17 10:53:15 +00:00
|
|
|
|
2016-06-07 19:33:58 +00:00
|
|
|
[_uiManager.viewRegistry[@20] didUpdateReactSubviews];
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
XCTAssertEqual(containerView.reactSubviews.count, (NSUInteger)13,
|
|
|
|
@"Expect to have 13 react subviews after calling manage children\
|
|
|
|
with 5 tags to remove and 18 prior children, instead have %zd",
|
|
|
|
containerView.reactSubviews.count);
|
|
|
|
for (UIView *view in removedViews) {
|
|
|
|
XCTAssertTrue([view superview] == nil,
|
|
|
|
@"Expected to have manage children successfully remove children");
|
|
|
|
// After removing views are unregistered - we need to reregister
|
|
|
|
_uiManager.viewRegistry[view.reactTag] = view;
|
|
|
|
}
|
|
|
|
for (NSInteger i = 2; i < 20; i++) {
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *view = _uiManager.viewRegistry[@(i)];
|
2015-07-17 10:53:15 +00:00
|
|
|
if (![removedViews containsObject:view]) {
|
|
|
|
XCTAssertTrue([view superview] == containerView,
|
|
|
|
@"Should not have removed view with react tag %ld during delete but did", (long)i);
|
|
|
|
[view removeFromSuperview];
|
|
|
|
}
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
// We want to start with views 1-10 added at indices 0-9
|
|
|
|
// Then we'll remove indices 2, 3, 5 and 8
|
|
|
|
// Add views 11 and 12 to indices 0 and 6
|
|
|
|
// And move indices 4 and 9 to 1 and 7
|
|
|
|
// So in total it goes from:
|
|
|
|
// [1,2,3,4,5,6,7,8,9,10]
|
|
|
|
// to
|
|
|
|
// [11,5,1,2,7,8,12,10]
|
|
|
|
- (void)testManagingChildrenToAddRemoveAndMove
|
2015-07-13 15:16:29 +00:00
|
|
|
{
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *containerView = _uiManager.viewRegistry[@20];
|
2015-07-17 10:53:15 +00:00
|
|
|
|
|
|
|
NSArray *removeAtIndices = @[@2, @3, @5, @8];
|
|
|
|
NSArray *addAtIndices = @[@0, @6];
|
|
|
|
NSArray *tagsToAdd = @[@11, @12];
|
|
|
|
NSArray *moveFromIndices = @[@4, @9];
|
|
|
|
NSArray *moveToIndices = @[@1, @7];
|
|
|
|
|
|
|
|
// We need to keep these in array to keep them around
|
|
|
|
NSMutableArray *viewsToRemove = [NSMutableArray array];
|
|
|
|
for (NSUInteger i = 0; i < removeAtIndices.count; i++) {
|
|
|
|
NSNumber *reactTagToRemove = @([removeAtIndices[i] integerValue] + 1);
|
|
|
|
UIView *viewToRemove = _uiManager.viewRegistry[reactTagToRemove];
|
|
|
|
[viewsToRemove addObject:viewToRemove];
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
for (NSInteger i = 1; i < 11; i++) {
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *view = _uiManager.viewRegistry[@(i)];
|
2016-06-07 15:36:07 +00:00
|
|
|
[containerView insertReactSubview:view atIndex:containerView.reactSubviews.count];
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
[_uiManager _manageChildren:@20
|
|
|
|
moveFromIndices:moveFromIndices
|
|
|
|
moveToIndices:moveToIndices
|
|
|
|
addChildReactTags:tagsToAdd
|
|
|
|
addAtIndices:addAtIndices
|
|
|
|
removeAtIndices:removeAtIndices
|
2015-11-14 18:25:00 +00:00
|
|
|
registry:(NSMutableDictionary<NSNumber *, id<RCTComponent>> *)_uiManager.viewRegistry];
|
2015-07-17 10:53:15 +00:00
|
|
|
|
|
|
|
XCTAssertTrue([[containerView reactSubviews] count] == 8,
|
|
|
|
@"Expect to have 8 react subviews after calling manage children,\
|
|
|
|
instead have the following subviews %@", [containerView reactSubviews]);
|
|
|
|
|
|
|
|
NSArray *expectedReactTags = @[@11, @5, @1, @2, @7, @8, @12, @10];
|
|
|
|
for (NSUInteger i = 0; i < containerView.subviews.count; i++) {
|
|
|
|
XCTAssertEqualObjects([[containerView reactSubviews][i] reactTag], expectedReactTags[i],
|
|
|
|
@"Expected subview at index %ld to have react tag #%@ but has tag #%@",
|
|
|
|
(long)i, expectedReactTags[i], [[containerView reactSubviews][i] reactTag]);
|
|
|
|
}
|
2015-07-13 15:16:29 +00:00
|
|
|
|
2015-07-17 10:53:15 +00:00
|
|
|
// Clean up after ourselves
|
|
|
|
for (NSInteger i = 1; i < 13; i++) {
|
2015-11-14 18:25:00 +00:00
|
|
|
UIView *view = _uiManager.viewRegistry[@(i)];
|
2015-07-17 10:53:15 +00:00
|
|
|
[view removeFromSuperview];
|
|
|
|
}
|
|
|
|
for (UIView *view in viewsToRemove) {
|
|
|
|
_uiManager.viewRegistry[view.reactTag] = view;
|
2015-07-13 15:16:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|