376 lines
10 KiB
Swift
376 lines
10 KiB
Swift
//
|
|
// DelegateProxyTest.swift
|
|
// RxTests
|
|
//
|
|
// Created by Krunoslav Zaher on 7/5/15.
|
|
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import XCTest
|
|
import RxSwift
|
|
import RxCocoa
|
|
#if os(iOS)
|
|
import UIKit
|
|
#endif
|
|
|
|
// MARK: Protocols
|
|
|
|
@objc protocol TestDelegateProtocol {
|
|
@objc optional func testEventHappened(_ value: Int)
|
|
}
|
|
|
|
@objc class MockTestDelegateProtocol
|
|
: NSObject
|
|
, TestDelegateProtocol
|
|
{
|
|
var numbers = [Int]()
|
|
|
|
func testEventHappened(_ value: Int) {
|
|
numbers.append(value)
|
|
}
|
|
}
|
|
|
|
protocol TestDelegateControl: NSObjectProtocol {
|
|
func doThatTest(_ value: Int)
|
|
|
|
var test: Observable<Int> { get }
|
|
|
|
func setMineForwardDelegate(_ testDelegate: TestDelegateProtocol) -> Disposable
|
|
}
|
|
|
|
// MARK: Tests
|
|
|
|
class DelegateProxyTest : RxTest {
|
|
func test_OnInstallDelegateIsRetained() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
let _ = view.rx_proxy
|
|
|
|
XCTAssertEqual(mock.messages, [])
|
|
XCTAssertTrue(view.rx_proxy.forwardToDelegate() === mock)
|
|
}
|
|
|
|
func test_forwardsUnobservedMethods() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
let _ = view.rx_proxy
|
|
|
|
view.delegate?.threeDView?(view, didLearnSomething: "Psssst ...")
|
|
|
|
XCTAssertEqual(mock.messages, ["didLearnSomething"])
|
|
}
|
|
|
|
func test_forwardsObservedMethods() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
var observedFeedRequest = false
|
|
|
|
let d = view.rx_proxy.observe(#selector(ThreeDSectionedViewProtocol.threeDView(_:didLearnSomething:)))
|
|
.subscribe(onNext: { n in
|
|
observedFeedRequest = true
|
|
})
|
|
defer {
|
|
d.dispose()
|
|
}
|
|
|
|
XCTAssertTrue(!observedFeedRequest)
|
|
view.delegate?.threeDView?(view, didLearnSomething: "Psssst ...")
|
|
XCTAssertTrue(observedFeedRequest)
|
|
|
|
XCTAssertEqual(mock.messages, ["didLearnSomething"])
|
|
}
|
|
|
|
func test_forwardsObserverDispose() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
var nMessages = 0
|
|
|
|
let d = view.rx_proxy.observe(#selector(ThreeDSectionedViewProtocol.threeDView(_:didLearnSomething:)))
|
|
.subscribe(onNext: { n in
|
|
nMessages += 1
|
|
})
|
|
|
|
XCTAssertTrue(nMessages == 0)
|
|
view.delegate?.threeDView?(view, didLearnSomething: "Psssst ...")
|
|
XCTAssertTrue(nMessages == 1)
|
|
|
|
d.dispose()
|
|
|
|
view.delegate?.threeDView?(view, didLearnSomething: "Psssst ...")
|
|
XCTAssertTrue(nMessages == 1)
|
|
}
|
|
|
|
func test_forwardsUnobservableMethods() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
view.delegate?.threeDView?(view, didLearnSomething: "Psssst ...")
|
|
|
|
XCTAssertEqual(mock.messages, ["didLearnSomething"])
|
|
}
|
|
|
|
func test_observesUnimplementedOptionalMethods() {
|
|
let view = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
XCTAssertTrue(!mock.responds(to: NSSelectorFromString("threeDView(threeDView:didGetXXX:")))
|
|
|
|
let sentArgument = IndexPath(index: 0)
|
|
|
|
var receivedArgument: IndexPath? = nil
|
|
|
|
let d = view.rx_proxy.observe(#selector(ThreeDSectionedViewProtocol.threeDView(_:didGetXXX:)))
|
|
.subscribe(onNext: { n in
|
|
let ip = n[1] as! IndexPath
|
|
receivedArgument = ip
|
|
})
|
|
defer {
|
|
d.dispose()
|
|
}
|
|
|
|
view.delegate?.threeDView?(view, didGetXXX: sentArgument)
|
|
XCTAssertTrue(receivedArgument == sentArgument)
|
|
|
|
XCTAssertEqual(mock.messages, [])
|
|
}
|
|
|
|
func test_delegateProxyCompletesOnDealloc() {
|
|
var view: ThreeDSectionedView! = ThreeDSectionedView()
|
|
let mock = MockThreeDSectionedViewProtocol()
|
|
|
|
view.delegate = mock
|
|
|
|
var completed = false
|
|
|
|
autoreleasepool {
|
|
XCTAssertTrue(!mock.responds(to: NSSelectorFromString("threeDView:threeDView:didGetXXX:")))
|
|
|
|
let sentArgument = IndexPath(index: 0)
|
|
|
|
_ = view
|
|
.rx_proxy
|
|
.observe(#selector(ThreeDSectionedViewProtocol.threeDView(_:didGetXXX:)))
|
|
.subscribe(onCompleted: {
|
|
completed = true
|
|
})
|
|
|
|
view.delegate?.threeDView?(view, didGetXXX: sentArgument)
|
|
}
|
|
XCTAssertTrue(!completed)
|
|
view = nil
|
|
XCTAssertTrue(completed)
|
|
}
|
|
}
|
|
|
|
#if os(iOS)
|
|
extension DelegateProxyTest {
|
|
func test_DelegateProxyHierarchyWorks() {
|
|
let tableView = UITableView()
|
|
_ = tableView.rx_delegate.observe(#selector(UIScrollViewDelegate.scrollViewWillBeginDragging(_:)))
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// MARK: Testing extensions
|
|
|
|
extension DelegateProxyTest {
|
|
func performDelegateTest<Control: TestDelegateControl>( _ createControl: @autoclosure() -> Control) {
|
|
var control: TestDelegateControl!
|
|
|
|
autoreleasepool {
|
|
control = createControl()
|
|
}
|
|
|
|
var receivedValue: Int!
|
|
var completed = false
|
|
var deallocated = false
|
|
|
|
autoreleasepool {
|
|
_ = control.test.subscribe(onNext: { value in
|
|
receivedValue = value
|
|
}, onCompleted: {
|
|
completed = true
|
|
})
|
|
|
|
_ = (control as! NSObject).rx_deallocated.subscribe(onNext: { _ in
|
|
deallocated = true
|
|
})
|
|
}
|
|
|
|
XCTAssertTrue(receivedValue == nil)
|
|
autoreleasepool {
|
|
control.doThatTest(382763)
|
|
}
|
|
XCTAssertEqual(receivedValue, 382763)
|
|
|
|
autoreleasepool {
|
|
let mine = MockTestDelegateProtocol()
|
|
let disposable = control.setMineForwardDelegate(mine)
|
|
|
|
XCTAssertEqual(mine.numbers, [])
|
|
control.doThatTest(2)
|
|
XCTAssertEqual(mine.numbers, [2])
|
|
disposable.dispose()
|
|
control.doThatTest(3)
|
|
XCTAssertEqual(mine.numbers, [2])
|
|
}
|
|
|
|
XCTAssertFalse(deallocated)
|
|
XCTAssertFalse(completed)
|
|
autoreleasepool {
|
|
control = nil
|
|
}
|
|
XCTAssertTrue(deallocated)
|
|
XCTAssertTrue(completed)
|
|
}
|
|
}
|
|
|
|
// MARK: Mocks
|
|
|
|
// test case {
|
|
|
|
class Food: NSObject {
|
|
}
|
|
|
|
@objc protocol ThreeDSectionedViewProtocol {
|
|
func threeDView(_ threeDView: ThreeDSectionedView, listenToMeee: IndexPath)
|
|
func threeDView(_ threeDView: ThreeDSectionedView, feedMe: IndexPath)
|
|
func threeDView(_ threeDView: ThreeDSectionedView, howTallAmI: IndexPath) -> CGFloat
|
|
|
|
@objc optional func threeDView(_ threeDView: ThreeDSectionedView, didGetXXX: IndexPath)
|
|
@objc optional func threeDView(_ threeDView: ThreeDSectionedView, didLearnSomething: String)
|
|
@objc optional func threeDView(_ threeDView: ThreeDSectionedView, didFallAsleep: IndexPath)
|
|
@objc optional func threeDView(_ threeDView: ThreeDSectionedView, getMeSomeFood: IndexPath) -> Food
|
|
}
|
|
|
|
class ThreeDSectionedView: NSObject {
|
|
var delegate: ThreeDSectionedViewProtocol?
|
|
}
|
|
|
|
// }
|
|
|
|
// integration {
|
|
|
|
class ThreeDSectionedViewDelegateProxy : DelegateProxy
|
|
, ThreeDSectionedViewProtocol
|
|
, DelegateProxyType {
|
|
required init(parentObject: AnyObject) {
|
|
super.init(parentObject: parentObject)
|
|
}
|
|
|
|
// delegate
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, listenToMeee: IndexPath) {
|
|
|
|
}
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, feedMe: IndexPath) {
|
|
|
|
}
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, howTallAmI: IndexPath) -> CGFloat {
|
|
return 1.1
|
|
}
|
|
|
|
// integration
|
|
|
|
class func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) {
|
|
let view = object as! ThreeDSectionedView
|
|
view.delegate = delegate as? ThreeDSectionedViewProtocol
|
|
}
|
|
|
|
class func currentDelegateFor(_ object: AnyObject) -> AnyObject? {
|
|
let view = object as! ThreeDSectionedView
|
|
return view.delegate
|
|
}
|
|
}
|
|
|
|
extension ThreeDSectionedView {
|
|
var rx_proxy: DelegateProxy {
|
|
return ThreeDSectionedViewDelegateProxy.proxyForObject(self)
|
|
}
|
|
}
|
|
|
|
// }
|
|
|
|
class MockThreeDSectionedViewProtocol : NSObject, ThreeDSectionedViewProtocol {
|
|
|
|
var messages: [String] = []
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, listenToMeee: IndexPath) {
|
|
messages.append("listenToMeee")
|
|
}
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, feedMe: IndexPath) {
|
|
messages.append("feedMe")
|
|
}
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, howTallAmI: IndexPath) -> CGFloat {
|
|
messages.append("howTallAmI")
|
|
return 3
|
|
}
|
|
|
|
/*func threeDView(threeDView: ThreeDSectionedView, didGetXXX: IndexPath) {
|
|
messages.append("didGetXXX")
|
|
}*/
|
|
|
|
func threeDView(_ threeDView: ThreeDSectionedView, didLearnSomething: String) {
|
|
messages.append("didLearnSomething")
|
|
}
|
|
|
|
//optional func threeDView(threeDView: ThreeDSectionedView, didFallAsleep: IndexPath)
|
|
func threeDView(_ threeDView: ThreeDSectionedView, getMeSomeFood: IndexPath) -> Food {
|
|
messages.append("getMeSomeFood")
|
|
return Food()
|
|
}
|
|
}
|
|
|
|
#if os(OSX)
|
|
extension MockTestDelegateProtocol
|
|
: NSTextFieldDelegate {
|
|
|
|
}
|
|
#endif
|
|
|
|
#if os(iOS) || os(tvOS)
|
|
extension MockTestDelegateProtocol
|
|
: UICollectionViewDataSource
|
|
, UIScrollViewDelegate
|
|
, UITableViewDataSource
|
|
, UITableViewDelegate {
|
|
|
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
fatalError()
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
fatalError()
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
fatalError()
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
fatalError()
|
|
}
|
|
}
|
|
#endif
|