ComponentKitTests/StatefulViews/CKStatefulViewComponentControllerTests.mm (118 lines of code) (raw):
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#import <XCTest/XCTest.h>
#import <ComponentKitTestHelpers/CKComponentLifecycleTestHelper.h>
#import <ComponentKitTestHelpers/CKLifecycleTestComponent.h>
#import <ComponentKitTestHelpers/CKTestRunLoopRunning.h>
#import <ComponentKit/CKComponentControllerEvents.h>
#import <ComponentKit/CKComponentProvider.h>
#import <ComponentKit/CKComponentSubclass.h>
#import "CKTestStatefulViewComponent.h"
@interface CKStatefulViewComponentControllerTests : XCTestCase
@end
@implementation CKStatefulViewComponentControllerTests
static CKComponent *componentProvider(id<NSObject> model, id<NSObject>context)
{
return [CKTestStatefulViewComponent newWithColor:(UIColor *)model];
}
- (void)testMountingStatefulViewComponentCreatesStatefulView
{
CKComponentLifecycleTestHelper *componentLifecycleTestController = [[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider
sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state = [componentLifecycleTestController prepareForUpdateWithModel:[UIColor blueColor]
constrainedSize:{{100, 100}, {100, 100}}
context:nil];
[componentLifecycleTestController updateWithState:state];
UIView *view = [UIView new];
[componentLifecycleTestController attachToView:view];
auto component = (CKTestStatefulViewComponent *)state.componentLayout.component;
auto controller = (CKTestStatefulViewComponentController *)[component controller];
auto statefulView = [controller statefulView];
XCTAssertTrue([statefulView isKindOfClass:[CKTestStatefulView class]], @"Expected stateful view but couldn't find it");
XCTAssertTrue(CGRectEqualToRect([statefulView frame], CGRectMake(0, 0, 100, 100)), @"Expected view to be sized to match component");
XCTAssertEqualObjects([statefulView backgroundColor], [UIColor blueColor], @"Expected view to be configured");
}
- (void)testUnmountingStatefulViewComponentEventuallyRelinquishesStatefulView
{
CKComponentLifecycleTestHelper *componentLifecycleTestController = [[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider
sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state = [componentLifecycleTestController prepareForUpdateWithModel:nil
constrainedSize:{{100, 100}, {100, 100}}
context:nil];
[componentLifecycleTestController updateWithState:state];
UIView *view = [UIView new];
[componentLifecycleTestController attachToView:view];
auto component = (CKTestStatefulViewComponent *)state.componentLayout.component;
auto controller = (CKTestStatefulViewComponentController *)[component controller];
XCTAssertNotNil([controller statefulView], @"Expected to have a stateful view while mounted");
[componentLifecycleTestController detachFromView];
XCTAssertTrue(CKRunRunLoopUntilBlockIsTrue(^BOOL{
return [controller statefulView] == nil;
}), @"Expected view to be relinquished");
}
- (void)testMountingStatefulViewComponentOnNewRootViewMovesStatefulView
{
CKComponentLifecycleTestHelper *componentLifecycleTestController = [[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider
sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state = [componentLifecycleTestController prepareForUpdateWithModel:nil
constrainedSize:{{100, 100}, {100, 100}}
context:nil];
[componentLifecycleTestController updateWithState:state];
auto controller = (CKTestStatefulViewComponentController *)[(CKTestStatefulViewComponent *)state.componentLayout.component controller];
UIView *view1 = [UIView new];
[componentLifecycleTestController attachToView:view1];
XCTAssertTrue([[controller statefulView] isDescendantOfView:view1], @"Expected view to be in view1");
UIView *view2 = [UIView new];
[componentLifecycleTestController attachToView:view2];
XCTAssertTrue([[controller statefulView] isDescendantOfView:view2], @"Expected view to be moved to view2");
}
- (void)testUpdatingStatefulViewComponentSizeUpdatesStatefulViewSize
{
CKComponentLifecycleTestHelper *componentLifecycleTestController = [[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider
sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state = [componentLifecycleTestController prepareForUpdateWithModel:nil
constrainedSize:{{100, 100}, {100, 100}}
context:nil];
[componentLifecycleTestController updateWithState:state];
UIView *view = [UIView new];
[componentLifecycleTestController attachToView:view];
auto controller = (CKTestStatefulViewComponentController *)[(CKTestStatefulViewComponent *)state.componentLayout.component controller];
[componentLifecycleTestController updateWithState:[componentLifecycleTestController prepareForUpdateWithModel:nil
constrainedSize:{{50, 50}, {50, 50}}
context:nil]];
XCTAssertTrue(CGRectEqualToRect([[controller statefulView] frame], CGRectMake(0, 0, 50, 50)), @"Stateful view size should be updated to match new size");
}
- (void)testUpdatingStatefulViewComponentColorUpdatesStatefulViewColor
{
CKComponentLifecycleTestHelper *componentLifecycleTestController = [[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider
sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state = [componentLifecycleTestController prepareForUpdateWithModel:[UIColor whiteColor]
constrainedSize:{{0, 0}, {100, 100}}
context:nil];
[componentLifecycleTestController updateWithState:state];
UIView *view = [UIView new];
[componentLifecycleTestController attachToView:view];
auto controller = (CKTestStatefulViewComponentController *)[(CKTestStatefulViewComponent *)state.componentLayout.component controller];
[componentLifecycleTestController updateWithState:[componentLifecycleTestController prepareForUpdateWithModel:[UIColor redColor]
constrainedSize:{{100, 100}, {100, 100}}
context:nil]];
XCTAssertEqualObjects([[controller statefulView] backgroundColor], [UIColor redColor], @"Stateful view size should be updated to match new color");
}
- (void)testInvalidatingStatefulViewComponentEventuallyRelinquishesStatefulView
{
CKComponentLifecycleTestHelper *componentLifecycleTestController =
[[CKComponentLifecycleTestHelper alloc] initWithComponentProvider:componentProvider sizeRangeProvider:nil];
const CKComponentLifecycleTestHelperState state =
[componentLifecycleTestController prepareForUpdateWithModel:nil
constrainedSize:{{0,0}, {100, 100}}
context:nil];
[componentLifecycleTestController attachToView:[UIView new]];
[componentLifecycleTestController updateWithState:state];
auto component = (CKTestStatefulViewComponent *)state.componentLayout.component;
auto controller = (CKTestStatefulViewComponentController *)[component controller];
XCTAssertNotNil([controller statefulView], @"Expected to have a stateful view while mounted");
[componentLifecycleTestController detachFromView];
CKComponentScopeRootAnnounceControllerInvalidation([componentLifecycleTestController state].scopeRoot);
XCTAssertTrue(CKRunRunLoopUntilBlockIsTrue(^BOOL{
return [controller statefulView] == nil;
}), @"Expected view to be relinquished");
}
@end