DownloadTests.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. //
  2. // DownloadTests.swift
  3. //
  4. // Copyright (c) 2014 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. import Alamofire
  25. import Foundation
  26. import XCTest
  27. class DownloadInitializationTestCase: BaseTestCase {
  28. func testDownloadClassMethodWithMethodURLAndDestination() {
  29. // Given
  30. let urlString = "https://httpbin.org/"
  31. // When
  32. let request = Alamofire.download(urlString)
  33. // Then
  34. XCTAssertNotNil(request.request)
  35. XCTAssertEqual(request.request?.httpMethod, "GET")
  36. XCTAssertEqual(request.request?.url?.absoluteString, urlString)
  37. XCTAssertNil(request.response)
  38. }
  39. func testDownloadClassMethodWithMethodURLHeadersAndDestination() {
  40. // Given
  41. let urlString = "https://httpbin.org/"
  42. let headers = ["Authorization": "123456"]
  43. // When
  44. let request = Alamofire.download(urlString, headers: headers)
  45. // Then
  46. XCTAssertNotNil(request.request)
  47. XCTAssertEqual(request.request?.httpMethod, "GET")
  48. XCTAssertEqual(request.request?.url?.absoluteString, urlString)
  49. XCTAssertEqual(request.request?.value(forHTTPHeaderField: "Authorization"), "123456")
  50. XCTAssertNil(request.response)
  51. }
  52. }
  53. // MARK: -
  54. class DownloadResponseTestCase: BaseTestCase {
  55. private var randomCachesFileURL: URL {
  56. return testDirectoryURL.appendingPathComponent("\(UUID().uuidString).json")
  57. }
  58. func testDownloadRequest() {
  59. // Given
  60. let fileURL = randomCachesFileURL
  61. let numberOfLines = 100
  62. let urlString = "https://httpbin.org/stream/\(numberOfLines)"
  63. let destination: DownloadRequest.DownloadFileDestination = { _, _ in (fileURL, []) }
  64. let expectation = self.expectation(description: "Download request should download data to file: \(urlString)")
  65. var response: DefaultDownloadResponse?
  66. // When
  67. Alamofire.download(urlString, to: destination)
  68. .response { resp in
  69. response = resp
  70. expectation.fulfill()
  71. }
  72. waitForExpectations(timeout: timeout, handler: nil)
  73. // Then
  74. XCTAssertNotNil(response?.request)
  75. XCTAssertNotNil(response?.response)
  76. XCTAssertNotNil(response?.destinationURL)
  77. XCTAssertNil(response?.resumeData)
  78. XCTAssertNil(response?.error)
  79. if let destinationURL = response?.destinationURL {
  80. XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
  81. if let data = try? Data(contentsOf: destinationURL) {
  82. XCTAssertGreaterThan(data.count, 0)
  83. } else {
  84. XCTFail("data should exist for contents of destinationURL")
  85. }
  86. }
  87. }
  88. func testCancelledDownloadRequest() {
  89. // Given
  90. let fileURL = randomCachesFileURL
  91. let numberOfLines = 100
  92. let urlString = "https://httpbin.org/stream/\(numberOfLines)"
  93. let destination: DownloadRequest.DownloadFileDestination = { _, _ in (fileURL, []) }
  94. let expectation = self.expectation(description: "Cancelled download request should not download data to file")
  95. var response: DefaultDownloadResponse?
  96. // When
  97. Alamofire.download(urlString, to: destination)
  98. .response { resp in
  99. response = resp
  100. expectation.fulfill()
  101. }
  102. .cancel()
  103. waitForExpectations(timeout: timeout, handler: nil)
  104. // Then
  105. XCTAssertNotNil(response?.request)
  106. XCTAssertNil(response?.response)
  107. XCTAssertNil(response?.destinationURL)
  108. XCTAssertNotNil(response?.error)
  109. }
  110. func testDownloadRequestWithProgress() {
  111. // Given
  112. let randomBytes = 4 * 1024 * 1024
  113. let urlString = "https://httpbin.org/bytes/\(randomBytes)"
  114. let expectation = self.expectation(description: "Bytes download progress should be reported: \(urlString)")
  115. var progressValues: [Double] = []
  116. var response: DefaultDownloadResponse?
  117. // When
  118. Alamofire.download(urlString)
  119. .downloadProgress { progress in
  120. progressValues.append(progress.fractionCompleted)
  121. }
  122. .response { resp in
  123. response = resp
  124. expectation.fulfill()
  125. }
  126. waitForExpectations(timeout: timeout, handler: nil)
  127. // Then
  128. XCTAssertNotNil(response?.request)
  129. XCTAssertNotNil(response?.response)
  130. XCTAssertNotNil(response?.temporaryURL)
  131. XCTAssertNil(response?.destinationURL)
  132. XCTAssertNil(response?.resumeData)
  133. XCTAssertNil(response?.error)
  134. var previousProgress: Double = progressValues.first ?? 0.0
  135. for progress in progressValues {
  136. XCTAssertGreaterThanOrEqual(progress, previousProgress)
  137. previousProgress = progress
  138. }
  139. if let lastProgressValue = progressValues.last {
  140. XCTAssertEqual(lastProgressValue, 1.0)
  141. } else {
  142. XCTFail("last item in progressValues should not be nil")
  143. }
  144. }
  145. func testDownloadRequestWithParameters() {
  146. // Given
  147. let urlString = "https://httpbin.org/get"
  148. let parameters = ["foo": "bar"]
  149. let expectation = self.expectation(description: "Download request should download data to file")
  150. var response: DefaultDownloadResponse?
  151. // When
  152. Alamofire.download(urlString, parameters: parameters)
  153. .response { resp in
  154. response = resp
  155. expectation.fulfill()
  156. }
  157. waitForExpectations(timeout: timeout, handler: nil)
  158. // Then
  159. XCTAssertNotNil(response?.request)
  160. XCTAssertNotNil(response?.response)
  161. XCTAssertNotNil(response?.temporaryURL)
  162. XCTAssertNil(response?.destinationURL)
  163. XCTAssertNil(response?.resumeData)
  164. XCTAssertNil(response?.error)
  165. if
  166. let temporaryURL = response?.temporaryURL,
  167. let data = try? Data(contentsOf: temporaryURL),
  168. let jsonObject = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: 0)),
  169. let json = jsonObject as? [String: Any],
  170. let args = json["args"] as? [String: String]
  171. {
  172. XCTAssertEqual(args["foo"], "bar")
  173. } else {
  174. XCTFail("args parameter in JSON should not be nil")
  175. }
  176. }
  177. func testDownloadRequestWithHeaders() {
  178. // Given
  179. let fileURL = randomCachesFileURL
  180. let urlString = "https://httpbin.org/get"
  181. let headers = ["Authorization": "123456"]
  182. let destination: DownloadRequest.DownloadFileDestination = { _, _ in (fileURL, []) }
  183. let expectation = self.expectation(description: "Download request should download data to file: \(fileURL)")
  184. var response: DefaultDownloadResponse?
  185. // When
  186. Alamofire.download(urlString, headers: headers, to: destination)
  187. .response { resp in
  188. response = resp
  189. expectation.fulfill()
  190. }
  191. waitForExpectations(timeout: timeout, handler: nil)
  192. // Then
  193. XCTAssertNotNil(response?.request)
  194. XCTAssertNotNil(response?.response)
  195. XCTAssertNotNil(response?.destinationURL)
  196. XCTAssertNil(response?.resumeData)
  197. XCTAssertNil(response?.error)
  198. if
  199. let data = try? Data(contentsOf: fileURL),
  200. let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
  201. let json = jsonObject as? [String: Any],
  202. let headers = json["headers"] as? [String: String]
  203. {
  204. XCTAssertEqual(headers["Authorization"], "123456")
  205. } else {
  206. XCTFail("headers parameter in JSON should not be nil")
  207. }
  208. }
  209. func testThatDownloadingFileAndMovingToDirectoryThatDoesNotExistThrowsError() {
  210. // Given
  211. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  212. let expectation = self.expectation(description: "Download request should download data but fail to move file")
  213. var response: DefaultDownloadResponse?
  214. // When
  215. Alamofire.download("https://httpbin.org/get", to: { _, _ in (fileURL, [])})
  216. .response { resp in
  217. response = resp
  218. expectation.fulfill()
  219. }
  220. waitForExpectations(timeout: timeout, handler: nil)
  221. // Then
  222. XCTAssertNotNil(response?.request)
  223. XCTAssertNotNil(response?.response)
  224. XCTAssertNotNil(response?.temporaryURL)
  225. XCTAssertNotNil(response?.destinationURL)
  226. XCTAssertNil(response?.resumeData)
  227. XCTAssertNotNil(response?.error)
  228. if let error = response?.error as? CocoaError {
  229. XCTAssertEqual(error.code, .fileNoSuchFile)
  230. } else {
  231. XCTFail("error should not be nil")
  232. }
  233. }
  234. func testThatDownloadOptionsCanCreateIntermediateDirectoriesPriorToMovingFile() {
  235. // Given
  236. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  237. let expectation = self.expectation(description: "Download request should download data to file: \(fileURL)")
  238. var response: DefaultDownloadResponse?
  239. // When
  240. Alamofire.download("https://httpbin.org/get", to: { _, _ in (fileURL, [.createIntermediateDirectories])})
  241. .response { resp in
  242. response = resp
  243. expectation.fulfill()
  244. }
  245. waitForExpectations(timeout: timeout, handler: nil)
  246. // Then
  247. XCTAssertNotNil(response?.request)
  248. XCTAssertNotNil(response?.response)
  249. XCTAssertNotNil(response?.temporaryURL)
  250. XCTAssertNotNil(response?.destinationURL)
  251. XCTAssertNil(response?.resumeData)
  252. XCTAssertNil(response?.error)
  253. }
  254. func testThatDownloadingFileAndMovingToDestinationThatIsOccupiedThrowsError() {
  255. do {
  256. // Given
  257. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  258. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  259. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  260. try "random_data".write(to: fileURL, atomically: true, encoding: .utf8)
  261. let expectation = self.expectation(description: "Download should complete but fail to move file")
  262. var response: DefaultDownloadResponse?
  263. // When
  264. Alamofire.download("https://httpbin.org/get", to: { _, _ in (fileURL, [])})
  265. .response { resp in
  266. response = resp
  267. expectation.fulfill()
  268. }
  269. waitForExpectations(timeout: timeout, handler: nil)
  270. // Then
  271. XCTAssertTrue(directoryCreated)
  272. XCTAssertNotNil(response?.request)
  273. XCTAssertNotNil(response?.response)
  274. XCTAssertNotNil(response?.temporaryURL)
  275. XCTAssertNotNil(response?.destinationURL)
  276. XCTAssertNil(response?.resumeData)
  277. XCTAssertNotNil(response?.error)
  278. if let error = response?.error as? CocoaError {
  279. XCTAssertEqual(error.code, .fileWriteFileExists)
  280. } else {
  281. XCTFail("error should not be nil")
  282. }
  283. } catch {
  284. XCTFail("Test encountered unexpected error: \(error)")
  285. }
  286. }
  287. func testThatDownloadOptionsCanRemovePreviousFilePriorToMovingFile() {
  288. // Given
  289. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  290. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  291. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  292. let expectation = self.expectation(description: "Download should complete and move file to URL: \(fileURL)")
  293. var response: DefaultDownloadResponse?
  294. // When
  295. Alamofire.download("https://httpbin.org/get", to: { _, _ in (fileURL, [.removePreviousFile])})
  296. .response { resp in
  297. response = resp
  298. expectation.fulfill()
  299. }
  300. waitForExpectations(timeout: timeout, handler: nil)
  301. // Then
  302. XCTAssertTrue(directoryCreated)
  303. XCTAssertNotNil(response?.request)
  304. XCTAssertNotNil(response?.response)
  305. XCTAssertNotNil(response?.temporaryURL)
  306. XCTAssertNotNil(response?.destinationURL)
  307. XCTAssertNil(response?.resumeData)
  308. XCTAssertNil(response?.error)
  309. }
  310. }
  311. // MARK: -
  312. class DownloadResumeDataTestCase: BaseTestCase {
  313. let urlString = "https://upload.wikimedia.org/wikipedia/commons/6/69/NASA-HS201427a-HubbleUltraDeepField2014-20140603.jpg"
  314. func testThatCancelledDownloadResponseDataMatchesResumeData() {
  315. // Given
  316. let expectation = self.expectation(description: "Download should be cancelled")
  317. var cancelled = false
  318. var response: DefaultDownloadResponse?
  319. // When
  320. let download = Alamofire.download(urlString)
  321. download.downloadProgress { progress in
  322. guard !cancelled else { return }
  323. if progress.fractionCompleted > 0.1 {
  324. download.cancel()
  325. cancelled = true
  326. }
  327. }
  328. download.response { resp in
  329. response = resp
  330. expectation.fulfill()
  331. }
  332. waitForExpectations(timeout: timeout, handler: nil)
  333. // Then
  334. XCTAssertNotNil(response?.request)
  335. XCTAssertNotNil(response?.response)
  336. XCTAssertNil(response?.destinationURL)
  337. XCTAssertNotNil(response?.error)
  338. XCTAssertNotNil(response?.resumeData)
  339. XCTAssertNotNil(download.resumeData)
  340. XCTAssertEqual(response?.resumeData, download.resumeData)
  341. }
  342. func testThatCancelledDownloadResumeDataIsAvailableWithJSONResponseSerializer() {
  343. // Given
  344. let expectation = self.expectation(description: "Download should be cancelled")
  345. var cancelled = false
  346. var response: DownloadResponse<Any>?
  347. // When
  348. let download = Alamofire.download(urlString)
  349. download.downloadProgress { progress in
  350. guard !cancelled else { return }
  351. if progress.fractionCompleted > 0.1 {
  352. download.cancel()
  353. cancelled = true
  354. }
  355. }
  356. download.responseJSON { resp in
  357. response = resp
  358. expectation.fulfill()
  359. }
  360. waitForExpectations(timeout: timeout, handler: nil)
  361. // Then
  362. XCTAssertNotNil(response?.request)
  363. XCTAssertNotNil(response?.response)
  364. XCTAssertNil(response?.destinationURL)
  365. XCTAssertEqual(response?.result.isFailure, true)
  366. XCTAssertNotNil(response?.result.error)
  367. XCTAssertNotNil(response?.resumeData)
  368. XCTAssertNotNil(download.resumeData)
  369. XCTAssertEqual(response?.resumeData, download.resumeData)
  370. }
  371. func testThatCancelledDownloadCanBeResumedWithResumeData() {
  372. // Given
  373. let expectation1 = self.expectation(description: "Download should be cancelled")
  374. var cancelled = false
  375. var response1: DownloadResponse<Data>?
  376. // When
  377. let download = Alamofire.download(urlString)
  378. download.downloadProgress { progress in
  379. guard !cancelled else { return }
  380. if progress.fractionCompleted > 0.4 {
  381. download.cancel()
  382. cancelled = true
  383. }
  384. }
  385. download.responseData { resp in
  386. response1 = resp
  387. expectation1.fulfill()
  388. }
  389. waitForExpectations(timeout: timeout, handler: nil)
  390. guard let resumeData = download.resumeData else {
  391. XCTFail("resumeData should not be nil")
  392. return
  393. }
  394. let expectation2 = self.expectation(description: "Download should complete")
  395. var progressValues: [Double] = []
  396. var response2: DownloadResponse<Data>?
  397. Alamofire.download(resumingWith: resumeData)
  398. .downloadProgress { progress in
  399. progressValues.append(progress.fractionCompleted)
  400. }
  401. .responseData { resp in
  402. response2 = resp
  403. expectation2.fulfill()
  404. }
  405. waitForExpectations(timeout: timeout, handler: nil)
  406. // Then
  407. XCTAssertNotNil(response1?.request)
  408. XCTAssertNotNil(response1?.response)
  409. XCTAssertNil(response1?.destinationURL)
  410. XCTAssertEqual(response1?.result.isFailure, true)
  411. XCTAssertNotNil(response1?.result.error)
  412. XCTAssertNotNil(response2?.response)
  413. XCTAssertNotNil(response2?.temporaryURL)
  414. XCTAssertNil(response2?.destinationURL)
  415. XCTAssertEqual(response2?.result.isSuccess, true)
  416. XCTAssertNil(response2?.result.error)
  417. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.4) }
  418. }
  419. func testThatDownloadCanBeCancelledWithoutResumeData() {
  420. // Given
  421. let expectation = self.expectation(description: "Download should be cancelled")
  422. var cancelled = false
  423. var response: DefaultDownloadResponse?
  424. // When
  425. let download = Alamofire.download(urlString)
  426. download.downloadProgress { progress in
  427. guard !cancelled else { return }
  428. if progress.fractionCompleted > 0.1 {
  429. download.cancel(createResumeData: false)
  430. cancelled = true
  431. }
  432. }
  433. download.response { resp in
  434. response = resp
  435. expectation.fulfill()
  436. }
  437. waitForExpectations(timeout: timeout, handler: nil)
  438. // Then
  439. XCTAssertNotNil(response?.request)
  440. XCTAssertNotNil(response?.response)
  441. XCTAssertNil(response?.destinationURL)
  442. XCTAssertNotNil(response?.error)
  443. XCTAssertNil(response?.resumeData)
  444. XCTAssertNil(download.resumeData)
  445. }
  446. }
  447. // MARK: -
  448. class DownloadResponseMapTestCase: BaseTestCase {
  449. func testThatMapTransformsSuccessValue() {
  450. // Given
  451. let urlString = "https://httpbin.org/get"
  452. let expectation = self.expectation(description: "request should succeed")
  453. var response: DownloadResponse<String>?
  454. // When
  455. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  456. response = resp.map { json in
  457. // json["args"]["foo"] is "bar": use this invariant to test the map function
  458. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  459. }
  460. expectation.fulfill()
  461. }
  462. waitForExpectations(timeout: timeout, handler: nil)
  463. // Then
  464. XCTAssertNotNil(response?.request)
  465. XCTAssertNotNil(response?.response)
  466. XCTAssertNotNil(response?.temporaryURL)
  467. XCTAssertNil(response?.destinationURL)
  468. XCTAssertNil(response?.resumeData)
  469. XCTAssertNil(response?.error)
  470. XCTAssertEqual(response?.result.value, "bar")
  471. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  472. XCTAssertNotNil(response?.metrics)
  473. }
  474. }
  475. func testThatMapPreservesFailureError() {
  476. // Given
  477. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  478. let expectation = self.expectation(description: "request should fail with 404")
  479. var response: DownloadResponse<String>?
  480. // When
  481. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  482. response = resp.map { _ in "ignored" }
  483. expectation.fulfill()
  484. }
  485. waitForExpectations(timeout: timeout, handler: nil)
  486. // Then
  487. XCTAssertNotNil(response?.request)
  488. XCTAssertNil(response?.response)
  489. XCTAssertNil(response?.temporaryURL)
  490. XCTAssertNil(response?.destinationURL)
  491. XCTAssertNil(response?.resumeData)
  492. XCTAssertNotNil(response?.error)
  493. XCTAssertEqual(response?.result.isFailure, true)
  494. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  495. XCTAssertNotNil(response?.metrics)
  496. }
  497. }
  498. }
  499. // MARK: -
  500. class DownloadResponseFlatMapTestCase: BaseTestCase {
  501. func testThatFlatMapTransformsSuccessValue() {
  502. // Given
  503. let urlString = "https://httpbin.org/get"
  504. let expectation = self.expectation(description: "request should succeed")
  505. var response: DownloadResponse<String>?
  506. // When
  507. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  508. response = resp.flatMap { json in
  509. // json["args"]["foo"] is "bar": use this invariant to test the map function
  510. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  511. }
  512. expectation.fulfill()
  513. }
  514. waitForExpectations(timeout: timeout, handler: nil)
  515. // Then
  516. XCTAssertNotNil(response?.request)
  517. XCTAssertNotNil(response?.response)
  518. XCTAssertNotNil(response?.temporaryURL)
  519. XCTAssertNil(response?.destinationURL)
  520. XCTAssertNil(response?.resumeData)
  521. XCTAssertNil(response?.error)
  522. XCTAssertEqual(response?.result.value, "bar")
  523. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  524. XCTAssertNotNil(response?.metrics)
  525. }
  526. }
  527. func testThatFlatMapCatchesTransformationError() {
  528. // Given
  529. struct TransformError: Error {}
  530. let urlString = "https://httpbin.org/get"
  531. let expectation = self.expectation(description: "request should succeed")
  532. var response: DownloadResponse<String>?
  533. // When
  534. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  535. response = resp.flatMap { json in
  536. throw TransformError()
  537. }
  538. expectation.fulfill()
  539. }
  540. waitForExpectations(timeout: timeout, handler: nil)
  541. // Then
  542. XCTAssertNotNil(response?.request)
  543. XCTAssertNotNil(response?.response)
  544. XCTAssertNotNil(response?.temporaryURL)
  545. XCTAssertNil(response?.destinationURL)
  546. XCTAssertNil(response?.resumeData)
  547. if let error = response?.result.error {
  548. XCTAssertTrue(error is TransformError)
  549. } else {
  550. XCTFail("flatMap should catch the transformation error")
  551. }
  552. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  553. XCTAssertNotNil(response?.metrics)
  554. }
  555. }
  556. func testThatFlatMapPreservesFailureError() {
  557. // Given
  558. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  559. let expectation = self.expectation(description: "request should fail with 404")
  560. var response: DownloadResponse<String>?
  561. // When
  562. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  563. response = resp.flatMap { _ in "ignored" }
  564. expectation.fulfill()
  565. }
  566. waitForExpectations(timeout: timeout, handler: nil)
  567. // Then
  568. XCTAssertNotNil(response?.request)
  569. XCTAssertNil(response?.response)
  570. XCTAssertNil(response?.temporaryURL)
  571. XCTAssertNil(response?.destinationURL)
  572. XCTAssertNil(response?.resumeData)
  573. XCTAssertNotNil(response?.error)
  574. XCTAssertEqual(response?.result.isFailure, true)
  575. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  576. XCTAssertNotNil(response?.metrics)
  577. }
  578. }
  579. }
  580. class DownloadResponseMapErrorTestCase: BaseTestCase {
  581. func testThatMapErrorTransformsFailureValue() {
  582. // Given
  583. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  584. let expectation = self.expectation(description: "request should not succeed")
  585. var response: DownloadResponse<Any>?
  586. // When
  587. Alamofire.download(urlString).responseJSON { resp in
  588. response = resp.mapError { error in
  589. return TestError.error(error: error)
  590. }
  591. expectation.fulfill()
  592. }
  593. waitForExpectations(timeout: timeout, handler: nil)
  594. // Then
  595. XCTAssertNotNil(response?.request)
  596. XCTAssertNil(response?.response)
  597. XCTAssertNil(response?.temporaryURL)
  598. XCTAssertNil(response?.destinationURL)
  599. XCTAssertNil(response?.resumeData)
  600. XCTAssertNotNil(response?.error)
  601. XCTAssertEqual(response?.result.isFailure, true)
  602. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  603. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  604. XCTAssertNotNil(response?.metrics)
  605. }
  606. }
  607. func testThatMapErrorPreservesSuccessValue() {
  608. // Given
  609. let urlString = "https://httpbin.org/get"
  610. let expectation = self.expectation(description: "request should succeed")
  611. var response: DownloadResponse<Data>?
  612. // When
  613. Alamofire.download(urlString).responseData { resp in
  614. response = resp.mapError { TestError.error(error: $0) }
  615. expectation.fulfill()
  616. }
  617. waitForExpectations(timeout: timeout, handler: nil)
  618. // Then
  619. XCTAssertNotNil(response?.request)
  620. XCTAssertNotNil(response?.response)
  621. XCTAssertNotNil(response?.temporaryURL)
  622. XCTAssertNil(response?.destinationURL)
  623. XCTAssertNil(response?.resumeData)
  624. XCTAssertEqual(response?.result.isSuccess, true)
  625. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  626. XCTAssertNotNil(response?.metrics)
  627. }
  628. }
  629. }
  630. // MARK: -
  631. class DownloadResponseFlatMapErrorTestCase: BaseTestCase {
  632. func testThatFlatMapErrorPreservesSuccessValue() {
  633. // Given
  634. let urlString = "https://httpbin.org/get"
  635. let expectation = self.expectation(description: "request should succeed")
  636. var response: DownloadResponse<Data>?
  637. // When
  638. Alamofire.download(urlString).responseData { resp in
  639. response = resp.flatMapError { TestError.error(error: $0) }
  640. expectation.fulfill()
  641. }
  642. waitForExpectations(timeout: timeout, handler: nil)
  643. // Then
  644. XCTAssertNotNil(response?.request)
  645. XCTAssertNotNil(response?.response)
  646. XCTAssertNotNil(response?.temporaryURL)
  647. XCTAssertNil(response?.destinationURL)
  648. XCTAssertNil(response?.resumeData)
  649. XCTAssertNil(response?.error)
  650. XCTAssertEqual(response?.result.isSuccess, true)
  651. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  652. XCTAssertNotNil(response?.metrics)
  653. }
  654. }
  655. func testThatFlatMapErrorCatchesTransformationError() {
  656. // Given
  657. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  658. let expectation = self.expectation(description: "request should fail")
  659. var response: DownloadResponse<Data>?
  660. // When
  661. Alamofire.download(urlString).responseData { resp in
  662. response = resp.flatMapError { _ in try TransformationError.error.alwaysFails() }
  663. expectation.fulfill()
  664. }
  665. waitForExpectations(timeout: timeout, handler: nil)
  666. // Then
  667. XCTAssertNotNil(response?.request)
  668. XCTAssertNil(response?.response)
  669. XCTAssertNil(response?.temporaryURL)
  670. XCTAssertNil(response?.destinationURL)
  671. XCTAssertNil(response?.resumeData)
  672. XCTAssertNotNil(response?.error)
  673. XCTAssertEqual(response?.result.isFailure, true)
  674. if let error = response?.result.error {
  675. XCTAssertTrue(error is TransformationError)
  676. } else {
  677. XCTFail("flatMapError should catch the transformation error")
  678. }
  679. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  680. XCTAssertNotNil(response?.metrics)
  681. }
  682. }
  683. func testThatFlatMapErrorTransformsError() {
  684. // Given
  685. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  686. let expectation = self.expectation(description: "request should fail")
  687. var response: DownloadResponse<Data>?
  688. // When
  689. Alamofire.download(urlString).responseData { resp in
  690. response = resp.flatMapError { TestError.error(error: $0) }
  691. expectation.fulfill()
  692. }
  693. waitForExpectations(timeout: timeout, handler: nil)
  694. // Then
  695. XCTAssertNotNil(response?.request)
  696. XCTAssertNil(response?.response)
  697. XCTAssertNil(response?.temporaryURL)
  698. XCTAssertNil(response?.destinationURL)
  699. XCTAssertNil(response?.resumeData)
  700. XCTAssertNotNil(response?.error)
  701. XCTAssertEqual(response?.result.isFailure, true)
  702. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  703. if #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) {
  704. XCTAssertNotNil(response?.metrics)
  705. }
  706. }
  707. }