mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-02-20 08:27:32 +08:00
Dropping the MDC prefix to match the majority of the other test cases. Part of https://github.com/material-components/material-components-ios/issues/5185
306 lines
11 KiB
Swift
306 lines
11 KiB
Swift
// 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
|
|
import MaterialComponents.MaterialAppBar
|
|
|
|
private class MockAppBarNavigationControllerDelegate:
|
|
NSObject, MDCAppBarNavigationControllerDelegate {
|
|
var trackingScrollView: UIScrollView?
|
|
func appBarNavigationController(_ navigationController: MDCAppBarNavigationController,
|
|
trackingScrollViewFor trackingScrollViewForViewController: UIViewController,
|
|
suggestedTrackingScrollView: UIScrollView?) -> UIScrollView? {
|
|
return trackingScrollView
|
|
}
|
|
}
|
|
|
|
class AppBarNavigationControllerTests: XCTestCase {
|
|
|
|
var navigationController: MDCAppBarNavigationController!
|
|
override func setUp() {
|
|
super.setUp()
|
|
|
|
navigationController = MDCAppBarNavigationController()
|
|
}
|
|
|
|
override func tearDown() {
|
|
navigationController = nil
|
|
|
|
super.tearDown()
|
|
}
|
|
// MARK: - AppBar injection
|
|
|
|
func testInitializingWithRootViewControllerInjectsAnAppBar() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
|
|
// When
|
|
let navigationController = MDCAppBarNavigationController(rootViewController: viewController)
|
|
|
|
// Then
|
|
XCTAssertEqual(viewController.children.count, 1,
|
|
"Expected there to be exactly one child view controller added to the view"
|
|
+ " controller.")
|
|
|
|
XCTAssertEqual(navigationController.topViewController, viewController,
|
|
"The navigation controller's top view controller is supposed to be the pushed"
|
|
+ " view controller, but it is \(viewController).")
|
|
|
|
XCTAssertTrue(viewController.children.first is MDCFlexibleHeaderViewController,
|
|
"The injected view controller is not a flexible header view controller, it is"
|
|
+ "\(String(describing: viewController.children.first)) instead.")
|
|
|
|
if let headerViewController
|
|
= viewController.children.first as? MDCFlexibleHeaderViewController {
|
|
XCTAssertEqual(headerViewController.headerView.frame.height,
|
|
headerViewController.headerView.maximumHeight)
|
|
}
|
|
}
|
|
|
|
func testPushingAViewControllerInjectsAnAppBar() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
|
|
// When
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
XCTAssertEqual(viewController.children.count, 1,
|
|
"Expected there to be exactly one child view controller added to the view"
|
|
+ " controller.")
|
|
|
|
XCTAssertEqual(navigationController.topViewController, viewController,
|
|
"The navigation controller's top view controller is supposed to be the pushed"
|
|
+ " view controller, but it is \(viewController).")
|
|
|
|
XCTAssertTrue(viewController.children.first is MDCFlexibleHeaderViewController,
|
|
"The injected view controller is not a flexible header view controller, it is"
|
|
+ "\(String(describing: viewController.children.first)) instead.")
|
|
|
|
if let headerViewController
|
|
= viewController.children.first as? MDCFlexibleHeaderViewController {
|
|
XCTAssertEqual(headerViewController.headerView.frame.height,
|
|
headerViewController.headerView.maximumHeight)
|
|
}
|
|
}
|
|
|
|
func testPushingAnAppBarContainerViewControllerDoesNotInjectAnAppBar() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let container = MDCAppBarContainerViewController(contentViewController: viewController)
|
|
|
|
// When
|
|
navigationController.pushViewController(container, animated: false)
|
|
|
|
// Then
|
|
XCTAssertEqual(container.children.count, 2,
|
|
"An App Bar container view controller should have exactly two child view"
|
|
+ " controllers. A failure of this assertion implies that the navigation"
|
|
+ " controller may have injected another App Bar.")
|
|
}
|
|
|
|
func testPushingAContainedAppBarContainerViewControllerDoesNotInjectAnAppBar() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let container = MDCAppBarContainerViewController(contentViewController: viewController)
|
|
let nestedContainer = UIViewController()
|
|
nestedContainer.addChild(container)
|
|
nestedContainer.view.addSubview(container.view)
|
|
container.didMove(toParent: nestedContainer)
|
|
|
|
// When
|
|
navigationController.pushViewController(nestedContainer, animated: false)
|
|
|
|
// Then
|
|
XCTAssertEqual(nestedContainer.children.count, 1,
|
|
"The view controller hierarchy already has one app bar view controller, but it"
|
|
+ " appears to have possibly added another.")
|
|
}
|
|
|
|
func testPushingAViewControllerWithAFlexibleHeaderDoesNotInjectAnAppBar() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let fhvc = MDCFlexibleHeaderViewController()
|
|
viewController.addChild(fhvc)
|
|
viewController.view.addSubview(fhvc.view)
|
|
fhvc.didMove(toParent: viewController)
|
|
|
|
// When
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
XCTAssertEqual(viewController.children.count, 1,
|
|
"The navigation controller may have injected another App Bar when it shouldn't"
|
|
+ " have.")
|
|
}
|
|
|
|
// MARK: - traitCollectionDidChangeBlock support
|
|
|
|
func testInitializingWithRootViewControllerDoesNotSetTraitCollectionDidChangeBlock() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
|
|
// When
|
|
let _ = MDCAppBarNavigationController(rootViewController: viewController)
|
|
|
|
// Then
|
|
let injectedAppBarViewController = viewController.children.first as! MDCAppBarViewController
|
|
XCTAssertNotNil(injectedAppBarViewController)
|
|
XCTAssertNil(injectedAppBarViewController.traitCollectionDidChangeBlock)
|
|
}
|
|
|
|
func testPushingAViewControllerAssignsTraitCollectionDidChangeBlock() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let block: ((MDCFlexibleHeaderViewController, UITraitCollection?) -> Void)? = {_, _ in }
|
|
navigationController.traitCollectionDidChangeBlockForAppBarController = block
|
|
|
|
// When
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
let injectedAppBarViewController = viewController.children.first as! MDCAppBarViewController
|
|
XCTAssertNotNil(injectedAppBarViewController)
|
|
XCTAssertNotNil(injectedAppBarViewController.traitCollectionDidChangeBlock)
|
|
}
|
|
|
|
func testPushingAnAppBarContainerViewControllerDoesNotAssignTraitCollectionDidChangeBlock() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let container = MDCAppBarContainerViewController(contentViewController: viewController)
|
|
var blockSemaphore = false
|
|
let block: ((MDCFlexibleHeaderViewController, UITraitCollection?) -> Void)? =
|
|
{ _, _ in
|
|
blockSemaphore = true
|
|
}
|
|
container.appBarViewController.traitCollectionDidChangeBlock = block
|
|
|
|
// When
|
|
navigationController.pushViewController(container, animated: false)
|
|
container.appBarViewController.traitCollectionDidChange(nil)
|
|
|
|
// Then
|
|
XCTAssertTrue(blockSemaphore)
|
|
}
|
|
|
|
func testPushingAContainedAppBarContainerViewControllerDoesNotAssignTraitCollectionDidChangeBlock() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let container = MDCAppBarContainerViewController(contentViewController: viewController)
|
|
let nestedContainer = UIViewController()
|
|
nestedContainer.addChild(container)
|
|
nestedContainer.view.addSubview(container.view)
|
|
container.didMove(toParent: nestedContainer)
|
|
var blockSemaphore = false
|
|
let block: ((MDCFlexibleHeaderViewController, UITraitCollection?) -> Void)? =
|
|
{ _, _ in
|
|
blockSemaphore = true
|
|
}
|
|
container.appBarViewController.traitCollectionDidChangeBlock = block
|
|
|
|
|
|
// When
|
|
navigationController.pushViewController(nestedContainer, animated: false)
|
|
container.appBarViewController.traitCollectionDidChange(nil)
|
|
|
|
// Then
|
|
XCTAssertTrue(blockSemaphore)
|
|
}
|
|
|
|
// MARK: - The rest
|
|
|
|
func testStatusBarStyleIsFetchedFromFlexibleHeaderViewController() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
|
|
// When
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
let appBar = navigationController.appBar(for: viewController)
|
|
|
|
XCTAssertNotNil(appBar, "Could not retrieve the injected App Bar.")
|
|
|
|
if let appBar = appBar {
|
|
XCTAssertEqual(navigationController.childForStatusBarStyle,
|
|
appBar.headerViewController,
|
|
"The navigation controller should be using the injected app bar's flexible"
|
|
+ "header view controller for status bar style updates.")
|
|
}
|
|
}
|
|
|
|
func testInfersFirstTrackingScrollViewByDefault() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let scrollView1 = UIScrollView()
|
|
viewController.view.addSubview(scrollView1)
|
|
let scrollView2 = UIScrollView()
|
|
viewController.view.addSubview(scrollView2)
|
|
|
|
// When
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
guard let appBarViewController = navigationController.appBarViewController(for: viewController) else {
|
|
XCTFail("No app bar view controller found.")
|
|
return
|
|
}
|
|
XCTAssertEqual(appBarViewController.headerView.trackingScrollView, scrollView1)
|
|
}
|
|
|
|
func testDelegateCanReturnNilTrackingScrollView() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let scrollView1 = UIScrollView()
|
|
viewController.view.addSubview(scrollView1)
|
|
let scrollView2 = UIScrollView()
|
|
viewController.view.addSubview(scrollView2)
|
|
let delegate = MockAppBarNavigationControllerDelegate()
|
|
navigationController.delegate = delegate
|
|
|
|
// When
|
|
delegate.trackingScrollView = nil
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
guard let appBarViewController = navigationController.appBarViewController(for: viewController) else {
|
|
XCTFail("No app bar view controller found.")
|
|
return
|
|
}
|
|
XCTAssertNil(appBarViewController.headerView.trackingScrollView)
|
|
}
|
|
|
|
func testDelegateCanPickDifferentTrackingScrollView() {
|
|
// Given
|
|
let viewController = UIViewController()
|
|
let scrollView1 = UIScrollView()
|
|
viewController.view.addSubview(scrollView1)
|
|
let scrollView2 = UIScrollView()
|
|
viewController.view.addSubview(scrollView2)
|
|
let delegate = MockAppBarNavigationControllerDelegate()
|
|
navigationController.delegate = delegate
|
|
|
|
// When
|
|
delegate.trackingScrollView = scrollView2
|
|
navigationController.pushViewController(viewController, animated: false)
|
|
|
|
// Then
|
|
guard let appBarViewController = navigationController.appBarViewController(for: viewController) else {
|
|
XCTFail("No app bar view controller found.")
|
|
return
|
|
}
|
|
XCTAssertEqual(appBarViewController.headerView.trackingScrollView, scrollView2)
|
|
}
|
|
}
|