Swift 2.2 curried functions for asserting IB outlets and actions are wired up correctly.
// | |
// SpecFunctions.swift | |
// | |
// Created by Ben Chatelain on 6/6/15. | |
// Copyright (c) 2015-2016 Ben Chatelain. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// 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 NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS 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 Quick | |
import Nimble | |
import UIKit | |
typealias ButtonTest = String -> AnyObject? | |
typealias CurriedOutletTest = (UIViewController) -> (String -> AnyObject?) | |
typealias CurriedButtonTest = (UIViewController) -> (AnyClass -> (String -> AnyObject?)) | |
// MARK: - Outlets | |
func outlet(viewController: UIViewController)(_ outlet: String) -> AnyObject? { | |
guard let object = viewController.valueForKey(outlet) | |
else { fail("\(outlet) outlet was nil"); return nil } | |
return object | |
} | |
func outlet<T>(viewController: UIViewController)(type: T.Type)(_ expectedOutlet: String) -> T? { | |
guard let object = outlet(viewController)(expectedOutlet) | |
else { return nil } | |
debugPrint(object.dynamicType) | |
guard let objectOfType = object as? T | |
else { fail("\(object) outlet was not a \(type)"); return nil } | |
return objectOfType | |
} | |
// MARK: - Actions | |
func action<T>(viewController: UIViewController)(type: T.Type) | |
(_ expectedAction: String, from expectedOutlet: String) { | |
let optionalControl = outlet(viewController)(type: type)(expectedOutlet) | |
var target: AnyObject? | |
var action: String? | |
if let control = optionalControl { | |
switch control { | |
case let button as UIBarButtonItem: | |
target = button.target | |
action = button.action.description | |
case let control as UIControl: | |
target = control.allTargets().first! | |
var allActions: [String] = [] | |
for event: UIControlEvents in [.TouchUpInside, .ValueChanged] { | |
allActions += control.actionsForTarget(target!, forControlEvent: event) ?? [] | |
} | |
// Filter down to the expected action | |
action = allActions.filter({$0 == expectedAction}).first! | |
default: | |
fail("Unhandled control type: \(control.dynamicType)") | |
} | |
} | |
expect(target) === viewController | |
expect(action).toNot(beNil()) | |
if let action = action { | |
expect(action) == expectedAction | |
} | |
} |
import Quick | |
import Nimble | |
import UIKit | |
class ViewControllerSpec: QuickSpec { | |
override func spec() { | |
// Start with an empty object so property can be non-optional | |
// Also needs to be initialized before passing to curried helper functions. | |
var viewController = ViewController() | |
beforeEach { | |
viewController = StoryboardScene.Workspace.instantiateSettingsTable() | |
viewController.loadView() | |
expect(viewController.view).toNot(beNil()) | |
} | |
var hasButtonOutlet = outlet(viewController)(type: UIBarButtonItem.self) | |
var receivesAction = action(viewController)(type: UIBarButtonItem.self) | |
describe("view controller") { | |
// MARK: - Outlets | |
it("has a leftDoneButton outlet") { | |
hasButtonOutlet("leftDoneButton") | |
} | |
it("has a rightDoneButton outlet") { | |
hasButtonOutlet("rightDoneButton") | |
} | |
// MARK: - Actions | |
it("receives a didTapDone action from leftDoneButton") { | |
receivesAction("didTapDone", from: "leftDoneButton") | |
} | |
it("receives a didTapDone action from rightDoneButton") { | |
receivesAction("didTapDone", from: "rightDoneButton") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment