ValidationTests.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. // ValidationTests.swift
  2. //
  3. // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. @testable import Alamofire
  23. import Foundation
  24. import XCTest
  25. class StatusCodeValidationTestCase: BaseTestCase {
  26. func testThatValidationForRequestWithAcceptableStatusCodeResponseSucceeds() {
  27. // Given
  28. let URLString = "https://httpbin.org/status/200"
  29. let expectation = expectationWithDescription("request should return 200 status code")
  30. var error: NSError?
  31. // When
  32. Alamofire.request(.GET, URLString)
  33. .validate(statusCode: 200..<300)
  34. .response { _, _, _, responseError in
  35. error = responseError
  36. expectation.fulfill()
  37. }
  38. waitForExpectationsWithTimeout(timeout, handler: nil)
  39. // Then
  40. XCTAssertNil(error)
  41. }
  42. func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() {
  43. // Given
  44. let URLString = "https://httpbin.org/status/404"
  45. let expectation = expectationWithDescription("request should return 404 status code")
  46. var error: NSError?
  47. // When
  48. Alamofire.request(.GET, URLString)
  49. .validate(statusCode: [200])
  50. .response { _, _, _, responseError in
  51. error = responseError
  52. expectation.fulfill()
  53. }
  54. waitForExpectationsWithTimeout(timeout, handler: nil)
  55. // Then
  56. XCTAssertNotNil(error)
  57. if let error = error {
  58. XCTAssertEqual(error.domain, Error.Domain)
  59. XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue)
  60. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 404)
  61. } else {
  62. XCTFail("error should not be nil")
  63. }
  64. }
  65. func testThatValidationForRequestWithNoAcceptableStatusCodesFails() {
  66. // Given
  67. let URLString = "https://httpbin.org/status/201"
  68. let expectation = expectationWithDescription("request should return 201 status code")
  69. var error: NSError?
  70. // When
  71. Alamofire.request(.GET, URLString)
  72. .validate(statusCode: [])
  73. .response { _, _, _, responseError in
  74. error = responseError
  75. expectation.fulfill()
  76. }
  77. waitForExpectationsWithTimeout(timeout, handler: nil)
  78. // Then
  79. XCTAssertNotNil(error)
  80. if let error = error {
  81. XCTAssertEqual(error.domain, Error.Domain)
  82. XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue)
  83. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 201)
  84. } else {
  85. XCTFail("error should not be nil")
  86. }
  87. }
  88. }
  89. // MARK: -
  90. class ContentTypeValidationTestCase: BaseTestCase {
  91. func testThatValidationForRequestWithAcceptableContentTypeResponseSucceeds() {
  92. // Given
  93. let URLString = "https://httpbin.org/ip"
  94. let expectation = expectationWithDescription("request should succeed and return ip")
  95. var error: NSError?
  96. // When
  97. Alamofire.request(.GET, URLString)
  98. .validate(contentType: ["application/json"])
  99. .validate(contentType: ["application/json;charset=utf8"])
  100. .validate(contentType: ["application/json;q=0.8;charset=utf8"])
  101. .response { _, _, _, responseError in
  102. error = responseError
  103. expectation.fulfill()
  104. }
  105. waitForExpectationsWithTimeout(timeout, handler: nil)
  106. // Then
  107. XCTAssertNil(error)
  108. }
  109. func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceeds() {
  110. // Given
  111. let URLString = "https://httpbin.org/ip"
  112. let expectation = expectationWithDescription("request should succeed and return ip")
  113. var error: NSError?
  114. // When
  115. Alamofire.request(.GET, URLString)
  116. .validate(contentType: ["*/*"])
  117. .validate(contentType: ["application/*"])
  118. .validate(contentType: ["*/json"])
  119. .response { _, _, _, responseError in
  120. error = responseError
  121. expectation.fulfill()
  122. }
  123. waitForExpectationsWithTimeout(timeout, handler: nil)
  124. // Then
  125. XCTAssertNil(error)
  126. }
  127. func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() {
  128. // Given
  129. let URLString = "https://httpbin.org/xml"
  130. let expectation = expectationWithDescription("request should succeed and return xml")
  131. var error: NSError?
  132. // When
  133. Alamofire.request(.GET, URLString)
  134. .validate(contentType: ["application/octet-stream"])
  135. .response { _, _, _, responseError in
  136. error = responseError
  137. expectation.fulfill()
  138. }
  139. waitForExpectationsWithTimeout(timeout, handler: nil)
  140. // Then
  141. XCTAssertNotNil(error)
  142. if let error = error {
  143. XCTAssertEqual(error.domain, Error.Domain)
  144. XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue)
  145. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml")
  146. } else {
  147. XCTFail("error should not be nil")
  148. }
  149. }
  150. func testThatValidationForRequestWithNoAcceptableContentTypeResponseFails() {
  151. // Given
  152. let URLString = "https://httpbin.org/xml"
  153. let expectation = expectationWithDescription("request should succeed and return xml")
  154. var error: NSError?
  155. // When
  156. Alamofire.request(.GET, URLString)
  157. .validate(contentType: [])
  158. .response { _, _, _, responseError in
  159. error = responseError
  160. expectation.fulfill()
  161. }
  162. waitForExpectationsWithTimeout(timeout, handler: nil)
  163. // Then
  164. XCTAssertNotNil(error, "error should not be nil")
  165. if let error = error {
  166. XCTAssertEqual(error.domain, Error.Domain)
  167. XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue)
  168. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml")
  169. } else {
  170. XCTFail("error should not be nil")
  171. }
  172. }
  173. func testThatValidationForRequestWithNoAcceptableContentTypeResponseSucceedsWhenNoDataIsReturned() {
  174. // Given
  175. let URLString = "https://httpbin.org/status/204"
  176. let expectation = expectationWithDescription("request should succeed and return no data")
  177. var error: NSError?
  178. // When
  179. Alamofire.request(.GET, URLString)
  180. .validate(contentType: [])
  181. .response { _, response, data, responseError in
  182. error = responseError
  183. expectation.fulfill()
  184. }
  185. waitForExpectationsWithTimeout(timeout, handler: nil)
  186. // Then
  187. XCTAssertNil(error)
  188. }
  189. func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceedsWhenResponseIsNil() {
  190. // Given
  191. class MockManager: Manager {
  192. override func request(URLRequest: URLRequestConvertible) -> Request {
  193. var dataTask: NSURLSessionDataTask!
  194. dispatch_sync(queue) {
  195. dataTask = self.session.dataTaskWithRequest(URLRequest.URLRequest)
  196. }
  197. let request = MockRequest(session: session, task: dataTask)
  198. delegate[request.delegate.task] = request.delegate
  199. if startRequestsImmediately {
  200. request.resume()
  201. }
  202. return request
  203. }
  204. }
  205. class MockRequest: Request {
  206. override var response: NSHTTPURLResponse? {
  207. return MockHTTPURLResponse(
  208. URL: NSURL(string: request!.URLString)!,
  209. statusCode: 204,
  210. HTTPVersion: "HTTP/1.1",
  211. headerFields: nil
  212. )
  213. }
  214. }
  215. class MockHTTPURLResponse: NSHTTPURLResponse {
  216. override var MIMEType: String? { return nil }
  217. }
  218. let manager: Manager = {
  219. let configuration: NSURLSessionConfiguration = {
  220. let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
  221. configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
  222. return configuration
  223. }()
  224. return MockManager(configuration: configuration)
  225. }()
  226. let URLString = "https://httpbin.org/delete"
  227. let expectation = expectationWithDescription("request should be stubbed and return 204 status code")
  228. var response: NSHTTPURLResponse?
  229. var data: NSData?
  230. var error: NSError?
  231. // When
  232. manager.request(.DELETE, URLString)
  233. .validate(contentType: ["*/*"])
  234. .response { _, responseResponse, responseData, responseError in
  235. response = responseResponse
  236. data = responseData
  237. error = responseError
  238. expectation.fulfill()
  239. }
  240. waitForExpectationsWithTimeout(timeout, handler: nil)
  241. // Then
  242. XCTAssertNotNil(response)
  243. XCTAssertNotNil(data)
  244. XCTAssertNil(error)
  245. if let response = response {
  246. XCTAssertEqual(response.statusCode, 204)
  247. XCTAssertNil(response.MIMEType)
  248. }
  249. }
  250. }
  251. // MARK: -
  252. class MultipleValidationTestCase: BaseTestCase {
  253. func testThatValidationForRequestWithAcceptableStatusCodeAndContentTypeResponseSucceeds() {
  254. // Given
  255. let URLString = "https://httpbin.org/ip"
  256. let expectation = expectationWithDescription("request should succeed and return ip")
  257. var error: NSError?
  258. // When
  259. Alamofire.request(.GET, URLString)
  260. .validate(statusCode: 200..<300)
  261. .validate(contentType: ["application/json"])
  262. .response { _, _, _, responseError in
  263. error = responseError
  264. expectation.fulfill()
  265. }
  266. waitForExpectationsWithTimeout(timeout, handler: nil)
  267. // Then
  268. XCTAssertNil(error)
  269. }
  270. func testThatValidationForRequestWithUnacceptableStatusCodeAndContentTypeResponseFailsWithStatusCodeError() {
  271. // Given
  272. let URLString = "https://httpbin.org/xml"
  273. let expectation = expectationWithDescription("request should succeed and return xml")
  274. var error: NSError?
  275. // When
  276. Alamofire.request(.GET, URLString)
  277. .validate(statusCode: 400..<600)
  278. .validate(contentType: ["application/octet-stream"])
  279. .response { _, _, _, responseError in
  280. error = responseError
  281. expectation.fulfill()
  282. }
  283. waitForExpectationsWithTimeout(timeout, handler: nil)
  284. // Then
  285. XCTAssertNotNil(error)
  286. if let error = error {
  287. XCTAssertEqual(error.domain, Error.Domain)
  288. XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue)
  289. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 200)
  290. } else {
  291. XCTFail("error should not be nil")
  292. }
  293. }
  294. func testThatValidationForRequestWithUnacceptableStatusCodeAndContentTypeResponseFailsWithContentTypeError() {
  295. // Given
  296. let URLString = "https://httpbin.org/xml"
  297. let expectation = expectationWithDescription("request should succeed and return xml")
  298. var error: NSError?
  299. // When
  300. Alamofire.request(.GET, URLString)
  301. .validate(contentType: ["application/octet-stream"])
  302. .validate(statusCode: 400..<600)
  303. .response { _, _, _, responseError in
  304. error = responseError
  305. expectation.fulfill()
  306. }
  307. waitForExpectationsWithTimeout(timeout, handler: nil)
  308. // Then
  309. XCTAssertNotNil(error)
  310. if let error = error {
  311. XCTAssertEqual(error.domain, Error.Domain)
  312. XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue)
  313. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml")
  314. } else {
  315. XCTFail("error should not be nil")
  316. }
  317. }
  318. }
  319. // MARK: -
  320. class AutomaticValidationTestCase: BaseTestCase {
  321. func testThatValidationForRequestWithAcceptableStatusCodeAndContentTypeResponseSucceeds() {
  322. // Given
  323. let URL = NSURL(string: "https://httpbin.org/ip")!
  324. let mutableURLRequest = NSMutableURLRequest(URL: URL)
  325. mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Accept")
  326. let expectation = expectationWithDescription("request should succeed and return ip")
  327. var error: NSError?
  328. // When
  329. Alamofire.request(mutableURLRequest)
  330. .validate()
  331. .response { _, _, _, responseError in
  332. error = responseError
  333. expectation.fulfill()
  334. }
  335. waitForExpectationsWithTimeout(timeout, handler: nil)
  336. // Then
  337. XCTAssertNil(error)
  338. }
  339. func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() {
  340. // Given
  341. let URLString = "https://httpbin.org/status/404"
  342. let expectation = expectationWithDescription("request should return 404 status code")
  343. var error: NSError?
  344. // When
  345. Alamofire.request(.GET, URLString)
  346. .validate()
  347. .response { _, _, _, responseError in
  348. error = responseError
  349. expectation.fulfill()
  350. }
  351. waitForExpectationsWithTimeout(timeout, handler: nil)
  352. // Then
  353. XCTAssertNotNil(error)
  354. if let error = error {
  355. XCTAssertEqual(error.domain, Error.Domain)
  356. XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue)
  357. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 404)
  358. } else {
  359. XCTFail("error should not be nil")
  360. }
  361. }
  362. func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceeds() {
  363. // Given
  364. let URL = NSURL(string: "https://httpbin.org/ip")!
  365. let mutableURLRequest = NSMutableURLRequest(URL: URL)
  366. mutableURLRequest.setValue("application/*", forHTTPHeaderField: "Accept")
  367. let expectation = expectationWithDescription("request should succeed and return ip")
  368. var error: NSError?
  369. // When
  370. Alamofire.request(mutableURLRequest)
  371. .validate()
  372. .response { _, _, _, responseError in
  373. error = responseError
  374. expectation.fulfill()
  375. }
  376. waitForExpectationsWithTimeout(timeout, handler: nil)
  377. // Then
  378. XCTAssertNil(error)
  379. }
  380. func testThatValidationForRequestWithAcceptableComplexContentTypeResponseSucceeds() {
  381. // Given
  382. let URL = NSURL(string: "https://httpbin.org/xml")!
  383. let mutableURLRequest = NSMutableURLRequest(URL: URL)
  384. let headerValue = "text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8,*/*;q=0.5"
  385. mutableURLRequest.setValue(headerValue, forHTTPHeaderField: "Accept")
  386. let expectation = expectationWithDescription("request should succeed and return xml")
  387. var error: NSError?
  388. // When
  389. Alamofire.request(mutableURLRequest)
  390. .validate()
  391. .response { _, _, _, responseError in
  392. error = responseError
  393. expectation.fulfill()
  394. }
  395. waitForExpectationsWithTimeout(timeout, handler: nil)
  396. // Then
  397. XCTAssertNil(error)
  398. }
  399. func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() {
  400. // Given
  401. let URL = NSURL(string: "https://httpbin.org/xml")!
  402. let mutableURLRequest = NSMutableURLRequest(URL: URL)
  403. mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Accept")
  404. let expectation = expectationWithDescription("request should succeed and return xml")
  405. var error: NSError?
  406. // When
  407. Alamofire.request(mutableURLRequest)
  408. .validate()
  409. .response { _, _, _, responseError in
  410. error = responseError
  411. expectation.fulfill()
  412. }
  413. waitForExpectationsWithTimeout(timeout, handler: nil)
  414. // Then
  415. XCTAssertNotNil(error)
  416. if let error = error {
  417. XCTAssertEqual(error.domain, Error.Domain)
  418. XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue)
  419. XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml")
  420. } else {
  421. XCTFail("error should not be nil")
  422. }
  423. }
  424. }