2
0

ParameterEncodingTests.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. // ParameterEncodingTests.swift
  2. //
  3. // Copyright (c) 2014–2015 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. import Alamofire
  23. import Foundation
  24. import XCTest
  25. class ParameterEncodingTestCase: BaseTestCase {
  26. let URLRequest = NSURLRequest(URL: NSURL(string: "http://example.com/")!)
  27. }
  28. // MARK: -
  29. /**
  30. The URL parameter encoding tests cover a variety of cases for encoding query parameters in addition to percent escaping reserved characters. The percent escaping implementation follows RFC 3986 - Sections 2.2, 2.4 and 3.4. All reserved characters are percent encoded with the exception of the "?" and "/" characters. This exception was made to allow other URIs to be included as query parameters without issue. See RFC 3986 - Section 3.4 for more details.
  31. */
  32. class URLParameterEncodingTestCase: ParameterEncodingTestCase {
  33. // MARK: Properties
  34. let encoding: ParameterEncoding = .URL
  35. // MARK: Tests
  36. func testURLParameterEncodeNilParameters() {
  37. // Given
  38. // When
  39. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: nil)
  40. // Then
  41. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  42. }
  43. func testURLParameterEncodeOneStringKeyStringValueParameter() {
  44. // Given
  45. let parameters = ["foo": "bar"]
  46. // When
  47. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  48. // Then
  49. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=bar", "query is incorrect")
  50. }
  51. func testURLParameterEncodeOneStringKeyStringValueParameterAppendedToQuery() {
  52. // Given
  53. var mutableURLRequest = self.URLRequest.mutableCopy() as! NSMutableURLRequest
  54. let URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false)!
  55. URLComponents.query = "baz=qux"
  56. mutableURLRequest.URL = URLComponents.URL
  57. let parameters = ["foo": "bar"]
  58. // When
  59. let (URLRequest, error) = self.encoding.encode(mutableURLRequest, parameters: parameters)
  60. // Then
  61. XCTAssertEqual(URLRequest.URL?.query ?? "", "baz=qux&foo=bar", "query is incorrect")
  62. }
  63. func testURLParameterEncodeTwoStringKeyStringValueParameters() {
  64. // Given
  65. let parameters = ["foo": "bar", "baz": "qux"]
  66. // When
  67. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  68. // Then
  69. XCTAssertEqual(URLRequest.URL?.query ?? "", "baz=qux&foo=bar", "query is incorrect")
  70. }
  71. func testURLParameterEncodeStringKeyIntegerValueParameter() {
  72. // Given
  73. let parameters = ["foo": 1]
  74. // When
  75. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  76. // Then
  77. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1", "query is incorrect")
  78. }
  79. func testURLParameterEncodeStringKeyDoubleValueParameter() {
  80. // Given
  81. let parameters = ["foo": 1.1]
  82. // When
  83. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  84. // Then
  85. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1.1", "query is incorrect")
  86. }
  87. func testURLParameterEncodeStringKeyBoolValueParameter() {
  88. // Given
  89. let parameters = ["foo": true]
  90. // When
  91. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  92. // Then
  93. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1", "query is incorrect")
  94. }
  95. func testURLParameterEncodeStringKeyArrayValueParameter() {
  96. // Given
  97. let parameters = ["foo": ["a", 1, true]]
  98. // When
  99. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  100. // Then
  101. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5B%5D=a&foo%5B%5D=1&foo%5B%5D=1", "query is incorrect")
  102. }
  103. func testURLParameterEncodeStringKeyDictionaryValueParameter() {
  104. // Given
  105. let parameters = ["foo": ["bar": 1]]
  106. // When
  107. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  108. // Then
  109. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5Bbar%5D=1", "query is incorrect")
  110. }
  111. func testURLParameterEncodeStringKeyNestedDictionaryValueParameter() {
  112. // Given
  113. let parameters = ["foo": ["bar": ["baz": 1]]]
  114. // When
  115. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  116. // Then
  117. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5Bbar%5D%5Bbaz%5D=1", "query is incorrect")
  118. }
  119. func testURLParameterEncodeStringKeyNestedDictionaryArrayValueParameter() {
  120. // Given
  121. let parameters = ["foo": ["bar": ["baz": ["a", 1, true]]]]
  122. // When
  123. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  124. // Then
  125. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5Bbar%5D%5Bbaz%5D%5B%5D=a&foo%5Bbar%5D%5Bbaz%5D%5B%5D=1&foo%5Bbar%5D%5Bbaz%5D%5B%5D=1", "query is incorrect")
  126. }
  127. func testURLParameterEncodeStringWithAmpersandKeyStringWithAmpersandValueParameter() {
  128. // Given
  129. let parameters = ["foo&bar": "baz&qux", "foobar": "bazqux"]
  130. // When
  131. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  132. // Then
  133. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%26bar=baz%26qux&foobar=bazqux", "query is incorrect")
  134. }
  135. func testURLParameterEncodeStringWithQuestionMarkKeyStringWithQuestionMarkValueParameter() {
  136. // Given
  137. let parameters = ["?foo?": "?bar?"]
  138. // When
  139. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  140. // Then
  141. XCTAssertEqual(URLRequest.URL?.query ?? "", "?foo?=?bar?", "query is incorrect")
  142. }
  143. func testURLParameterEncodeStringWithSlashKeyStringWithQuestionMarkValueParameter() {
  144. // Given
  145. let parameters = ["foo": "/bar/baz/qux"]
  146. // When
  147. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  148. // Then
  149. XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=/bar/baz/qux", "query is incorrect")
  150. }
  151. func testURLParameterEncodeStringWithSpaceKeyStringWithSpaceValueParameter() {
  152. // Given
  153. let parameters = [" foo ": " bar "]
  154. // When
  155. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  156. // Then
  157. XCTAssertEqual(URLRequest.URL?.query ?? "", "%20foo%20=%20bar%20", "query is incorrect")
  158. }
  159. func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameter() {
  160. // Given
  161. let parameters = ["+foo+": "+bar+"]
  162. // When
  163. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  164. // Then
  165. XCTAssertEqual(URLRequest.URL?.query ?? "", "%2Bfoo%2B=%2Bbar%2B", "query is incorrect")
  166. }
  167. func testURLParameterEncodeStringKeyAllowedCharactersStringValueParameter() {
  168. // Given
  169. let parameters = ["allowed": " =\"#%<>@\\^`{}[]|&"]
  170. // When
  171. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  172. // Then
  173. XCTAssertEqual(URLRequest.URL?.query ?? "", "allowed=%20%3D%22%23%25%3C%3E%40%5C%5E%60%7B%7D%5B%5D%7C%26", "query is incorrect")
  174. }
  175. func testURLParameterEncodeStringKeyPercentEncodedStringValueParameter() {
  176. // Given
  177. let parameters = ["percent": "%25"]
  178. // When
  179. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  180. // Then
  181. XCTAssertEqual(URLRequest.URL?.query ?? "", "percent=%2525", "query is incorrect")
  182. }
  183. func testURLParameterEncodeStringKeyNonLatinStringValueParameter() {
  184. // Given
  185. let parameters = [
  186. "french": "français",
  187. "japanese": "日本語",
  188. "arabic": "العربية",
  189. "emoji": "😃"
  190. ]
  191. // When
  192. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  193. // Then
  194. XCTAssertEqual(URLRequest.URL?.query ?? "", "arabic=%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9&emoji=%F0%9F%98%83&french=fran%C3%A7ais&japanese=%E6%97%A5%E6%9C%AC%E8%AA%9E", "query is incorrect")
  195. }
  196. func testURLParameterEncodeStringForRequestWithPrecomposedQuery() {
  197. // Given
  198. let URL = NSURL(string: "http://example.com/movies?hd=[1]")!
  199. let parameters = ["page": "0"]
  200. // When
  201. let (URLRequest, error) = self.encoding.encode(NSURLRequest(URL: URL), parameters: parameters)
  202. // Then
  203. XCTAssertEqual(URLRequest.URL?.query ?? "", "hd=%5B1%5D&page=0", "query is incorrect")
  204. }
  205. func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameterForRequestWithPrecomposedQuery() {
  206. // Given
  207. let URL = NSURL(string: "http://example.com/movie?hd=[1]")!
  208. let parameters = ["+foo+": "+bar+"]
  209. // When
  210. let (URLRequest, error) = self.encoding.encode(NSURLRequest(URL: URL), parameters: parameters)
  211. // Then
  212. XCTAssertEqual(URLRequest.URL?.query ?? "", "hd=%5B1%5D&%2Bfoo%2B=%2Bbar%2B", "query is incorrect")
  213. }
  214. func testURLParameterEncodeGETParametersInURL() {
  215. // Given
  216. var mutableURLRequest = self.URLRequest.mutableCopy() as! NSMutableURLRequest
  217. mutableURLRequest.HTTPMethod = Method.GET.rawValue
  218. let parameters = ["foo": 1, "bar": 2]
  219. // When
  220. let (URLRequest, error) = self.encoding.encode(mutableURLRequest, parameters: parameters)
  221. // Then
  222. XCTAssertEqual(URLRequest.URL?.query ?? "", "bar=2&foo=1", "query is incorrect")
  223. XCTAssertNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should be nil")
  224. XCTAssertNil(URLRequest.HTTPBody, "HTTPBody should be nil")
  225. }
  226. func testURLParameterEncodePOSTParametersInHTTPBody() {
  227. // Given
  228. var mutableURLRequest = self.URLRequest.mutableCopy() as! NSMutableURLRequest
  229. mutableURLRequest.HTTPMethod = Method.POST.rawValue
  230. let parameters = ["foo": 1, "bar": 2]
  231. // When
  232. let (URLRequest, error) = self.encoding.encode(mutableURLRequest, parameters: parameters)
  233. // Then
  234. XCTAssertEqual(URLRequest.valueForHTTPHeaderField("Content-Type") ?? "", "application/x-www-form-urlencoded", "Content-Type should be application/x-www-form-urlencoded")
  235. XCTAssertNotNil(URLRequest.HTTPBody, "HTTPBody should not be nil")
  236. if let HTTPBody = URLRequest.HTTPBody,
  237. decodedHTTPBody = NSString(data: HTTPBody, encoding: NSUTF8StringEncoding)
  238. {
  239. XCTAssertEqual(decodedHTTPBody, "bar=2&foo=1", "HTTPBody is incorrect")
  240. } else {
  241. XCTFail("decoded http body should not be nil")
  242. }
  243. }
  244. }
  245. // MARK: -
  246. class JSONParameterEncodingTestCase: ParameterEncodingTestCase {
  247. // MARK: Properties
  248. let encoding: ParameterEncoding = .JSON
  249. // MARK: Tests
  250. func testJSONParameterEncodeNilParameters() {
  251. // Given
  252. // When
  253. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: nil)
  254. // Then
  255. XCTAssertNil(error, "error should be nil")
  256. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  257. XCTAssertNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should be nil")
  258. XCTAssertNil(URLRequest.HTTPBody, "HTTPBody should be nil")
  259. }
  260. func testJSONParameterEncodeComplexParameters() {
  261. // Given
  262. let parameters = [
  263. "foo": "bar",
  264. "baz": ["a", 1, true],
  265. "qux": [
  266. "a": 1,
  267. "b": [2, 2],
  268. "c": [3, 3, 3]
  269. ]
  270. ]
  271. // When
  272. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  273. // Then
  274. XCTAssertNil(error, "error should be nil")
  275. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  276. XCTAssertNotNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should not be nil")
  277. XCTAssertEqual(URLRequest.valueForHTTPHeaderField("Content-Type") ?? "", "application/json", "Content-Type should be application/json")
  278. XCTAssertNotNil(URLRequest.HTTPBody, "HTTPBody should not be nil")
  279. if let HTTPBody = URLRequest.HTTPBody,
  280. JSON = NSJSONSerialization.JSONObjectWithData(HTTPBody, options: .AllowFragments, error: nil) as? NSObject
  281. {
  282. XCTAssertEqual(JSON, parameters as NSObject, "HTTPBody JSON does not equal parameters")
  283. } else {
  284. XCTFail("JSON should not be nil")
  285. }
  286. }
  287. }
  288. // MARK: -
  289. class PropertyListParameterEncodingTestCase: ParameterEncodingTestCase {
  290. // MARK: Properties
  291. let encoding: ParameterEncoding = .PropertyList(.XMLFormat_v1_0, 0)
  292. // MARK: Tests
  293. func testPropertyListParameterEncodeNilParameters() {
  294. // Given
  295. // When
  296. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: nil)
  297. // Then
  298. XCTAssertNil(error, "error should be nil")
  299. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  300. XCTAssertNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should be nil")
  301. XCTAssertNil(URLRequest.HTTPBody, "HTTPBody should be nil")
  302. }
  303. func testPropertyListParameterEncodeComplexParameters() {
  304. // Given
  305. let parameters = [
  306. "foo": "bar",
  307. "baz": ["a", 1, true],
  308. "qux": [
  309. "a": 1,
  310. "b": [2, 2],
  311. "c": [3, 3, 3]
  312. ]
  313. ]
  314. // When
  315. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  316. // Then
  317. XCTAssertNil(error, "error should be nil")
  318. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  319. XCTAssertNotNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should not be nil")
  320. XCTAssertEqual(URLRequest.valueForHTTPHeaderField("Content-Type") ?? "", "application/x-plist", "Content-Type should be application/x-plist")
  321. XCTAssertNotNil(URLRequest.HTTPBody, "HTTPBody should not be nil")
  322. if let HTTPBody = URLRequest.HTTPBody,
  323. let plist = NSPropertyListSerialization.propertyListWithData(HTTPBody, options: 0, format: nil, error: nil) as? NSObject
  324. {
  325. XCTAssertEqual(plist, parameters as NSObject, "HTTPBody plist does not equal parameters")
  326. } else {
  327. XCTFail("plist should not be nil")
  328. }
  329. }
  330. func testPropertyListParameterEncodeDateAndDataParameters() {
  331. // Given
  332. let date: NSDate = NSDate()
  333. let data: NSData = "data".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
  334. let parameters = [
  335. "date": date,
  336. "data": data
  337. ]
  338. // When
  339. let (URLRequest, error) = self.encoding.encode(self.URLRequest, parameters: parameters)
  340. // Then
  341. XCTAssertNil(error, "error should be nil")
  342. XCTAssertNil(URLRequest.URL?.query, "query should be nil")
  343. XCTAssertNotNil(URLRequest.valueForHTTPHeaderField("Content-Type"), "Content-Type should not be nil")
  344. XCTAssertEqual(URLRequest.valueForHTTPHeaderField("Content-Type") ?? "", "application/x-plist", "Content-Type should be application/x-plist")
  345. XCTAssertNotNil(URLRequest.HTTPBody, "HTTPBody should not be nil")
  346. if let HTTPBody = URLRequest.HTTPBody,
  347. let plist = NSPropertyListSerialization.propertyListWithData(HTTPBody, options: 0, format: nil, error: nil) as? NSObject
  348. {
  349. XCTAssertTrue(plist.valueForKey("date") is NSDate, "date is not NSDate")
  350. XCTAssertTrue(plist.valueForKey("data") is NSData, "data is not NSData")
  351. } else {
  352. XCTFail("plist should not be nil")
  353. }
  354. }
  355. }
  356. // MARK: -
  357. class CustomParameterEncodingTestCase: ParameterEncodingTestCase {
  358. // MARK: Tests
  359. func testCustomParameterEncode() {
  360. // Given
  361. let encodingClosure: (URLRequestConvertible, [String: AnyObject]?) -> (NSURLRequest, NSError?) = { URLRequest, parameters in
  362. let mutableURLRequest = URLRequest.URLRequest.mutableCopy() as! NSMutableURLRequest
  363. mutableURLRequest.setValue("Xcode", forHTTPHeaderField: "User-Agent")
  364. return (mutableURLRequest, nil)
  365. }
  366. // When
  367. let encoding: ParameterEncoding = .Custom(encodingClosure)
  368. // Then
  369. let URL = NSURL(string: "http://example.com")!
  370. let URLRequest = NSURLRequest(URL: URL)
  371. let parameters: [String: AnyObject] = [:]
  372. XCTAssertEqual(encoding.encode(URLRequest, parameters: parameters).0, encodingClosure(URLRequest, parameters).0, "URLRequest should be equal")
  373. }
  374. }