blob: ee37466c8189524cd1756ab6d0338cf648b22c5f [file] [log] [blame] [edit]
// Copyright 2018-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <XCTest/XCTest.h>
#import "../../src/private/MDCBottomDrawerContainerViewController.h"
#import "../../src/private/MDCBottomDrawerHeaderMask.h"
#import "../../src/private/MDCBottomDrawerShadowedView.h"
#import "MDCBottomDrawerState.h"
#import "MaterialNavigationDrawer.h"
#import "MDCBottomDrawerContainerViewControllerDelegate.h"
#import "MDCNavigationDrawerFakes.h"
#import "MaterialShadowLayer.h"
@interface MDCBottomDrawerDelegateTest
: UIViewController <MDCBottomDrawerPresentationControllerDelegate,
MDCBottomDrawerViewControllerDelegate>
@property(nonatomic, strong) NSMutableArray *commands;
@end
@implementation MDCBottomDrawerDelegateTest
- (instancetype)init {
self = [super init];
if (self) {
_commands = [NSMutableArray array];
}
return self;
}
- (void)bottomDrawerWillChangeState:(MDCBottomDrawerPresentationController *)presentationController
drawerState:(MDCBottomDrawerState)drawerState {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerTopTransitionRatio:
(nonnull MDCBottomDrawerPresentationController *)presentationController
transitionRatio:(CGFloat)transitionRatio {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerDismissTransitionDidEnd:
(MDCBottomDrawerPresentationController *)presentationController {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerPresentTransitionDidEnd:
(MDCBottomDrawerPresentationController *)presentationController {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerTopDidChangeYOffset:
(MDCBottomDrawerPresentationController *)presentationController
yOffset:(CGFloat)yOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerDismissTransitionWillBegin:
(MDCBottomDrawerPresentationController *)presentationController
withCoordinator:
(id<UIViewControllerTransitionCoordinator>)transitionCoordinator
targetYOffset:(CGFloat)targetYOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerPresentTransitionWillBegin:
(MDCBottomDrawerPresentationController *)presentationController
withCoordinator:
(id<UIViewControllerTransitionCoordinator>)transitionCoordinator
targetYOffset:(CGFloat)targetYOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerDidTapScrim:(MDCBottomDrawerPresentationController *)presentationController {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerDidEndOpenTransition:(MDCBottomDrawerViewController *)controller {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerDidEndCloseTransition:(MDCBottomDrawerViewController *)controller {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerDidChangeTopInset:(nonnull MDCBottomDrawerViewController *)controller
topInset:(CGFloat)topInset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerDidChangeTopYOffset:
(nonnull MDCBottomDrawerViewController *)controller
yOffset:(CGFloat)yOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerWillTransitionOpen:(nonnull MDCBottomDrawerViewController *)controller
withCoordinator:
(nullable id<UIViewControllerTransitionCoordinator>)
transitionCoordinator
targetYOffset:(CGFloat)targetYOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)
bottomDrawerControllerWillTransitionClosed:(nonnull MDCBottomDrawerViewController *)controller
withCoordinator:(nullable id<UIViewControllerTransitionCoordinator>)
transitionCoordinator
targetYOffset:(CGFloat)targetYOffset {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)bottomDrawerControllerDidTapScrim:(nonnull MDCBottomDrawerViewController *)controller {
[_commands addObject:NSStringFromSelector(_cmd)];
}
- (void)clear {
_commands = [NSMutableArray array];
}
- (BOOL)verifyCallback:(SEL)cmd {
return [_commands containsObject:NSStringFromSelector(cmd)];
}
@end
@interface MDCBottomDrawerViewController (ScrollViewTests)
@property(nullable, nonatomic, readonly) MDCBottomDrawerHeaderMask *maskLayer;
@end
@interface MDCBottomDrawerContainerViewController (ScrollViewTests)
@property(nonatomic) BOOL scrollViewObserved;
@property(nonatomic, readonly) UIScrollView *scrollView;
@property(nonatomic, readonly) CGFloat topHeaderHeight;
@property(nonatomic, readonly) CGFloat contentHeaderHeight;
@property(nonatomic, readonly) CGFloat contentHeaderTopInset;
@property(nonatomic, readonly) CGRect presentingViewBounds;
@property(nonatomic, readonly) CGFloat contentHeightSurplus;
@property(nonatomic, readonly) BOOL contentScrollsToReveal;
@property(nonatomic) MDCBottomDrawerState drawerState;
@property(nullable, nonatomic, readonly) UIPresentationController *presentationController;
@property(nonatomic) MDCShadowLayer *headerShadowLayer;
@property(nonatomic) MDCBottomDrawerShadowedView *shadowedView;
- (void)cacheLayoutCalculations;
- (void)updateViewWithContentOffset:(CGPoint)contentOffset;
- (void)updateDrawerState:(CGFloat)transitionPercentage;
- (CGFloat)calculateMaximumInitialDrawerHeight;
@end
@interface MDCBottomDrawerPresentationController (ScrollViewTests) <
MDCBottomDrawerContainerViewControllerDelegate>
@property(nonatomic) MDCBottomDrawerContainerViewController *bottomDrawerContainerViewController;
@property(nonatomic, weak, nullable) id<MDCBottomDrawerPresentationControllerDelegate> delegate;
@property(nonatomic, strong, nullable) UIView *topHandle;
- (void)scrimTapped;
@end
@interface MDCNavigationDrawerScrollViewTests : XCTestCase
@property(nonatomic, strong, nullable) UIScrollView *fakeScrollView;
@property(nonatomic, strong, nullable) MDCBottomDrawerContainerViewController *fakeBottomDrawer;
@property(nonatomic, strong, nullable) MDCBottomDrawerViewController *drawerViewController;
@property(nonatomic, strong, nullable)
MDCBottomDrawerPresentationController *presentationController;
@property(nonatomic, strong, nullable) MDCBottomDrawerDelegateTest *delegateTest;
@end
@implementation MDCNavigationDrawerScrollViewTests
- (void)setUp {
[super setUp];
UIViewController *fakeViewController = [[UIViewController alloc] init];
fakeViewController.view.frame = CGRectMake(0, 0, 200, 500);
_fakeScrollView = [[UIScrollView alloc] init];
_fakeBottomDrawer = [[MDCBottomDrawerContainerViewController alloc]
initWithOriginalPresentingViewController:fakeViewController
trackingScrollView:_fakeScrollView];
_drawerViewController = [[MDCBottomDrawerViewController alloc] init];
_drawerViewController.contentViewController = fakeViewController;
_presentationController = [[MDCBottomDrawerPresentationController alloc]
initWithPresentedViewController:_drawerViewController
presentingViewController:nil];
_delegateTest = [[MDCBottomDrawerDelegateTest alloc] init];
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
presentationController.bottomDrawerContainerViewController = self.fakeBottomDrawer;
self.fakeBottomDrawer.contentViewController = self.drawerViewController.contentViewController;
}
- (void)tearDown {
self.fakeScrollView = nil;
self.fakeBottomDrawer = nil;
[super tearDown];
}
- (void)setupHeaderWithPreferredContentSize:(CGSize)preferredContentSize {
MDCNavigationDrawerFakeHeaderViewController *fakeHeader =
[[MDCNavigationDrawerFakeHeaderViewController alloc] init];
self.fakeBottomDrawer.headerViewController = fakeHeader;
self.fakeBottomDrawer.headerViewController.preferredContentSize = preferredContentSize;
}
- (void)testScrollViewNotNil {
// Then
XCTAssertNotNil(self.fakeBottomDrawer.scrollView);
}
- (void)testScrollViewBeingObserved {
// When
[self.fakeBottomDrawer viewWillAppear:YES];
// Then
XCTAssertTrue(self.fakeBottomDrawer.scrollViewObserved);
}
- (void)testScrollViewNotBeingObserved {
// When
[self.fakeBottomDrawer viewWillAppear:YES];
[self.fakeBottomDrawer viewDidDisappear:YES];
// Then
XCTAssertFalse(self.fakeBottomDrawer.scrollViewObserved);
}
- (void)testPresentingViewBounds {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 375);
// When
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
// Then
CGRect standardizePresentingViewBounds =
CGRectStandardize(self.fakeBottomDrawer.presentingViewBounds);
XCTAssertEqualWithAccuracy(standardizePresentingViewBounds.origin.x, fakeRect.origin.x, 0.001);
XCTAssertEqualWithAccuracy(standardizePresentingViewBounds.origin.y, fakeRect.origin.y, 0.001);
XCTAssertEqualWithAccuracy(standardizePresentingViewBounds.size.width, fakeRect.size.width,
0.001);
XCTAssertEqualWithAccuracy(standardizePresentingViewBounds.size.height, fakeRect.size.height,
0.001);
}
- (void)testContentHeaderHeightWithNoHeader {
// When
self.fakeBottomDrawer.headerViewController = nil;
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderHeight, 0, 0.001);
}
- (void)testContentHeaderHeightWithHeader {
// Given
CGSize fakePreferredContentSize = CGSizeMake(200, 300);
// When
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderHeight,
fakePreferredContentSize.height, 0.001);
}
- (void)testTopHeaderHeightWithNoHeader {
// Given
CGFloat topSafeArea;
if (@available(iOS 11.0, *)) {
topSafeArea = self.fakeBottomDrawer.view.safeAreaInsets.top;
} else {
// A safe area of 20 is used prior to iOS 11.0 to reflect the status bar height.
topSafeArea = 20;
}
// When
self.fakeBottomDrawer.headerViewController = nil;
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.topHeaderHeight, topSafeArea, 0.001);
}
- (void)testTopHeaderHeightWithHeader {
// Given
CGFloat topSafeArea;
if (@available(iOS 11.0, *)) {
topSafeArea = self.fakeBottomDrawer.view.safeAreaInsets.top;
} else {
// A safe area of 20 is used prior to iOS 11.0 to reflect the status bar height.
topSafeArea = 20;
}
CGSize fakePreferredContentSize = CGSizeMake(200, 300);
// When
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.topHeaderHeight,
topSafeArea + fakePreferredContentSize.height, 0.001);
}
- (void)testContentHeaderTopInsetWithHeaderAndContentViewController {
// Given
// Setup gives us presentingViewBounds of (0, 0, 200, 500)
CGSize fakePreferredContentSize = CGSizeMake(200, 300);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 100);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// presentingViewBounds.size.height = 500 / 2 = 250
// The drawer should initially open to half the presentingViewBounds if there is more than
// half of the view's height worth of content
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 250, 0.001);
}
- (void)testContentHeaderTopInsetWithNoHeaderOrContentViewController {
// Given
// Setup gives us presentingViewbounds of (0, 0, 200, 500)
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// presentingViewBounds.size.height = 500, contentHeaderHeight = 0
// contentViewController.preferredContentSize.height = 0
// 500 - 0 - 0 = 500
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 500, 0.001);
}
- (void)testContentHeaderTopInsetWithHeaderAndNoContentViewController {
// Given
// Setup gives us presentingViewBounds of (0, 0, 200, 500)
CGSize fakePreferredContentSize = CGSizeMake(200, 300);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// presentingViewBounds.size.height = 500 / 2 = 250
// The drawer should initially open to half the presentingViewBounds if there is more than
// half of the view's height worth of content
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 250, 0.001);
}
- (void)testContentHeaderTopInsetWithOnlyContentViewController {
// Given
// Setup gives us presentingViewBounds of (0, 0, 200, 500)
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 100);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// presentingViewBounds.size.height = 500, contentHeaderHeight = 0
// contentViewController.preferredContentSize.height = 100
// 500 - 0 - 100 = 400
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 400, 0.001);
}
- (void)testContentHeaderTopInsetForScrollableContentForLargeHeader {
// Given
// Setup gives us presentingViewBoudns of (0, 0, 200, 500)
CGSize fakePreferredContentSize = CGSizeMake(200, 700);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// In cacheLayoutCalculation we test if contentScrollsToReveal is true then contentHeaderTopInset
// should be initialDrawerFactor * presentingViewBounds = 500 * 0.5
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 250, 0.001);
}
- (void)testContentHeaderTopInsetForScrollableContentForLargeContent {
// Given
// Setup gives us presentingViewBounds of (0, 0, 200, 500)
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1000);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// In cacheLayoutCalculation we test if contentScrollsToReveal is true then contentHeaderTopInset
// should be initialDrawerFactor * presentingViewBounds = 500 * 0.5
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 250, 0.001);
}
- (void)testContentHeaderTopInsetForScrollableContent {
// Given
// Setup gives us presentingViewBounds of (0, 0, 200, 500)
CGSize fakePreferredContentSize = CGSizeMake(200, 700);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1000);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// In cacheLayoutCalculation we test if contentScrollsToReveal is true then contentHeaderTopInset
// should be initialDrawerFactor * presentingViewBounds = 500 * 0.5
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 250, 0.001);
}
- (void)testContentHeightSurplus {
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeightSurplus, 0, 0.001);
}
- (void)testContentHeightSurplusWithScrollableContent {
// Given
CGSize fakePreferredContentSize = CGSizeMake(200, 1000);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1500);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeightSurplus, 2250, 0.001);
}
- (void)testContentScrollsToRevealFalse {
// Then
XCTAssertFalse(self.fakeBottomDrawer.contentScrollsToReveal);
}
- (void)testContentScrollsToRevealTrue {
CGSize fakePreferredContentSize = CGSizeMake(200, 1000);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1500);
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
XCTAssertTrue(self.fakeBottomDrawer.contentScrollsToReveal);
}
- (void)testBottomDrawerStateCollapsed {
CGSize fakePreferredContentSize = CGSizeMake(200, 1000);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1500);
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
XCTAssertEqual(self.fakeBottomDrawer.drawerState, MDCBottomDrawerStateCollapsed);
}
- (void)testBottomDrawerStateExpanded {
CGSize fakePreferredContentSize = CGSizeMake(200, 100);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 100);
[self.fakeBottomDrawer cacheLayoutCalculations];
// Then
// The drawer needs less than half the presentingViewBounds.height to be in an expanded state
// Unless if a user scrolls passed `initialDrawerFactor`.
XCTAssertEqual(self.fakeBottomDrawer.drawerState, MDCBottomDrawerStateExpanded);
}
- (void)testBottomDrawerStateFullScreen {
CGSize fakePreferredContentSize = CGSizeMake(200, 2000);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
// When
[self.fakeBottomDrawer cacheLayoutCalculations];
[self.fakeBottomDrawer updateDrawerState:1];
// Then
XCTAssertEqual(self.fakeBottomDrawer.drawerState, MDCBottomDrawerStateFullScreen);
}
- (void)testBottomDrawerStateCallback {
CGSize fakePreferredContentSize = CGSizeMake(200, 1000);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 1500);
[self.fakeBottomDrawer cacheLayoutCalculations];
self.presentationController.delegate = self.delegateTest;
self.presentationController.bottomDrawerContainerViewController = self.fakeBottomDrawer;
self.fakeBottomDrawer.delegate = self.presentationController;
self.fakeBottomDrawer.drawerState = MDCBottomDrawerStateExpanded;
// Then
XCTAssertTrue([self.delegateTest verifyCallback:@selector(bottomDrawerWillChangeState:
drawerState:)]);
}
- (void)testBottomDrawerControllerWillOpenCallback {
self.drawerViewController.delegate = self.delegateTest;
self.presentationController.delegate = self.drawerViewController;
[self.presentationController presentationTransitionWillBegin];
XCTAssertTrue([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerWillTransitionOpen:
withCoordinator:targetYOffset:)]);
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
}
- (void)testBottomDrawerControllerDidOpenCallback {
self.drawerViewController.delegate = self.delegateTest;
self.presentationController.delegate = self.drawerViewController;
[self.presentationController presentationTransitionDidEnd:YES];
XCTAssertTrue(
[self.delegateTest verifyCallback:@selector(bottomDrawerControllerDidEndOpenTransition:)]);
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
}
- (void)testBottomDrawerControllerWillCloseCallback {
self.drawerViewController.delegate = self.delegateTest;
self.presentationController.delegate = self.drawerViewController;
[self.presentationController dismissalTransitionWillBegin];
XCTAssertTrue([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerWillTransitionClosed:
withCoordinator:targetYOffset:)]);
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
}
- (void)testBottomDrawerControllerDidCloseCallback {
self.drawerViewController.delegate = self.delegateTest;
self.presentationController.delegate = self.drawerViewController;
[self.presentationController dismissalTransitionDidEnd:YES];
XCTAssertTrue(
[self.delegateTest verifyCallback:@selector(bottomDrawerControllerDidEndCloseTransition:)]);
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
}
- (void)testBottomDrawerControllerToYOffsetChangesCallback {
self.fakeBottomDrawer.delegate = self.presentationController;
self.drawerViewController.delegate = self.delegateTest;
self.presentationController.delegate = self.drawerViewController;
CGSize fakePreferredContentSize = CGSizeMake(200, 100);
[self setupHeaderWithPreferredContentSize:fakePreferredContentSize];
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
// fake out a layout pass...
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 100);
self.fakeBottomDrawer.contentViewController.view.frame = CGRectMake(0, 500, 200, 100);
// fake presenting the drawer
[self.presentationController presentationTransitionWillBegin];
[self.presentationController presentationTransitionDidEnd:YES];
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
// fake a content inset change -- aka a user scrolled
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, 100)];
XCTAssertTrue([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
// clear recorded cmds
[self.delegateTest clear];
// fake close the drawer
[self.presentationController dismissalTransitionWillBegin];
[self.presentationController dismissalTransitionDidEnd:YES];
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
// fake a content inset change -- aka a reset
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, 50)];
XCTAssertFalse([self.delegateTest
verifyCallback:@selector(bottomDrawerControllerDidChangeTopYOffset:yOffset:)]);
}
- (void)testBottomDrawerControllerDidTapScrimCallback {
// Given
self.presentationController.delegate = self.delegateTest;
self.presentationController.bottomDrawerContainerViewController = self.fakeBottomDrawer;
// When
[self.presentationController scrimTapped];
// Then
XCTAssertTrue([self.delegateTest verifyCallback:@selector(bottomDrawerDidTapScrim:)]);
}
- (void)testBottomDrawerCornersAPICollapsed {
// When
[self.drawerViewController setTopCornersRadius:10 forDrawerState:MDCBottomDrawerStateCollapsed];
// Then
XCTAssertEqual(self.drawerViewController.maskLayer.maximumCornerRadius, 10);
}
- (void)testBottomDrawerCornersAPIExpanded {
// When
self.drawerViewController.contentViewController.preferredContentSize = CGSizeMake(100, 100);
[self.fakeBottomDrawer cacheLayoutCalculations];
[self.drawerViewController setTopCornersRadius:5 forDrawerState:MDCBottomDrawerStateExpanded];
// Then
XCTAssertEqual(self.drawerViewController.maskLayer.minimumCornerRadius, 5);
}
- (void)testBottomDrawerCornersAPIFullScreen {
// When
self.drawerViewController.contentViewController.preferredContentSize = CGSizeMake(100, 5000);
[self.fakeBottomDrawer cacheLayoutCalculations];
[self.drawerViewController setTopCornersRadius:3 forDrawerState:MDCBottomDrawerStateFullScreen];
// Then
XCTAssertEqual(self.drawerViewController.maskLayer.minimumCornerRadius, 3);
}
- (void)testBottomDrawerDynamicSizing {
// Given
self.fakeBottomDrawer.contentViewController =
[[MDCNavigationDrawerFakeTableViewController alloc] init];
[self.fakeBottomDrawer viewDidLoad];
[self.fakeBottomDrawer cacheLayoutCalculations];
CGFloat previousContentHeaderTopInset = self.fakeBottomDrawer.contentHeaderTopInset;
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(200, 200);
// Then
XCTAssertLessThan(self.fakeBottomDrawer.contentHeaderTopInset, previousContentHeaderTopInset);
}
- (void)testBottomDrawerHandle {
// When
[self.presentationController presentationTransitionWillBegin];
// Then
XCTAssertNotNil(self.presentationController.topHandle);
XCTAssertEqualWithAccuracy(CGRectGetWidth(self.presentationController.topHandle.frame),
(CGFloat)24.0, (CGFloat)0.001);
XCTAssertEqualWithAccuracy(CGRectGetHeight(self.presentationController.topHandle.frame),
(CGFloat)2.0, (CGFloat)0.001);
XCTAssertEqualWithAccuracy(self.presentationController.topHandle.layer.cornerRadius, (CGFloat)1.0,
(CGFloat)0.001);
XCTAssertEqual(self.presentationController.topHandle.hidden, YES);
}
- (void)testBottomDrawerHandleHidden {
// When
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
presentationController.topHandle = [[UIView alloc] init];
presentationController.topHandle.hidden = YES;
self.drawerViewController.topHandleHidden = NO;
// Then
XCTAssertEqual(presentationController.topHandle.hidden, NO);
}
- (void)testBottomDrawerHandleColor {
// When
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
presentationController.topHandle = [[UIView alloc] init];
presentationController.topHandle.backgroundColor = UIColor.blueColor;
self.drawerViewController.topHandleColor = UIColor.redColor;
// Then
XCTAssertEqualObjects(presentationController.topHandle.backgroundColor, UIColor.redColor);
}
- (void)testBottomDrawerScrollingEnabled {
// When
self.drawerViewController.trackingScrollView = self.fakeScrollView;
// Then
XCTAssertEqual(self.fakeScrollView.scrollEnabled, NO);
}
- (void)testSetTrackingScrollViewAfterSetScrimColor {
// Given
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
// When
// Setting the scrim color before setting the tracking scroll view in some cases used to
// not set the trackingScrollView on bottomDrawerContainerViewController.
self.drawerViewController.scrimColor = UIColor.blueColor;
self.drawerViewController.trackingScrollView = self.fakeScrollView;
// Then
XCTAssertNotNil(
drawerPresentationController.bottomDrawerContainerViewController.trackingScrollView);
}
- (void)testSetShouldAutoDismissOnTapCorrectly {
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
self.drawerViewController.dismissOnBackgroundTap = YES;
XCTAssertTrue(drawerPresentationController.dismissOnBackgroundTap);
}
- (void)testSetAdjustLayoutForIPadSlideOverCorrectly {
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
self.drawerViewController.adjustLayoutForIPadSlideOver = YES;
XCTAssertTrue(drawerPresentationController.adjustLayoutForIPadSlideOver);
}
- (void)testSetShouldForwardTouchEventsCorrectly {
XCTAssertNil(self.drawerViewController.nextResponder);
self.drawerViewController.shouldForwardBackgroundTouchEvents = YES;
XCTAssertFalse(self.drawerViewController.dismissOnBackgroundTap);
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertTrue(drawerPresentationController.shouldForwardBackgroundTouchEvents);
XCTAssertEqualObjects(self.drawerViewController.delegate,
self.drawerViewController.nextResponder);
}
- (void)testSetShouldDisplayMobileLandscapeFullscreenCorrectly {
self.drawerViewController.shouldDisplayMobileLandscapeFullscreen = NO;
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertFalse(self.drawerViewController.shouldDisplayMobileLandscapeFullscreen);
XCTAssertFalse(drawerPresentationController.shouldDisplayMobileLandscapeFullscreen);
}
- (void)testGestureRecognizersSetCorrectly {
self.drawerViewController.shouldForwardBackgroundTouchEvents = YES;
MDCBottomDrawerPresentationController *drawerPresentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertTrue(drawerPresentationController.containerView.gestureRecognizers.count == 0);
}
- (void)testBottomDrawerTopInset {
// Given
MDCNavigationDrawerFakeHeaderViewController *fakeHeader =
[[MDCNavigationDrawerFakeHeaderViewController alloc] init];
self.fakeBottomDrawer.headerViewController = fakeHeader;
self.drawerViewController.delegate = fakeHeader;
self.fakeBottomDrawer.delegate = self.presentationController;
[self.presentationController presentationTransitionWillBegin];
// When
[self.fakeBottomDrawer viewWillAppear:YES];
[self.fakeBottomDrawer cacheLayoutCalculations];
[self.fakeBottomDrawer.scrollView setContentOffset:CGPointMake(0, 1000)];
// Then
XCTAssertEqualWithAccuracy(fakeHeader.topInset, (CGFloat)7.0, (CGFloat)0.001);
}
- (void)testContentReachesFullscreenPresentationControllerValue {
// When
[self.presentationController presentationTransitionWillBegin];
[self.presentationController.bottomDrawerContainerViewController cacheLayoutCalculations];
// Then
XCTAssertEqual(
self.presentationController.bottomDrawerContainerViewController.contentReachesFullscreen,
self.presentationController.contentReachesFullscreen);
}
- (void)testContentOffsetY {
// When
[self.drawerViewController setContentOffsetY:0 animated:YES];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.scrollView.contentOffset.y, 500, (CGFloat)0.001);
}
- (void)testAddedHeight {
// Given
CGFloat contentViewControllerHeight =
CGRectStandardize(self.fakeBottomDrawer.contentViewController.view.frame).size.height;
CGFloat fakeHeight = 100;
self.fakeBottomDrawer.trackingScrollView = nil;
// When
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, fakeHeight)];
// Then
CGFloat newContentViewControllerHeight =
CGRectGetHeight(self.fakeBottomDrawer.contentViewController.view.frame);
CGFloat expectedHeight = contentViewControllerHeight + fakeHeight;
XCTAssertEqualWithAccuracy(newContentViewControllerHeight, expectedHeight, 0.001);
}
- (void)testAddedHeightWithMultipleScrolls {
// Given
CGFloat contentViewControllerHeight =
CGRectStandardize(self.fakeBottomDrawer.contentViewController.view.frame).size.height;
CGFloat fakeFirstHeight = 80;
CGFloat fakeSecondHeight = 100;
self.fakeBottomDrawer.trackingScrollView = nil;
// When
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, fakeFirstHeight)];
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, fakeSecondHeight)];
// Then
CGFloat newContentViewControllerHeight =
CGRectGetHeight(self.fakeBottomDrawer.contentViewController.view.frame);
CGFloat expectedHeight = contentViewControllerHeight + fakeSecondHeight;
XCTAssertEqualWithAccuracy(newContentViewControllerHeight, expectedHeight, 0.001);
}
- (void)testAddedHeightWithTrackingScrollView {
// Given
CGFloat contentViewControllerHeight =
CGRectStandardize(self.fakeBottomDrawer.contentViewController.view.frame).size.height;
CGFloat fakeHeight = 100;
self.fakeBottomDrawer.trackingScrollView = self.fakeScrollView;
// When
[self.fakeBottomDrawer updateViewWithContentOffset:CGPointMake(0, fakeHeight)];
// Then
CGFloat newContentViewControllerHeight =
CGRectGetHeight(self.fakeBottomDrawer.contentViewController.view.frame);
XCTAssertEqualWithAccuracy(newContentViewControllerHeight, contentViewControllerHeight, 0.001);
}
- (void)testCalculateInitialDrawerHeightWithSmallHeight {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 100);
// When
CGFloat drawerHeight = [self.fakeBottomDrawer calculateMaximumInitialDrawerHeight];
// Then
XCTAssertEqualWithAccuracy(drawerHeight, 100, 0.001);
}
- (void)testCalculateInitialDrawerHeightWithLargeHeight {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 1000);
// When
CGFloat drawerHeight = [self.fakeBottomDrawer calculateMaximumInitialDrawerHeight];
// Then
XCTAssertEqualWithAccuracy(drawerHeight, 250, 0.001);
}
- (void)testSettingMaximumInitialDrawerHeight {
// Given
self.drawerViewController.maximumInitialDrawerHeight = 500;
// Then
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertEqualWithAccuracy(presentationController.maximumInitialDrawerHeight, 500, 0.001);
}
- (void)testInitialDrawerHeight {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.maximumInitialDrawerHeight = 320;
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 1000);
// When
CGFloat drawerHeight = [self.fakeBottomDrawer calculateMaximumInitialDrawerHeight];
// Then
XCTAssertEqualWithAccuracy(drawerHeight, 320, 0.001);
}
- (void)testInitialDrawerHeightWithMaximalHeightBiggerThanPreferredContentSize {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.maximumInitialDrawerHeight = 1000;
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 320);
// When
CGFloat drawerHeight = [self.fakeBottomDrawer calculateMaximumInitialDrawerHeight];
// Then
XCTAssertEqualWithAccuracy(drawerHeight, 320, 0.001);
}
- (void)testDrawerHeightReasonableRounding {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.maximumInitialDrawerHeight = (CGFloat)412.3;
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 1000);
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 88, 0.001);
}
- (void)testExpandToFullScreen {
// Given
CGFloat topSafeArea;
if (@available(iOS 11.0, *)) {
topSafeArea = self.fakeBottomDrawer.view.safeAreaInsets.top;
} else {
// A safe area of 20 is used prior to iOS 11.0 to reflect the status bar height.
topSafeArea = 20;
}
MDCNavigationDrawerFakeHeaderViewController *fakeHeader =
[[MDCNavigationDrawerFakeHeaderViewController alloc] init];
self.fakeBottomDrawer.headerViewController = fakeHeader;
XCTestExpectation *expectation = [self expectationWithDescription:@"expand complete"];
// When
[self.drawerViewController expandToFullscreenWithDuration:(CGFloat)0.2
completion:^(BOOL completed) {
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:1 handler:nil];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.trackingScrollView.frame.origin.y, 0, 0.001);
CGFloat expectedHeight = self.fakeBottomDrawer.presentingViewBounds.size.height -
fakeHeader.preferredContentSize.height;
XCTAssertEqualWithAccuracy(
CGRectGetHeight(self.fakeBottomDrawer.contentViewController.view.frame), expectedHeight,
0.001);
XCTAssertEqualWithAccuracy(CGRectGetMinY(self.fakeBottomDrawer.scrollView.frame), 0, 0.001);
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, topSafeArea, 0.01);
}
- (void)testNavigationDrawerCorrectShadowValue {
// When
[self.fakeBottomDrawer viewWillLayoutSubviews];
[self.fakeBottomDrawer viewWillAppear:YES];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.headerShadowLayer.elevation, 4, 0.001);
}
- (void)testMaximumInitialDrawerHeightWhenPreferredContentSizeIsntUpdatedYet {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 0);
// When
CGFloat drawerHeight = [self.fakeBottomDrawer calculateMaximumInitialDrawerHeight];
// Then
XCTAssertEqualWithAccuracy(drawerHeight, 250, 0.001);
}
- (void)testSettingShouldIncludeSafeAreaInContentHeight {
// Given
self.drawerViewController.shouldIncludeSafeAreaInContentHeight = YES;
// When
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
[presentationController presentationTransitionWillBegin];
// Then
XCTAssertTrue(presentationController.shouldIncludeSafeAreaInContentHeight);
XCTAssertTrue(presentationController.bottomDrawerContainerViewController
.shouldIncludeSafeAreaInContentHeight);
}
- (void)testFullScreenContentLayoutCalculationsComplete {
// Given
UIViewController *fakeViewController = [[UIViewController alloc] init];
fakeViewController.view.frame = CGRectMake(0, 0, 200, UIScreen.mainScreen.bounds.size.height);
self.drawerViewController.contentViewController = fakeViewController;
[self.drawerViewController expandToFullscreenWithDuration:0 completion:nil];
// When
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
[presentationController.bottomDrawerContainerViewController cacheLayoutCalculations];
// Then
// This test was put in place to validate that cacheLayoutCalculations doesn't infinitely recurse
// It has no visible side effects, so as long as this test finishes, it passes
}
- (void)testSettingElevationInDrawerViewControllerPropogatesToPresentationController {
// Given
self.drawerViewController.elevation = 20;
// Then
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertEqualWithAccuracy(presentationController.elevation, 20, 0.001);
}
- (void)testCorrectDefaultElevationValue {
// When
[self.fakeBottomDrawer loadViewIfNeeded];
// Then
XCTAssertEqualWithAccuracy(((MDCShadowLayer *)self.fakeBottomDrawer.shadowedView.layer).elevation,
16, 0.001);
}
- (void)testElevationIsSetCorrectly {
// Given
self.fakeBottomDrawer.elevation = 12;
// When
[self.fakeBottomDrawer loadViewIfNeeded];
// Then
XCTAssertEqualWithAccuracy(((MDCShadowLayer *)self.fakeBottomDrawer.shadowedView.layer).elevation,
12, 0.001);
}
- (void)testSettingElevationInPresentationControllerAfterPresentationWillPropagateCorrectly {
// When
[self.presentationController presentationTransitionWillBegin];
self.presentationController.elevation = 20;
// Then
MDCBottomDrawerContainerViewController *drawerContainer =
self.presentationController.bottomDrawerContainerViewController;
XCTAssertEqualWithAccuracy(drawerContainer.shadowedView.shadowLayer.elevation, 20, 0.001);
}
- (void)testSettingElevationInPresentationControllerBeforePresentationWillPropagateCorrectly {
// When
self.presentationController.elevation = 20;
[self.presentationController presentationTransitionWillBegin];
// Then
MDCBottomDrawerContainerViewController *drawerContainer =
self.presentationController.bottomDrawerContainerViewController;
XCTAssertEqualWithAccuracy(drawerContainer.shadowedView.shadowLayer.elevation, 20, 0.001);
}
- (void)testSettingShadowColorInDrawerViewControllerPropogatesToPresentationController {
// Given
self.drawerViewController.drawerShadowColor = UIColor.blueColor;
// Then
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
XCTAssertEqualObjects(presentationController.drawerShadowColor, UIColor.blueColor);
}
- (void)testCorrectDefaultShadowColorValue {
// When
[self.fakeBottomDrawer loadViewIfNeeded];
// Then
XCTAssertTrue(CGColorEqualToColor(self.fakeBottomDrawer.shadowedView.layer.shadowColor,
[UIColor colorWithWhite:0 alpha:(CGFloat)0.2].CGColor));
}
- (void)testShadowColorIsSetCorrectly {
// Given
self.drawerViewController.drawerShadowColor = UIColor.blueColor;
// When
[self.fakeBottomDrawer loadViewIfNeeded];
// Then
XCTAssertTrue(CGColorEqualToColor(self.fakeBottomDrawer.shadowedView.layer.shadowColor,
UIColor.blueColor.CGColor));
}
- (void)testSettingShadowColorInPresentationControllerAfterPresentationWillPropagateCorrectly {
// When
[self.presentationController presentationTransitionWillBegin];
self.presentationController.drawerShadowColor = UIColor.redColor;
// Then
MDCBottomDrawerContainerViewController *drawerContainer =
self.presentationController.bottomDrawerContainerViewController;
XCTAssertTrue(CGColorEqualToColor(drawerContainer.shadowedView.layer.shadowColor,
UIColor.redColor.CGColor));
}
- (void)testSettingShadowColorInPresentationControllerBeforePresentationWillPropagateCorrectly {
// When
self.presentationController.drawerShadowColor = UIColor.redColor;
[self.presentationController presentationTransitionWillBegin];
// Then
MDCBottomDrawerContainerViewController *drawerContainer =
self.presentationController.bottomDrawerContainerViewController;
XCTAssertTrue(CGColorEqualToColor(drawerContainer.shadowedView.layer.shadowColor,
UIColor.redColor.CGColor));
}
- (void)testSettingTrackingScrollViewAfterInit {
// Given
[self.presentationController presentationTransitionWillBegin];
UIScrollView *newTrackingScrollView = [[UIScrollView alloc] init];
// When
self.presentationController.trackingScrollView = newTrackingScrollView;
// Then
MDCBottomDrawerContainerViewController *drawerContainer =
self.presentationController.bottomDrawerContainerViewController;
XCTAssertEqualObjects(drawerContainer.trackingScrollView, newTrackingScrollView);
}
- (void)testUpdatingMaximumInitialDrawerHeightWithLargePreferredContentSize {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 1000);
// When
self.fakeBottomDrawer.maximumInitialDrawerHeight = 100;
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 400, 0.001);
// When
self.fakeBottomDrawer.maximumInitialDrawerHeight = 300;
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 200, 0.001);
}
- (void)testUpdatingPreferredContentSizeWithLargeMaximumInitialDrawerHeight {
// Given
CGRect fakeRect = CGRectMake(0, 0, 250, 500);
self.fakeBottomDrawer.originalPresentingViewController.view.bounds = fakeRect;
self.fakeBottomDrawer.maximumInitialDrawerHeight = 500;
self.fakeBottomDrawer.shouldAdjustOnContentSizeChange = YES;
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 100);
[self.fakeBottomDrawer
preferredContentSizeDidChangeForChildContentContainer:self.fakeBottomDrawer
.contentViewController];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 400, 0.001);
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 300);
[self.fakeBottomDrawer
preferredContentSizeDidChangeForChildContentContainer:self.fakeBottomDrawer
.contentViewController];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 200, 0.001);
// When
self.fakeBottomDrawer.contentViewController.preferredContentSize = CGSizeMake(250, 50);
[self.fakeBottomDrawer
preferredContentSizeDidChangeForChildContentContainer:self.fakeBottomDrawer
.contentViewController];
// Then
XCTAssertEqualWithAccuracy(self.fakeBottomDrawer.contentHeaderTopInset, 450, 0.001);
}
@end