SessionDelegateTests.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. //
  2. // SessionDelegateTests.swift
  3. //
  4. // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. @testable import Alamofire
  25. import Foundation
  26. import XCTest
  27. class SessionDelegateTestCase: BaseTestCase {
  28. var manager: SessionManager!
  29. // MARK: - Setup and Teardown
  30. override func setUp() {
  31. super.setUp()
  32. manager = SessionManager(configuration: .ephemeral)
  33. }
  34. // MARK: - Tests - Session Invalidation
  35. // TODO: Do we want closure API? Or some sort of event API we can plug closures into?
  36. // func testThatSessionDidBecomeInvalidWithErrorClosureIsCalledWhenSet() {
  37. // // Given
  38. // let expectation = self.expectation(description: "Override closure should be called")
  39. //
  40. // var overrideClosureCalled = false
  41. // var invalidationError: Error?
  42. //
  43. // manager.delegate.sessionDidBecomeInvalidWithError = { _, error in
  44. // overrideClosureCalled = true
  45. // invalidationError = error
  46. //
  47. // expectation.fulfill()
  48. // }
  49. //
  50. // // When
  51. // manager.session.invalidateAndCancel()
  52. // waitForExpectations(timeout: timeout, handler: nil)
  53. //
  54. // // Then
  55. // XCTAssertTrue(overrideClosureCalled)
  56. // XCTAssertNil(invalidationError)
  57. // }
  58. //
  59. // // MARK: - Tests - Session Challenges
  60. //
  61. // func testThatSessionDidReceiveChallengeClosureIsCalledWhenSet() {
  62. // // Given
  63. // let expectation = self.expectation(description: "Override closure should be called")
  64. //
  65. // var overrideClosureCalled = false
  66. // var response: HTTPURLResponse?
  67. //
  68. // manager.delegate.sessionDidReceiveChallenge = { session, challenge in
  69. // overrideClosureCalled = true
  70. // return (.performDefaultHandling, nil)
  71. // }
  72. //
  73. // // When
  74. // manager.request("https://httpbin.org/get").responseJSON { closureResponse in
  75. // response = closureResponse.response
  76. // expectation.fulfill()
  77. // }
  78. //
  79. // waitForExpectations(timeout: timeout, handler: nil)
  80. //
  81. // // Then
  82. // XCTAssertTrue(overrideClosureCalled)
  83. // XCTAssertEqual(response?.statusCode, 200)
  84. // }
  85. //
  86. // func testThatSessionDidReceiveChallengeWithCompletionClosureIsCalledWhenSet() {
  87. // // Given
  88. // let expectation = self.expectation(description: "Override closure should be called")
  89. //
  90. // var overrideClosureCalled = false
  91. // var response: HTTPURLResponse?
  92. //
  93. // manager.delegate.sessionDidReceiveChallengeWithCompletion = { session, challenge, completion in
  94. // overrideClosureCalled = true
  95. // completion(.performDefaultHandling, nil)
  96. // }
  97. //
  98. // // When
  99. // manager.request("https://httpbin.org/get").responseJSON { closureResponse in
  100. // response = closureResponse.response
  101. // expectation.fulfill()
  102. // }
  103. //
  104. // waitForExpectations(timeout: timeout, handler: nil)
  105. //
  106. // // Then
  107. // XCTAssertTrue(overrideClosureCalled)
  108. // XCTAssertEqual(response?.statusCode, 200)
  109. // }
  110. // MARK: - Tests - Redirects
  111. func testThatRequestWillPerformHTTPRedirectionByDefault() {
  112. // Given
  113. let redirectURLString = "https://www.apple.com/"
  114. let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  115. let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  116. var response: DataResponse<Data?>?
  117. // When
  118. manager.request(urlString)
  119. .response { resp in
  120. response = resp
  121. expectation.fulfill()
  122. }
  123. waitForExpectations(timeout: timeout, handler: nil)
  124. // Then
  125. XCTAssertNotNil(response?.request)
  126. XCTAssertNotNil(response?.response)
  127. XCTAssertNotNil(response?.data)
  128. XCTAssertNil(response?.error)
  129. XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  130. XCTAssertEqual(response?.response?.statusCode, 200)
  131. }
  132. func testThatRequestWillPerformRedirectionMultipleTimesByDefault() {
  133. // Given
  134. let redirectURLString = "https://httpbin.org/get"
  135. let urlString = "https://httpbin.org/redirect/5"
  136. let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  137. var response: DataResponse<Data?>?
  138. // When
  139. manager.request(urlString)
  140. .response { resp in
  141. response = resp
  142. expectation.fulfill()
  143. }
  144. waitForExpectations(timeout: timeout, handler: nil)
  145. // Then
  146. XCTAssertNotNil(response?.request)
  147. XCTAssertNotNil(response?.response)
  148. XCTAssertNotNil(response?.data)
  149. XCTAssertNil(response?.error)
  150. XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  151. XCTAssertEqual(response?.response?.statusCode, 200)
  152. }
  153. // func testThatTaskOverrideClosureCanPerformHTTPRedirection() {
  154. // // Given
  155. // let redirectURLString = "https://www.apple.com/"
  156. // let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  157. //
  158. // let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  159. // let callbackExpectation = self.expectation(description: "Redirect callback should be made")
  160. // let delegate: SessionDelegate = manager.delegate
  161. //
  162. // delegate.taskWillPerformHTTPRedirection = { _, _, _, request in
  163. // callbackExpectation.fulfill()
  164. // return request
  165. // }
  166. //
  167. // var response: DataResponse<Data?>?
  168. //
  169. // // When
  170. // manager.request(urlString)
  171. // .response { resp in
  172. // response = resp
  173. // expectation.fulfill()
  174. // }
  175. //
  176. // waitForExpectations(timeout: timeout, handler: nil)
  177. //
  178. // // Then
  179. // XCTAssertNotNil(response?.request)
  180. // XCTAssertNotNil(response?.response)
  181. // XCTAssertNotNil(response?.data)
  182. // XCTAssertNil(response?.error)
  183. //
  184. // XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  185. // XCTAssertEqual(response?.response?.statusCode, 200)
  186. // }
  187. // func testThatTaskOverrideClosureWithCompletionCanPerformHTTPRedirection() {
  188. // // Given
  189. // let redirectURLString = "https://www.apple.com/"
  190. // let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  191. //
  192. // let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  193. // let callbackExpectation = self.expectation(description: "Redirect callback should be made")
  194. // let delegate: SessionDelegate = manager.delegate
  195. //
  196. // delegate.taskWillPerformHTTPRedirectionWithCompletion = { _, _, _, request, completion in
  197. // completion(request)
  198. // callbackExpectation.fulfill()
  199. // }
  200. //
  201. // var response: DataResponse<Data?>?
  202. //
  203. // // When
  204. // manager.request(urlString)
  205. // .response { resp in
  206. // response = resp
  207. // expectation.fulfill()
  208. // }
  209. //
  210. // waitForExpectations(timeout: timeout, handler: nil)
  211. //
  212. // // Then
  213. // XCTAssertNotNil(response?.request)
  214. // XCTAssertNotNil(response?.response)
  215. // XCTAssertNotNil(response?.data)
  216. // XCTAssertNil(response?.error)
  217. //
  218. // XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  219. // XCTAssertEqual(response?.response?.statusCode, 200)
  220. // }
  221. // func testThatTaskOverrideClosureCanCancelHTTPRedirection() {
  222. // // Given
  223. // let redirectURLString = "https://www.apple.com"
  224. // let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  225. //
  226. // let expectation = self.expectation(description: "Request should not redirect to \(redirectURLString)")
  227. // let callbackExpectation = self.expectation(description: "Redirect callback should be made")
  228. // let delegate: SessionDelegate = manager.delegate
  229. //
  230. // delegate.taskWillPerformHTTPRedirectionWithCompletion = { _, _, _, _, completion in
  231. // callbackExpectation.fulfill()
  232. // completion(nil)
  233. // }
  234. //
  235. // var response: DataResponse<Data?>?
  236. //
  237. // // When
  238. // manager.request(urlString)
  239. // .response { resp in
  240. // response = resp
  241. // expectation.fulfill()
  242. // }
  243. //
  244. // waitForExpectations(timeout: timeout, handler: nil)
  245. //
  246. // // Then
  247. // XCTAssertNotNil(response?.request)
  248. // XCTAssertNotNil(response?.response)
  249. // XCTAssertNotNil(response?.data)
  250. // XCTAssertNil(response?.error)
  251. //
  252. // XCTAssertEqual(response?.response?.url?.absoluteString, urlString)
  253. // XCTAssertEqual(response?.response?.statusCode, 302)
  254. // }
  255. // func testThatTaskOverrideClosureWithCompletionCanCancelHTTPRedirection() {
  256. // // Given
  257. // let redirectURLString = "https://www.apple.com"
  258. // let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  259. //
  260. // let expectation = self.expectation(description: "Request should not redirect to \(redirectURLString)")
  261. // let callbackExpectation = self.expectation(description: "Redirect callback should be made")
  262. // let delegate: SessionDelegate = manager.delegate
  263. //
  264. // delegate.taskWillPerformHTTPRedirection = { _, _, _, _ in
  265. // callbackExpectation.fulfill()
  266. // return nil
  267. // }
  268. //
  269. // var response: DataResponse<Data?>?
  270. //
  271. // // When
  272. // manager.request(urlString)
  273. // .response { resp in
  274. // response = resp
  275. // expectation.fulfill()
  276. // }
  277. //
  278. // waitForExpectations(timeout: timeout, handler: nil)
  279. //
  280. // // Then
  281. // XCTAssertNotNil(response?.request)
  282. // XCTAssertNotNil(response?.response)
  283. // XCTAssertNotNil(response?.data)
  284. // XCTAssertNil(response?.error)
  285. //
  286. // XCTAssertEqual(response?.response?.url?.absoluteString, urlString)
  287. // XCTAssertEqual(response?.response?.statusCode, 302)
  288. // }
  289. // func testThatTaskOverrideClosureIsCalledMultipleTimesForMultipleHTTPRedirects() {
  290. // // Given
  291. // let redirectCount = 5
  292. // let redirectURLString = "https://httpbin.org/get"
  293. // let urlString = "https://httpbin.org/redirect/\(redirectCount)"
  294. //
  295. // let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  296. // let delegate: SessionDelegate = manager.delegate
  297. // var redirectExpectations = [XCTestExpectation]()
  298. // for index in 0..<redirectCount {
  299. // redirectExpectations.insert(self.expectation(description: "Redirect #\(index) callback was received"), at: 0)
  300. // }
  301. //
  302. // delegate.taskWillPerformHTTPRedirection = { _, _, _, request in
  303. // if let redirectExpectation = redirectExpectations.popLast() {
  304. // redirectExpectation.fulfill()
  305. // } else {
  306. // XCTFail("Too many redirect callbacks were received")
  307. // }
  308. //
  309. // return request
  310. // }
  311. //
  312. // var response: DataResponse<Data?>?
  313. //
  314. // // When
  315. // manager.request(urlString)
  316. // .response { resp in
  317. // response = resp
  318. // expectation.fulfill()
  319. // }
  320. //
  321. // waitForExpectations(timeout: timeout, handler: nil)
  322. //
  323. // // Then
  324. // XCTAssertNotNil(response?.request)
  325. // XCTAssertNotNil(response?.response)
  326. // XCTAssertNotNil(response?.data)
  327. // XCTAssertNil(response?.error)
  328. //
  329. // XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  330. // XCTAssertEqual(response?.response?.statusCode, 200)
  331. // }
  332. // func testThatTaskOverrideClosureWithCompletionIsCalledMultipleTimesForMultipleHTTPRedirects() {
  333. // // Given
  334. // let redirectCount = 5
  335. // let redirectURLString = "https://httpbin.org/get"
  336. // let urlString = "https://httpbin.org/redirect/\(redirectCount)"
  337. //
  338. // let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  339. // let delegate: SessionDelegate = manager.delegate
  340. //
  341. // var redirectExpectations = [XCTestExpectation]()
  342. //
  343. // for index in 0..<redirectCount {
  344. // redirectExpectations.insert(self.expectation(description: "Redirect #\(index) callback was received"), at: 0)
  345. // }
  346. //
  347. // delegate.taskWillPerformHTTPRedirectionWithCompletion = { _, _, _, request, completion in
  348. // if let redirectExpectation = redirectExpectations.popLast() {
  349. // redirectExpectation.fulfill()
  350. // } else {
  351. // XCTFail("Too many redirect callbacks were received")
  352. // }
  353. //
  354. // completion(request)
  355. // }
  356. //
  357. // var response: DataResponse<Data?>?
  358. //
  359. // // When
  360. // manager.request(urlString)
  361. // .response { resp in
  362. // response = resp
  363. // expectation.fulfill()
  364. // }
  365. //
  366. // waitForExpectations(timeout: timeout, handler: nil)
  367. //
  368. // // Then
  369. // XCTAssertNotNil(response?.request)
  370. // XCTAssertNotNil(response?.response)
  371. // XCTAssertNotNil(response?.data)
  372. // XCTAssertNil(response?.error)
  373. //
  374. // XCTAssertEqual(response?.response?.url?.absoluteString, redirectURLString)
  375. // XCTAssertEqual(response?.response?.statusCode, 200)
  376. // }
  377. // func testThatRedirectedRequestContainsAllHeadersFromOriginalRequest() {
  378. // // Given
  379. // let redirectURLString = "https://httpbin.org/get"
  380. // let urlString = "https://httpbin.org/redirect-to?url=\(redirectURLString)"
  381. // let headers = [
  382. // "Authorization": "1234",
  383. // "Custom-Header": "foobar",
  384. // ]
  385. //
  386. // // NOTE: It appears that most headers are maintained during a redirect with the exception of the `Authorization`
  387. // // header. It appears that Apple's strips the `Authorization` header from the redirected URL request. If you
  388. // // need to maintain the `Authorization` header, you need to manually append it to the redirected request.
  389. //
  390. // manager.delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
  391. // var redirectedRequest = request
  392. //
  393. // if
  394. // let originalRequest = task.originalRequest,
  395. // let headers = originalRequest.allHTTPHeaderFields,
  396. // let authorizationHeaderValue = headers["Authorization"]
  397. // {
  398. // var mutableRequest = request
  399. // mutableRequest.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
  400. // redirectedRequest = mutableRequest
  401. // }
  402. //
  403. // return redirectedRequest
  404. // }
  405. //
  406. // let expectation = self.expectation(description: "Request should redirect to \(redirectURLString)")
  407. //
  408. // var response: DataResponse<Any>?
  409. //
  410. // // When
  411. // manager.request(urlString, headers: headers)
  412. // .responseJSON { closureResponse in
  413. // response = closureResponse
  414. // expectation.fulfill()
  415. // }
  416. //
  417. // waitForExpectations(timeout: timeout, handler: nil)
  418. //
  419. // // Then
  420. // XCTAssertNotNil(response?.request)
  421. // XCTAssertNotNil(response?.response)
  422. // XCTAssertNotNil(response?.data)
  423. // XCTAssertEqual(response?.result.isSuccess, true)
  424. //
  425. // if let json = response?.result.value as? [String: Any], let headers = json["headers"] as? [String: String] {
  426. // XCTAssertEqual(headers["Authorization"], "1234")
  427. // XCTAssertEqual(headers["Custom-Header"], "foobar")
  428. // }
  429. // }
  430. // MARK: - Tests - Data Task Responses
  431. // func testThatDataTaskDidReceiveResponseClosureIsCalledWhenSet() {
  432. // // Given
  433. // let expectation = self.expectation(description: "Override closure should be called")
  434. //
  435. // var overrideClosureCalled = false
  436. // var response: HTTPURLResponse?
  437. //
  438. // manager.delegate.dataTaskDidReceiveResponse = { session, task, response in
  439. // overrideClosureCalled = true
  440. // return .allow
  441. // }
  442. //
  443. // // When
  444. // manager.request("https://httpbin.org/get").responseJSON { closureResponse in
  445. // response = closureResponse.response
  446. // expectation.fulfill()
  447. // }
  448. //
  449. // waitForExpectations(timeout: timeout, handler: nil)
  450. //
  451. // // Then
  452. // XCTAssertTrue(overrideClosureCalled)
  453. // XCTAssertEqual(response?.statusCode, 200)
  454. // }
  455. // func testThatDataTaskDidReceiveResponseWithCompletionClosureIsCalledWhenSet() {
  456. // // Given
  457. // let expectation = self.expectation(description: "Override closure should be called")
  458. //
  459. // var overrideClosureCalled = false
  460. // var response: HTTPURLResponse?
  461. //
  462. // manager.delegate.dataTaskDidReceiveResponseWithCompletion = { session, task, response, completion in
  463. // overrideClosureCalled = true
  464. // completion(.allow)
  465. // }
  466. //
  467. // // When
  468. // manager.request("https://httpbin.org/get").responseJSON { closureResponse in
  469. // response = closureResponse.response
  470. // expectation.fulfill()
  471. // }
  472. //
  473. // waitForExpectations(timeout: timeout, handler: nil)
  474. //
  475. // // Then
  476. // XCTAssertTrue(overrideClosureCalled)
  477. // XCTAssertEqual(response?.statusCode, 200)
  478. // }
  479. // func testThatDidCompleteNotificationIsCalledWithResponseDataForDataTasks() {
  480. // // Given
  481. // var notificationCalledWithResponseData = false
  482. // var response: HTTPURLResponse?
  483. //
  484. // let expectation = self.expectation(forNotification: Notification.Name.Task.DidComplete, object: nil) { notif -> Bool in
  485. //
  486. // // check that we are handling notif for a dataTask
  487. // guard let task = notif.userInfo?[Notification.Key.Task] as? URLSessionDataTask else {
  488. // return false
  489. // }
  490. //
  491. // response = task.response as? HTTPURLResponse
  492. //
  493. // // check that responseData are set in userInfo-dict and it's not empty
  494. // if let responseData = notif.userInfo?[Notification.Key.ResponseData] as? Data {
  495. // notificationCalledWithResponseData = responseData.count > 0
  496. // }
  497. //
  498. // return notificationCalledWithResponseData
  499. // }
  500. //
  501. // // When
  502. // manager.request("https://httpbin.org/get").responseJSON { resp in }
  503. //
  504. // wait(for: [expectation], timeout: timeout)
  505. //
  506. // // Then
  507. // XCTAssertTrue(notificationCalledWithResponseData)
  508. // XCTAssertEqual(response?.statusCode, 200)
  509. // }
  510. // func testThatDidCompleteNotificationIsntCalledForDownloadTasks() {
  511. // // Given
  512. // var notificationCalledWithNilResponseData = false
  513. // var response: HTTPURLResponse?
  514. // let notification = Notification.Name.Task.DidComplete
  515. // let expectation = self.expectation(forNotification: notification, object: nil) { notif -> Bool in
  516. //
  517. // // check that we are handling notif for a downloadTask
  518. // guard let task = notif.userInfo?[Notification.Key.Task] as? URLSessionDownloadTask else {
  519. // return false
  520. // }
  521. //
  522. // response = task.response as? HTTPURLResponse
  523. //
  524. // // check that responseData are NOT set in userInfo-dict
  525. // notificationCalledWithNilResponseData = notif.userInfo?[Notification.Key.ResponseData] == nil
  526. // return notificationCalledWithNilResponseData
  527. // }
  528. //
  529. // // When
  530. // manager.download("https://httpbin.org/get").response { resp in }
  531. //
  532. // wait(for: [expectation], timeout: timeout)
  533. //
  534. // // Then
  535. // XCTAssertTrue(notificationCalledWithNilResponseData)
  536. // XCTAssertEqual(response?.statusCode, 200)
  537. // }
  538. }