From 4beef5bec35cfcb949c78d3fb24d2d4b17cbbbe5 Mon Sep 17 00:00:00 2001 From: Alex Akers Date: Mon, 13 Jul 2015 08:16:29 -0700 Subject: [PATCH] [React Native] Re-enable testScenario{1,2} Summary: The tests are passing locally. Not sure why they weren't passing on FB CI. --- .../UIExplorer.xcodeproj/project.pbxproj | 4 + .../RCTUIManagerScenarioTests.m | 437 ++++++++++++++++++ .../UIExplorerUnitTests/RCTUIManagerTests.m | 348 -------------- 3 files changed, 441 insertions(+), 348 deletions(-) create mode 100644 Examples/UIExplorer/UIExplorerIntegrationTests/RCTUIManagerScenarioTests.m diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj index 5b1d0d240..4897cb72e 100644 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj +++ b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; }; + 83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; }; D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; }; /* End PBXBuildFile section */ @@ -202,6 +203,7 @@ 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = ""; }; 357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; }; 58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = ""; }; + 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = ""; }; D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ @@ -383,6 +385,7 @@ children = ( 141FC1201B222EBB004D5FFB /* IntegrationTests.m */, 143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */, + 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */, 143BC5971B21E3E100462512 /* Supporting Files */, ); path = UIExplorerIntegrationTests; @@ -797,6 +800,7 @@ buildActionMask = 2147483647; files = ( 141FC1211B222EBB004D5FFB /* IntegrationTests.m in Sources */, + 83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */, 143BC5A11B21E45C00462512 /* UIExplorerSnapshotTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/RCTUIManagerScenarioTests.m b/Examples/UIExplorer/UIExplorerIntegrationTests/RCTUIManagerScenarioTests.m new file mode 100644 index 000000000..60c238b88 --- /dev/null +++ b/Examples/UIExplorer/UIExplorerIntegrationTests/RCTUIManagerScenarioTests.m @@ -0,0 +1,437 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#import +#import + +#import "RCTShadowView.h" +#import "RCTUIManager.h" +#import "RCTRootView.h" +#import "RCTSparseArray.h" +#import "UIView+React.h" + +@interface RCTUIManager (Testing) + +- (void)_manageChildren:(NSNumber *)containerReactTag + addChildReactTags:(NSArray *)addChildReactTags + addAtIndices:(NSArray *)addAtIndices + removeAtIndices:(NSArray *)removeAtIndices + registry:(RCTSparseArray *)registry; + +- (void)modifyManageChildren:(NSNumber *)containerReactTag + addChildReactTags:(NSMutableArray *)mutableAddChildReactTags + addAtIndices:(NSMutableArray *)mutableAddAtIndices + removeAtIndices:(NSMutableArray *)mutableRemoveAtIndices; + +- (void)createView:(NSNumber *)reactTag + viewName:(NSString *)viewName + rootTag:(NSNumber *)rootTag + props:(NSDictionary *)props; + +- (void)updateView:(NSNumber *)reactTag + viewName:(NSString *)viewName + props:(NSDictionary *)props; + +- (void)manageChildren:(NSNumber *)containerReactTag + moveFromIndices:(NSArray *)moveFromIndices + moveToIndices:(NSArray *)moveToIndices + addChildReactTags:(NSArray *)addChildReactTags + addAtIndices:(NSArray *)addAtIndices + removeAtIndices:(NSArray *)removeAtIndices; + +- (void)flushUIBlocks; + +@property (nonatomic, readonly) RCTSparseArray *viewRegistry; +@property (nonatomic, readonly) RCTSparseArray *shadowViewRegistry; // RCT thread only + +@end + +@interface RCTUIManagerScenarioTests : XCTestCase + +@property (nonatomic, readwrite, strong) RCTUIManager *uiManager; + +@end + +@implementation RCTUIManagerScenarioTests + +- (void)setUp +{ + [super setUp]; + + _uiManager = [[RCTUIManager alloc] init]; + + // Register 20 views to use in the tests + for (NSInteger i = 1; i <= 20; i++) { + UIView *registeredView = [[UIView alloc] init]; + [registeredView setReactTag:@(i)]; + _uiManager.viewRegistry[i] = registeredView; + + RCTShadowView *registeredShadowView = [[RCTShadowView alloc] init]; + registeredShadowView.viewName = @"RCTView"; + [registeredShadowView setReactTag:@(i)]; + _uiManager.shadowViewRegistry[i] = registeredShadowView; + } +} + +/* +-----------------------------------------------------------+ +----------------------+ + * | Shadow Hierarchy | | Legend | + * +-----------------------------------------------------------+ +----------------------+ + * | | | | + * | +---+ ****** | | ******************** | + * | | 1 | * 11 * | | * Layout-only View * | + * | +---+ ****** | | ******************** | + * | | | | | | + * | +-------+---+---+----------+ +---+---+ | | +----+ | + * | | | | | | | | | |View| Subview | + * | v v v v v v | | +----+ -----------> | + * | ***** +---+ ***** +---+ +----+ +----+ | | | + * | * 2 * | 3 | * 4 * | 5 | | 12 | | 13 | | +----------------------+ + * | ***** +---+ ***** +---+ +----+ +----+ | + * | | | | | + * | +---+--+ | +---+---+ | + * | | | | | | | + * | v v v v v | + * | +---+ +---+ +---+ +---+ ****** | + * | | 6 | | 7 | | 8 | | 9 | * 10 * | + * | +---+ +---+ +---+ +---+ ****** | + * | | + * +-----------------------------------------------------------+ + * + * +-----------------------------------------------------------+ + * | View Hierarchy | + * +-----------------------------------------------------------+ + * | | + * | +---+ ****** | + * | | 1 | * 11 * | + * | +---+ ****** | + * | | | | + * | +------+------+------+------+ +---+---+ | + * | | | | | | | | | + * | v v v v v v v | + * | +---+ +---+ +---+ +---+ +---+ +----+ +----+ | + * | | 6 | | 7 | | 3 | | 8 | | 5 | | 12 | | 13 | | + * | +---+ +---+ +---+ +---+ +---+ +----+ +----+ | + * | | | + * | v | + * | +---+ | + * | | 9 | | + * | +---+ | + * | | + * +-----------------------------------------------------------+ + */ + +- (void)updateShadowViewWithReactTag:(NSNumber *)reactTag layoutOnly:(BOOL)isLayoutOnly childTags:(NSArray *)childTags +{ + RCTShadowView *shadowView = _uiManager.shadowViewRegistry[reactTag]; + shadowView.allProps = isLayoutOnly ? @{} : @{@"collapsible": @NO}; + [childTags enumerateObjectsUsingBlock:^(NSNumber *childTag, NSUInteger idx, __unused BOOL *stop) { + [shadowView insertReactSubview:_uiManager.shadowViewRegistry[childTag] atIndex:idx]; + }]; +} + +- (void)setUpShadowViewHierarchy +{ + [self updateShadowViewWithReactTag:@1 layoutOnly:NO childTags:@[@2, @3, @4, @5]]; + [self updateShadowViewWithReactTag:@2 layoutOnly:YES childTags:@[@6, @7]]; + [self updateShadowViewWithReactTag:@3 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@4 layoutOnly:YES childTags:@[@8]]; + [self updateShadowViewWithReactTag:@5 layoutOnly:NO childTags:@[@9, @10]]; + [self updateShadowViewWithReactTag:@6 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@7 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@8 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@9 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@10 layoutOnly:YES childTags:nil]; + [self updateShadowViewWithReactTag:@11 layoutOnly:YES childTags:@[@12, @13]]; + [self updateShadowViewWithReactTag:@12 layoutOnly:NO childTags:nil]; + [self updateShadowViewWithReactTag:@13 layoutOnly:NO childTags:nil]; +} + +- (void)testModifyIndices1 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[@2] mutableCopy]; + NSMutableArray *addIndices = [@[@3] mutableCopy]; + NSMutableArray *removeIndices = [@[@0] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[@6, @7])); + XCTAssertEqualObjects(addIndices, (@[@3, @4])); + XCTAssertEqualObjects(removeIndices, (@[@0, @1])); +} + +- (void)testModifyIndices2 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[@11] mutableCopy]; + NSMutableArray *addIndices = [@[@4] mutableCopy]; + NSMutableArray *removeIndices = [@[] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[@12, @13])); + XCTAssertEqualObjects(addIndices, (@[@5, @6])); + XCTAssertEqualObjects(removeIndices, (@[])); +} + +- (void)testModifyIndices3 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[] mutableCopy]; + NSMutableArray *addIndices = [@[] mutableCopy]; + NSMutableArray *removeIndices = [@[@2] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[])); + XCTAssertEqualObjects(addIndices, (@[])); + XCTAssertEqualObjects(removeIndices, (@[@3])); +} + +- (void)testModifyIndices4 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[@11] mutableCopy]; + NSMutableArray *addIndices = [@[@3] mutableCopy]; + NSMutableArray *removeIndices = [@[@2] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[@12, @13])); + XCTAssertEqualObjects(addIndices, (@[@4, @5])); + XCTAssertEqualObjects(removeIndices, (@[@3])); +} + +- (void)testModifyIndices5 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[] mutableCopy]; + NSMutableArray *addIndices = [@[] mutableCopy]; + NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[])); + XCTAssertEqualObjects(addIndices, (@[])); + XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4])); +} + +- (void)testModifyIndices6 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[@11] mutableCopy]; + NSMutableArray *addIndices = [@[@0] mutableCopy]; + NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[@12, @13])); + XCTAssertEqualObjects(addIndices, (@[@0, @1])); + XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4])); +} + +- (void)testModifyIndices7 +{ + [self setUpShadowViewHierarchy]; + + NSMutableArray *addTags = [@[@11] mutableCopy]; + NSMutableArray *addIndices = [@[@1] mutableCopy]; + NSMutableArray *removeIndices = [@[@0, @2, @3] mutableCopy]; + [self.uiManager modifyManageChildren:@1 + addChildReactTags:addTags + addAtIndices:addIndices + removeAtIndices:removeIndices]; + XCTAssertEqualObjects(addTags, (@[@12, @13])); + XCTAssertEqualObjects(addIndices, (@[@1, @2])); + XCTAssertEqualObjects(removeIndices, (@[@0, @1, @3, @4])); +} + +- (void)testScenario1 +{ + RCTUIManager *uiManager = [[RCTUIManager alloc] init]; + RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil]; + NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"]; + + __block BOOL done = NO; + + dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"]; + dispatch_async(shadowQueue, ^{ + // Make sure root view finishes loading. + dispatch_sync(dispatch_get_main_queue(), ^{}); + + /* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; + /* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; + /* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}]; + /* V */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"blue",@"height":@50,@"width":@50}]; + /* */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}]; + /* V */[uiManager createView:@7 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@10,@"margin":@50}]; + /* V */[uiManager createView:@8 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"yellow",@"height":@50}]; + /* V */[uiManager createView:@9 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}]; + /* */[uiManager createView:@10 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}]; + /* */[uiManager manageChildren:@9 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@10] addAtIndices:@[@0] removeAtIndices:nil]; + /* V */[uiManager createView:@12 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"green",@"height":@50}]; + /* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8,@9,@12] addAtIndices:@[@0,@1,@2] removeAtIndices:nil]; + /* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil]; + /* V */[uiManager createView:@13 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"red",@"height":@50,@"width":@50}]; + /* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5,@6,@13] addAtIndices:@[@0,@1,@2] removeAtIndices:nil]; + /* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil]; + + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + + done = NO; + dispatch_async(shadowQueue, ^{ + [uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}]; + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)7); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + + done = NO; + dispatch_async(shadowQueue, ^{ + [uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":@10}]; + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } +} + +- (void)testScenario2 +{ + RCTUIManager *uiManager = [[RCTUIManager alloc] init]; + RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil]; + NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"]; + + __block BOOL done = NO; + + dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"]; + dispatch_async(shadowQueue, ^{ + // Make sure root view finishes loading. + dispatch_sync(dispatch_get_main_queue(), ^{}); + + /* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; + /* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; + /* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}]; + /* */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}]; + /* V */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@1}]; + /* V */[uiManager createView:@7 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}]; + /* */[uiManager createView:@8 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}]; + /* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@5 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@6] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil]; + /* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil]; + + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + + done = NO; + dispatch_async(shadowQueue, ^{ + [uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}]; + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)3); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + + done = NO; + dispatch_async(shadowQueue, ^{ + [uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":@1}]; + [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { + XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); + XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4); + done = YES; + }]; + + [uiManager flushUIBlocks]; + }); + + date = [NSDate dateWithTimeIntervalSinceNow:1.0]; + while ([date timeIntervalSinceNow] > 0 && !done) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } +} + +@end diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m index db4118a68..6b788fad1 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m @@ -16,29 +16,6 @@ removeAtIndices:(NSArray *)removeAtIndices registry:(RCTSparseArray *)registry; -- (void)modifyManageChildren:(NSNumber *)containerReactTag - addChildReactTags:(NSMutableArray *)mutableAddChildReactTags - addAtIndices:(NSMutableArray *)mutableAddAtIndices - removeAtIndices:(NSMutableArray *)mutableRemoveAtIndices; - -- (void)createView:(NSNumber *)reactTag - viewName:(NSString *)viewName - rootTag:(NSNumber *)rootTag - props:(NSDictionary *)props; - -- (void)updateView:(NSNumber *)reactTag - viewName:(NSString *)viewName - props:(NSDictionary *)props; - -- (void)manageChildren:(NSNumber *)containerReactTag - moveFromIndices:(NSArray *)moveFromIndices - moveToIndices:(NSArray *)moveToIndices - addChildReactTags:(NSArray *)addChildReactTags - addAtIndices:(NSArray *)addAtIndices - removeAtIndices:(NSArray *)removeAtIndices; - -- (void)flushUIBlocks; - @property (nonatomic, readonly) RCTSparseArray *viewRegistry; @property (nonatomic, readonly) RCTSparseArray *shadowViewRegistry; // RCT thread only @@ -197,329 +174,4 @@ } } -/* +-----------------------------------------------------------+ +----------------------+ - * | Shadow Hierarchy | | Legend | - * +-----------------------------------------------------------+ +----------------------+ - * | | | | - * | +---+ ****** | | ******************** | - * | | 1 | * 11 * | | * Layout-only View * | - * | +---+ ****** | | ******************** | - * | | | | | | - * | +-------+---+---+----------+ +---+---+ | | +----+ | - * | | | | | | | | | |View| Subview | - * | v v v v v v | | +----+ -----------> | - * | ***** +---+ ***** +---+ +----+ +----+ | | | - * | * 2 * | 3 | * 4 * | 5 | | 12 | | 13 | | +----------------------+ - * | ***** +---+ ***** +---+ +----+ +----+ | - * | | | | | - * | +---+--+ | +---+---+ | - * | | | | | | | - * | v v v v v | - * | +---+ +---+ +---+ +---+ ****** | - * | | 6 | | 7 | | 8 | | 9 | * 10 * | - * | +---+ +---+ +---+ +---+ ****** | - * | | - * +-----------------------------------------------------------+ - * - * +-----------------------------------------------------------+ - * | View Hierarchy | - * +-----------------------------------------------------------+ - * | | - * | +---+ ****** | - * | | 1 | * 11 * | - * | +---+ ****** | - * | | | | - * | +------+------+------+------+ +---+---+ | - * | | | | | | | | | - * | v v v v v v v | - * | +---+ +---+ +---+ +---+ +---+ +----+ +----+ | - * | | 6 | | 7 | | 3 | | 8 | | 5 | | 12 | | 13 | | - * | +---+ +---+ +---+ +---+ +---+ +----+ +----+ | - * | | | - * | v | - * | +---+ | - * | | 9 | | - * | +---+ | - * | | - * +-----------------------------------------------------------+ - */ - -- (void)updateShadowViewWithReactTag:(NSNumber *)reactTag layoutOnly:(BOOL)isLayoutOnly childTags:(NSArray *)childTags -{ - RCTShadowView *shadowView = _uiManager.shadowViewRegistry[reactTag]; - shadowView.allProps = isLayoutOnly ? @{} : @{@"collapsible": @NO}; - [childTags enumerateObjectsUsingBlock:^(NSNumber *childTag, NSUInteger idx, __unused BOOL *stop) { - [shadowView insertReactSubview:_uiManager.shadowViewRegistry[childTag] atIndex:idx]; - }]; -} - -- (void)setUpShadowViewHierarchy -{ - [self updateShadowViewWithReactTag:@1 layoutOnly:NO childTags:@[@2, @3, @4, @5]]; - [self updateShadowViewWithReactTag:@2 layoutOnly:YES childTags:@[@6, @7]]; - [self updateShadowViewWithReactTag:@3 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@4 layoutOnly:YES childTags:@[@8]]; - [self updateShadowViewWithReactTag:@5 layoutOnly:NO childTags:@[@9, @10]]; - [self updateShadowViewWithReactTag:@6 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@7 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@8 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@9 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@10 layoutOnly:YES childTags:nil]; - [self updateShadowViewWithReactTag:@11 layoutOnly:YES childTags:@[@12, @13]]; - [self updateShadowViewWithReactTag:@12 layoutOnly:NO childTags:nil]; - [self updateShadowViewWithReactTag:@13 layoutOnly:NO childTags:nil]; -} - -- (void)testModifyIndices1 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[@2] mutableCopy]; - NSMutableArray *addIndices = [@[@3] mutableCopy]; - NSMutableArray *removeIndices = [@[@0] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[@6, @7])); - XCTAssertEqualObjects(addIndices, (@[@3, @4])); - XCTAssertEqualObjects(removeIndices, (@[@0, @1])); -} - -- (void)testModifyIndices2 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[@11] mutableCopy]; - NSMutableArray *addIndices = [@[@4] mutableCopy]; - NSMutableArray *removeIndices = [@[] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[@12, @13])); - XCTAssertEqualObjects(addIndices, (@[@5, @6])); - XCTAssertEqualObjects(removeIndices, (@[])); -} - -- (void)testModifyIndices3 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[] mutableCopy]; - NSMutableArray *addIndices = [@[] mutableCopy]; - NSMutableArray *removeIndices = [@[@2] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[])); - XCTAssertEqualObjects(addIndices, (@[])); - XCTAssertEqualObjects(removeIndices, (@[@3])); -} - -- (void)testModifyIndices4 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[@11] mutableCopy]; - NSMutableArray *addIndices = [@[@3] mutableCopy]; - NSMutableArray *removeIndices = [@[@2] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[@12, @13])); - XCTAssertEqualObjects(addIndices, (@[@4, @5])); - XCTAssertEqualObjects(removeIndices, (@[@3])); -} - -- (void)testModifyIndices5 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[] mutableCopy]; - NSMutableArray *addIndices = [@[] mutableCopy]; - NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[])); - XCTAssertEqualObjects(addIndices, (@[])); - XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4])); -} - -- (void)testModifyIndices6 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[@11] mutableCopy]; - NSMutableArray *addIndices = [@[@0] mutableCopy]; - NSMutableArray *removeIndices = [@[@0, @1, @2, @3] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[@12, @13])); - XCTAssertEqualObjects(addIndices, (@[@0, @1])); - XCTAssertEqualObjects(removeIndices, (@[@0, @1, @2, @3, @4])); -} - -- (void)testModifyIndices7 -{ - [self setUpShadowViewHierarchy]; - - NSMutableArray *addTags = [@[@11] mutableCopy]; - NSMutableArray *addIndices = [@[@1] mutableCopy]; - NSMutableArray *removeIndices = [@[@0, @2, @3] mutableCopy]; - [self.uiManager modifyManageChildren:@1 - addChildReactTags:addTags - addAtIndices:addIndices - removeAtIndices:removeIndices]; - XCTAssertEqualObjects(addTags, (@[@12, @13])); - XCTAssertEqualObjects(addIndices, (@[@1, @2])); - XCTAssertEqualObjects(removeIndices, (@[@0, @1, @3, @4])); -} - -- (void)DISABLED_testScenario1 // t7660646 -{ - RCTUIManager *uiManager = [[RCTUIManager alloc] init]; - RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil]; - NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"]; - - XCTestExpectation *expectation = [self expectationWithDescription:@""]; - - dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"]; - dispatch_async(shadowQueue, ^{ - // Make sure root view finishes loading. - dispatch_sync(dispatch_get_main_queue(), ^{}); - - /* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; - /* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; - /* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}]; - /* V */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"blue",@"height":@50,@"width":@50}]; - /* */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}]; - /* V */[uiManager createView:@7 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@10,@"margin":@50}]; - /* V */[uiManager createView:@8 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"yellow",@"height":@50}]; - /* V */[uiManager createView:@9 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}]; - /* */[uiManager createView:@10 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}]; - /* */[uiManager manageChildren:@9 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@10] addAtIndices:@[@0] removeAtIndices:nil]; - /* V */[uiManager createView:@12 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"green",@"height":@50}]; - /* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8,@9,@12] addAtIndices:@[@0,@1,@2] removeAtIndices:nil]; - /* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil]; - /* V */[uiManager createView:@13 viewName:@"RCTView" rootTag:@1 props:@{@"backgroundColor":@"red",@"height":@50,@"width":@50}]; - /* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5,@6,@13] addAtIndices:@[@0,@1,@2] removeAtIndices:nil]; - /* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil]; - - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; - - expectation = [self expectationWithDescription:@""]; - dispatch_async(shadowQueue, ^{ - [uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}]; - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)7); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; - - expectation = [self expectationWithDescription:@""]; - dispatch_async(shadowQueue, ^{ - [uiManager updateView:@7 viewName:@"RCTView" props:@{@"borderWidth":@10}]; - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)12); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)8); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; -} - -- (void)DISABLED_testScenario2 // t7660646 -{ - RCTUIManager *uiManager = [[RCTUIManager alloc] init]; - RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:^{ return @[uiManager]; } launchOptions:nil]; - NS_VALID_UNTIL_END_OF_SCOPE RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Test"]; - - XCTestExpectation *expectation = [self expectationWithDescription:@""]; - - dispatch_queue_t shadowQueue = [uiManager valueForKey:@"shadowQueue"]; - dispatch_async(shadowQueue, ^{ - // Make sure root view finishes loading. - dispatch_sync(dispatch_get_main_queue(), ^{}); - - /* */[uiManager createView:@2 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; - /* */[uiManager createView:@3 viewName:@"RCTView" rootTag:@1 props:@{@"bottom":@0,@"left":@0,@"position":@"absolute",@"right":@0,@"top":@0}]; - /* V */[uiManager createView:@4 viewName:@"RCTView" rootTag:@1 props:@{@"alignItems":@"center",@"backgroundColor":@"#F5FCFF",@"flex":@1,@"justifyContent":@"center"}]; - /* */[uiManager createView:@5 viewName:@"RCTView" rootTag:@1 props:@{@"width":@250}]; - /* V */[uiManager createView:@6 viewName:@"RCTView" rootTag:@1 props:@{@"borderWidth":@1}]; - /* V */[uiManager createView:@7 viewName:@"RCTText" rootTag:@1 props:@{@"accessible":@1,@"fontSize":@20,@"isHighlighted":@0,@"margin":@10,@"textAlign":@"center"}]; - /* */[uiManager createView:@8 viewName:@"RCTRawText" rootTag:@1 props:@{@"text":@"This tests removal of layout-only views."}]; - /* */[uiManager manageChildren:@7 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@8] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@6 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@7] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@5 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@6] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@4 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@5] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@3 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@4] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@2 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@3] addAtIndices:@[@0] removeAtIndices:nil]; - /* */[uiManager manageChildren:@1 moveFromIndices:nil moveToIndices:nil addChildReactTags:@[@2] addAtIndices:@[@0] removeAtIndices:nil]; - - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; - - expectation = [self expectationWithDescription:@""]; - dispatch_async(shadowQueue, ^{ - [uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":[NSNull null]}]; - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)3); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; - - expectation = [self expectationWithDescription:@""]; - dispatch_async(shadowQueue, ^{ - [uiManager updateView:@6 viewName:@"RCTView" props:@{@"borderWidth":@1}]; - [uiManager addUIBlock:^(RCTUIManager *uiManager_, __unused RCTSparseArray *viewRegistry) { - XCTAssertEqual(uiManager_.shadowViewRegistry.count, (NSUInteger)8); - XCTAssertEqual(uiManager_.viewRegistry.count, (NSUInteger)4); - [expectation fulfill]; - }]; - - [uiManager flushUIBlocks]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; -} - @end