DownloadTests.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  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. let destination = DownloadRequest.suggestedDownloadDestination(options: [.removePreviousFile, .createIntermediateDirectories])
  431. // TODO: Added destination because temp file was being deleted very quickly.
  432. Alamofire.download(resumingWith: resumeData,
  433. to: destination)
  434. .downloadProgress { progress in
  435. progressValues.append(progress.fractionCompleted)
  436. }
  437. .responseData { resp in
  438. response2 = resp
  439. expectation2.fulfill()
  440. }
  441. waitForExpectations(timeout: timeout, handler: nil)
  442. // Then
  443. XCTAssertNotNil(response1?.request)
  444. XCTAssertNotNil(response1?.response)
  445. XCTAssertNil(response1?.destinationURL)
  446. XCTAssertEqual(response1?.result.isFailure, true)
  447. XCTAssertNotNil(response1?.result.error)
  448. XCTAssertNotNil(response2?.response)
  449. XCTAssertNotNil(response2?.temporaryURL)
  450. XCTAssertNotNil(response2?.destinationURL)
  451. XCTAssertEqual(response2?.result.isSuccess, true)
  452. XCTAssertNil(response2?.result.error)
  453. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.4) }
  454. }
  455. }
  456. // MARK: -
  457. class DownloadResponseMapTestCase: BaseTestCase {
  458. // func testThatMapTransformsSuccessValue() {
  459. // // Given
  460. // let urlString = "https://httpbin.org/get"
  461. // let expectation = self.expectation(description: "request should succeed")
  462. //
  463. // var response: DownloadResponse<String>?
  464. //
  465. // // When
  466. // Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  467. // response = resp.map { json in
  468. // // json["args"]["foo"] is "bar": use this invariant to test the map function
  469. // return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  470. // }
  471. //
  472. // expectation.fulfill()
  473. // }
  474. //
  475. // waitForExpectations(timeout: timeout, handler: nil)
  476. //
  477. // // Then
  478. // XCTAssertNotNil(response?.request)
  479. // XCTAssertNotNil(response?.response)
  480. // XCTAssertNotNil(response?.temporaryURL)
  481. // XCTAssertNil(response?.destinationURL)
  482. // XCTAssertNil(response?.resumeData)
  483. // XCTAssertNil(response?.error)
  484. // XCTAssertEqual(response?.result.value, "bar")
  485. // XCTAssertNotNil(response?.metrics)
  486. // }
  487. func testThatMapPreservesFailureError() {
  488. // Given
  489. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  490. let expectation = self.expectation(description: "request should fail with 404")
  491. var response: DownloadResponse<String>?
  492. // When
  493. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  494. response = resp.map { _ in "ignored" }
  495. expectation.fulfill()
  496. }
  497. waitForExpectations(timeout: timeout, handler: nil)
  498. // Then
  499. XCTAssertNotNil(response?.request)
  500. XCTAssertNil(response?.response)
  501. XCTAssertNil(response?.temporaryURL)
  502. XCTAssertNil(response?.destinationURL)
  503. XCTAssertNil(response?.resumeData)
  504. XCTAssertNotNil(response?.error)
  505. XCTAssertEqual(response?.result.isFailure, true)
  506. XCTAssertNotNil(response?.metrics)
  507. }
  508. }
  509. // MARK: -
  510. class DownloadResponseFlatMapTestCase: BaseTestCase {
  511. // func testThatFlatMapTransformsSuccessValue() {
  512. // // Given
  513. // let urlString = "https://httpbin.org/get"
  514. // let expectation = self.expectation(description: "request should succeed")
  515. //
  516. // var response: DownloadResponse<String>?
  517. //
  518. // // When
  519. // Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  520. // response = resp.flatMap { json in
  521. // // json["args"]["foo"] is "bar": use this invariant to test the map function
  522. // return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  523. // }
  524. //
  525. // expectation.fulfill()
  526. // }
  527. //
  528. // waitForExpectations(timeout: timeout, handler: nil)
  529. //
  530. // // Then
  531. // XCTAssertNotNil(response?.request)
  532. // XCTAssertNotNil(response?.response)
  533. // XCTAssertNotNil(response?.temporaryURL)
  534. // XCTAssertNil(response?.destinationURL)
  535. // XCTAssertNil(response?.resumeData)
  536. // XCTAssertNil(response?.error)
  537. // XCTAssertEqual(response?.result.value, "bar")
  538. // XCTAssertNotNil(response?.metrics)
  539. // }
  540. //
  541. // func testThatFlatMapCatchesTransformationError() {
  542. // // Given
  543. // struct TransformError: Error {}
  544. //
  545. // let urlString = "https://httpbin.org/get"
  546. // let expectation = self.expectation(description: "request should succeed")
  547. //
  548. // var response: DownloadResponse<String>?
  549. //
  550. // // When
  551. // Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  552. // response = resp.flatMap { json in
  553. // throw TransformError()
  554. // }
  555. //
  556. // expectation.fulfill()
  557. // }
  558. //
  559. // waitForExpectations(timeout: timeout, handler: nil)
  560. //
  561. // // Then
  562. // XCTAssertNotNil(response?.request)
  563. // XCTAssertNotNil(response?.response)
  564. // XCTAssertNotNil(response?.temporaryURL)
  565. // XCTAssertNil(response?.destinationURL)
  566. // XCTAssertNil(response?.resumeData)
  567. // if let error = response?.result.error {
  568. // XCTAssertTrue(error is TransformError)
  569. // } else {
  570. // XCTFail("flatMap should catch the transformation error")
  571. // }
  572. //
  573. // XCTAssertNotNil(response?.metrics)
  574. // }
  575. func testThatFlatMapPreservesFailureError() {
  576. // Given
  577. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  578. let expectation = self.expectation(description: "request should fail with 404")
  579. var response: DownloadResponse<String>?
  580. // When
  581. Alamofire.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  582. response = resp.flatMap { _ in "ignored" }
  583. expectation.fulfill()
  584. }
  585. waitForExpectations(timeout: timeout, handler: nil)
  586. // Then
  587. XCTAssertNotNil(response?.request)
  588. XCTAssertNil(response?.response)
  589. XCTAssertNil(response?.temporaryURL)
  590. XCTAssertNil(response?.destinationURL)
  591. XCTAssertNil(response?.resumeData)
  592. XCTAssertNotNil(response?.error)
  593. XCTAssertEqual(response?.result.isFailure, true)
  594. XCTAssertNotNil(response?.metrics)
  595. }
  596. }
  597. class DownloadResponseMapErrorTestCase: BaseTestCase {
  598. func testThatMapErrorTransformsFailureValue() {
  599. // Given
  600. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  601. let expectation = self.expectation(description: "request should not succeed")
  602. var response: DownloadResponse<Any>?
  603. // When
  604. Alamofire.download(urlString).responseJSON { resp in
  605. response = resp.mapError { error in
  606. return TestError.error(error: error)
  607. }
  608. expectation.fulfill()
  609. }
  610. waitForExpectations(timeout: timeout, handler: nil)
  611. // Then
  612. XCTAssertNotNil(response?.request)
  613. XCTAssertNil(response?.response)
  614. XCTAssertNil(response?.temporaryURL)
  615. XCTAssertNil(response?.destinationURL)
  616. XCTAssertNil(response?.resumeData)
  617. XCTAssertNotNil(response?.error)
  618. XCTAssertEqual(response?.result.isFailure, true)
  619. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  620. XCTAssertNotNil(response?.metrics)
  621. }
  622. // func testThatMapErrorPreservesSuccessValue() {
  623. // // Given
  624. // let urlString = "https://httpbin.org/get"
  625. // let expectation = self.expectation(description: "request should succeed")
  626. //
  627. // var response: DownloadResponse<Data>?
  628. //
  629. // // When
  630. // Alamofire.download(urlString).responseData { resp in
  631. // response = resp.mapError { TestError.error(error: $0) }
  632. // expectation.fulfill()
  633. // }
  634. //
  635. // waitForExpectations(timeout: timeout, handler: nil)
  636. //
  637. // // Then
  638. // XCTAssertNotNil(response?.request)
  639. // XCTAssertNotNil(response?.response)
  640. // XCTAssertNotNil(response?.temporaryURL)
  641. // XCTAssertNil(response?.destinationURL)
  642. // XCTAssertNil(response?.resumeData)
  643. // XCTAssertEqual(response?.result.isSuccess, true)
  644. // XCTAssertNotNil(response?.metrics)
  645. // }
  646. }
  647. // MARK: -
  648. class DownloadResponseFlatMapErrorTestCase: BaseTestCase {
  649. // func testThatFlatMapErrorPreservesSuccessValue() {
  650. // // Given
  651. // let urlString = "https://httpbin.org/get"
  652. // let expectation = self.expectation(description: "request should succeed")
  653. //
  654. // var response: DownloadResponse<Data>?
  655. //
  656. // // When
  657. // Alamofire.download(urlString).responseData { resp in
  658. // response = resp.flatMapError { TestError.error(error: $0) }
  659. // expectation.fulfill()
  660. // }
  661. //
  662. // waitForExpectations(timeout: timeout, handler: nil)
  663. //
  664. // // Then
  665. // XCTAssertNotNil(response?.request)
  666. // XCTAssertNotNil(response?.response)
  667. // XCTAssertNotNil(response?.temporaryURL)
  668. // XCTAssertNil(response?.destinationURL)
  669. // XCTAssertNil(response?.resumeData)
  670. // XCTAssertNil(response?.error)
  671. // XCTAssertEqual(response?.result.isSuccess, true)
  672. // XCTAssertNotNil(response?.metrics)
  673. // }
  674. func testThatFlatMapErrorCatchesTransformationError() {
  675. // Given
  676. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  677. let expectation = self.expectation(description: "request should fail")
  678. var response: DownloadResponse<Data>?
  679. // When
  680. Alamofire.download(urlString).responseData { resp in
  681. response = resp.flatMapError { _ in try TransformationError.error.alwaysFails() }
  682. expectation.fulfill()
  683. }
  684. waitForExpectations(timeout: timeout, handler: nil)
  685. // Then
  686. XCTAssertNotNil(response?.request)
  687. XCTAssertNil(response?.response)
  688. XCTAssertNil(response?.temporaryURL)
  689. XCTAssertNil(response?.destinationURL)
  690. XCTAssertNil(response?.resumeData)
  691. XCTAssertNotNil(response?.error)
  692. XCTAssertEqual(response?.result.isFailure, true)
  693. if let error = response?.result.error {
  694. XCTAssertTrue(error is TransformationError)
  695. } else {
  696. XCTFail("flatMapError should catch the transformation error")
  697. }
  698. XCTAssertNotNil(response?.metrics)
  699. }
  700. func testThatFlatMapErrorTransformsError() {
  701. // Given
  702. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  703. let expectation = self.expectation(description: "request should fail")
  704. var response: DownloadResponse<Data>?
  705. // When
  706. Alamofire.download(urlString).responseData { resp in
  707. response = resp.flatMapError { TestError.error(error: $0) }
  708. expectation.fulfill()
  709. }
  710. waitForExpectations(timeout: timeout, handler: nil)
  711. // Then
  712. XCTAssertNotNil(response?.request)
  713. XCTAssertNil(response?.response)
  714. XCTAssertNil(response?.temporaryURL)
  715. XCTAssertNil(response?.destinationURL)
  716. XCTAssertNil(response?.resumeData)
  717. XCTAssertNotNil(response?.error)
  718. XCTAssertEqual(response?.result.isFailure, true)
  719. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  720. XCTAssertNotNil(response?.metrics)
  721. }
  722. }