DownloadTests.swift 30 KB

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