ObjectiveCBridgingSpec.swift 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. //
  2. // ObjectiveCBridgingSpec.swift
  3. // ReactiveCocoa
  4. //
  5. // Created by Justin Spahr-Summers on 2015-01-23.
  6. // Copyright (c) 2015 GitHub. All rights reserved.
  7. //
  8. import Result
  9. import Nimble
  10. import Quick
  11. import ReactiveCocoa
  12. import XCTest
  13. class ObjectiveCBridgingSpec: QuickSpec {
  14. override func spec() {
  15. describe("RACScheduler") {
  16. var originalScheduler: RACTestScheduler!
  17. var scheduler: DateSchedulerType!
  18. beforeEach {
  19. originalScheduler = RACTestScheduler()
  20. scheduler = originalScheduler as DateSchedulerType
  21. }
  22. it("gives current date") {
  23. expect(scheduler.currentDate).to(beCloseTo(NSDate()))
  24. }
  25. it("schedules actions") {
  26. var actionRan: Bool = false
  27. scheduler.schedule {
  28. actionRan = true
  29. }
  30. expect(actionRan) == false
  31. originalScheduler.step()
  32. expect(actionRan) == true
  33. }
  34. it("does not invoke action if disposed") {
  35. var actionRan: Bool = false
  36. let disposable: Disposable? = scheduler.schedule {
  37. actionRan = true
  38. }
  39. expect(actionRan) == false
  40. disposable!.dispose()
  41. originalScheduler.step()
  42. expect(actionRan) == false
  43. }
  44. }
  45. describe("RACSignal.toSignalProducer") {
  46. it("should subscribe once per start()") {
  47. var subscriptions = 0
  48. let racSignal = RACSignal.createSignal { subscriber in
  49. subscriber.sendNext(subscriptions)
  50. subscriber.sendCompleted()
  51. subscriptions += 1
  52. return nil
  53. }
  54. let producer = racSignal.toSignalProducer().map { $0 as! Int }
  55. expect((producer.single())?.value) == 0
  56. expect((producer.single())?.value) == 1
  57. expect((producer.single())?.value) == 2
  58. }
  59. it("should forward errors") {
  60. let error = TestError.Default as NSError
  61. let racSignal = RACSignal.error(error)
  62. let producer = racSignal.toSignalProducer()
  63. let result = producer.last()
  64. expect(result?.error) == error
  65. }
  66. }
  67. describe("toRACSignal") {
  68. let key = "TestKey"
  69. let userInfo: [String: String] = [key: "TestValue"]
  70. let testNSError = NSError(domain: "TestDomain", code: 1, userInfo: userInfo)
  71. describe("on a Signal") {
  72. it("should forward events") {
  73. let (signal, observer) = Signal<NSNumber, NoError>.pipe()
  74. let racSignal = signal.toRACSignal()
  75. var lastValue: NSNumber?
  76. var didComplete = false
  77. racSignal.subscribeNext({ number in
  78. lastValue = number as? NSNumber
  79. }, completed: {
  80. didComplete = true
  81. })
  82. expect(lastValue).to(beNil())
  83. for number in [1, 2, 3] {
  84. observer.sendNext(number)
  85. expect(lastValue) == number
  86. }
  87. expect(didComplete) == false
  88. observer.sendCompleted()
  89. expect(didComplete) == true
  90. }
  91. it("should convert errors to NSError") {
  92. let (signal, observer) = Signal<AnyObject, TestError>.pipe()
  93. let racSignal = signal.toRACSignal()
  94. let expectedError = TestError.Error2
  95. var error: NSError?
  96. racSignal.subscribeError {
  97. error = $0
  98. return
  99. }
  100. observer.sendFailed(expectedError)
  101. expect(error) == expectedError as NSError
  102. }
  103. it("should maintain userInfo on NSError") {
  104. let (signal, observer) = Signal<AnyObject, NSError>.pipe()
  105. let racSignal = signal.toRACSignal()
  106. var error: NSError?
  107. racSignal.subscribeError {
  108. error = $0
  109. return
  110. }
  111. observer.sendFailed(testNSError)
  112. let userInfoValue = error?.userInfo[key] as? String
  113. expect(userInfoValue) == userInfo[key]
  114. }
  115. }
  116. describe("on a SignalProducer") {
  117. it("should start once per subscription") {
  118. var subscriptions = 0
  119. let producer = SignalProducer<NSNumber, NoError>.attempt {
  120. defer {
  121. subscriptions += 1
  122. }
  123. return .Success(subscriptions)
  124. }
  125. let racSignal = producer.toRACSignal()
  126. expect(racSignal.first() as? NSNumber) == 0
  127. expect(racSignal.first() as? NSNumber) == 1
  128. expect(racSignal.first() as? NSNumber) == 2
  129. }
  130. it("should convert errors to NSError") {
  131. let producer = SignalProducer<AnyObject, TestError>(error: .Error1)
  132. let racSignal = producer.toRACSignal().materialize()
  133. let event = racSignal.first() as? RACEvent
  134. expect(event?.error) == TestError.Error1 as NSError
  135. }
  136. it("should maintain userInfo on NSError") {
  137. let producer = SignalProducer<AnyObject, NSError>(error: testNSError)
  138. let racSignal = producer.toRACSignal().materialize()
  139. let event = racSignal.first() as? RACEvent
  140. let userInfoValue = event?.error.userInfo[key] as? String
  141. expect(userInfoValue) == userInfo[key]
  142. }
  143. }
  144. }
  145. describe("RACCommand.toAction") {
  146. var command: RACCommand!
  147. var results: [Int] = []
  148. var enabledSubject: RACSubject!
  149. var enabled = false
  150. var action: Action<AnyObject?, AnyObject?, NSError>!
  151. beforeEach {
  152. enabledSubject = RACSubject()
  153. results = []
  154. command = RACCommand(enabled: enabledSubject) { (input: AnyObject?) -> RACSignal! in
  155. let inputNumber = input as! Int
  156. return RACSignal.`return`(inputNumber + 1)
  157. }
  158. expect(command).notTo(beNil())
  159. command.enabled.subscribeNext { enabled = $0 as! Bool }
  160. expect(enabled) == true
  161. command.executionSignals.flatten().subscribeNext { results.append($0 as! Int) }
  162. expect(results) == []
  163. action = command.toAction()
  164. }
  165. it("should reflect the enabledness of the command") {
  166. expect(action.enabled.value) == true
  167. enabledSubject.sendNext(false)
  168. expect(enabled).toEventually(beFalsy())
  169. expect(action.enabled.value) == false
  170. }
  171. it("should execute the command once per start()") {
  172. let producer = action.apply(0)
  173. expect(results) == []
  174. producer.start()
  175. expect(results).toEventually(equal([ 1 ]))
  176. producer.start()
  177. expect(results).toEventually(equal([ 1, 1 ]))
  178. let otherProducer = action.apply(2)
  179. expect(results) == [ 1, 1 ]
  180. otherProducer.start()
  181. expect(results).toEventually(equal([ 1, 1, 3 ]))
  182. producer.start()
  183. expect(results).toEventually(equal([ 1, 1, 3, 1 ]))
  184. }
  185. }
  186. describe("toRACCommand") {
  187. var action: Action<AnyObject?, NSString, TestError>!
  188. var results: [NSString] = []
  189. var enabledProperty: MutableProperty<Bool>!
  190. var command: RACCommand!
  191. var enabled = false
  192. beforeEach {
  193. results = []
  194. enabledProperty = MutableProperty(true)
  195. action = Action(enabledIf: enabledProperty) { input in
  196. let inputNumber = input as! Int
  197. return SignalProducer(value: "\(inputNumber + 1)")
  198. }
  199. expect(action.enabled.value) == true
  200. action.values.observeNext { results.append($0) }
  201. command = toRACCommand(action)
  202. expect(command).notTo(beNil())
  203. command.enabled.subscribeNext { enabled = $0 as! Bool }
  204. expect(enabled) == true
  205. }
  206. it("should reflect the enabledness of the action") {
  207. enabledProperty.value = false
  208. expect(enabled).toEventually(beFalsy())
  209. enabledProperty.value = true
  210. expect(enabled).toEventually(beTruthy())
  211. }
  212. it("should apply and start a signal once per execution") {
  213. let signal = command.execute(0)
  214. do {
  215. try signal.asynchronouslyWaitUntilCompleted()
  216. expect(results) == [ "1" ]
  217. try signal.asynchronouslyWaitUntilCompleted()
  218. expect(results) == [ "1" ]
  219. try command.execute(2).asynchronouslyWaitUntilCompleted()
  220. expect(results) == [ "1", "3" ]
  221. } catch {
  222. XCTFail("Failed to wait for completion")
  223. }
  224. }
  225. }
  226. }
  227. }