ParameterEncodingTests.swift 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. //
  2. // ParameterEncodingTests.swift
  3. //
  4. // Copyright (c) 2014-2016 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 ParameterEncodingTestCase: BaseTestCase {
  28. let urlRequest = URLRequest(url: URL(string: "https://example.com/")!)
  29. }
  30. // MARK: -
  31. class URLParameterEncodingTestCase: ParameterEncodingTestCase {
  32. // MARK: Properties
  33. let encoding: ParameterEncoding = .url
  34. // MARK: Tests - Parameter Types
  35. func testURLParameterEncodeNilParameters() {
  36. do {
  37. // Given, When
  38. let urlRequest = try encoding.encode(self.urlRequest, with: nil)
  39. // Then
  40. XCTAssertNil(urlRequest.url?.query, "query should be nil")
  41. } catch {
  42. XCTFail("Test encountered unexpected error: \(error)")
  43. }
  44. }
  45. func testURLParameterEncodeEmptyDictionaryParameter() {
  46. do {
  47. // Given
  48. let parameters: [String: Any] = [:]
  49. // When
  50. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  51. // Then
  52. XCTAssertNil(urlRequest.url?.query, "query should be nil")
  53. } catch {
  54. XCTFail("Test encountered unexpected error: \(error)")
  55. }
  56. }
  57. func testURLParameterEncodeOneStringKeyStringValueParameter() {
  58. do {
  59. // Given
  60. let parameters = ["foo": "bar"]
  61. // When
  62. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  63. // Then
  64. XCTAssertEqual(urlRequest.url?.query ?? "", "foo=bar", "query is incorrect")
  65. } catch {
  66. XCTFail("Test encountered unexpected error: \(error)")
  67. }
  68. }
  69. func testURLParameterEncodeOneStringKeyStringValueParameterAppendedToQuery() {
  70. do {
  71. // Given
  72. var mutableURLRequest = self.urlRequest.urlRequest
  73. var urlComponents = URLComponents(url: mutableURLRequest.url!, resolvingAgainstBaseURL: false)!
  74. urlComponents.query = "baz=qux"
  75. mutableURLRequest.url = urlComponents.url
  76. let parameters = ["foo": "bar"]
  77. // When
  78. let urlRequest = try encoding.encode(mutableURLRequest, with: parameters)
  79. // Then
  80. XCTAssertEqual(urlRequest.url?.query ?? "", "baz=qux&foo=bar", "query is incorrect")
  81. } catch {
  82. XCTFail("Test encountered unexpected error: \(error)")
  83. }
  84. }
  85. func testURLParameterEncodeTwoStringKeyStringValueParameters() {
  86. do {
  87. // Given
  88. let parameters = ["foo": "bar", "baz": "qux"]
  89. // When
  90. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  91. // Then
  92. XCTAssertEqual(urlRequest.url?.query ?? "", "baz=qux&foo=bar", "query is incorrect")
  93. } catch {
  94. XCTFail("Test encountered unexpected error: \(error)")
  95. }
  96. }
  97. func testURLParameterEncodeStringKeyIntegerValueParameter() {
  98. do {
  99. // Given
  100. let parameters = ["foo": 1]
  101. // When
  102. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  103. // Then
  104. XCTAssertEqual(urlRequest.url?.query ?? "", "foo=1", "query is incorrect")
  105. } catch {
  106. XCTFail("Test encountered unexpected error: \(error)")
  107. }
  108. }
  109. func testURLParameterEncodeStringKeyDoubleValueParameter() {
  110. do {
  111. // Given
  112. let parameters = ["foo": 1.1]
  113. // When
  114. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  115. // Then
  116. XCTAssertEqual(urlRequest.url?.query ?? "", "foo=1.1", "query is incorrect")
  117. } catch {
  118. XCTFail("Test encountered unexpected error: \(error)")
  119. }
  120. }
  121. func testURLParameterEncodeStringKeyBoolValueParameter() {
  122. do {
  123. // Given
  124. let parameters = ["foo": true]
  125. // When
  126. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  127. // Then
  128. XCTAssertEqual(urlRequest.url?.query ?? "", "foo=1", "query is incorrect")
  129. } catch {
  130. XCTFail("Test encountered unexpected error: \(error)")
  131. }
  132. }
  133. func testURLParameterEncodeStringKeyArrayValueParameter() {
  134. do {
  135. // Given
  136. let parameters = ["foo": ["a", 1, true]]
  137. // When
  138. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  139. // Then
  140. XCTAssertEqual(urlRequest.url?.query ?? "", "foo%5B%5D=a&foo%5B%5D=1&foo%5B%5D=1", "query is incorrect")
  141. } catch {
  142. XCTFail("Test encountered unexpected error: \(error)")
  143. }
  144. }
  145. func testURLParameterEncodeStringKeyDictionaryValueParameter() {
  146. do {
  147. // Given
  148. let parameters = ["foo": ["bar": 1]]
  149. // When
  150. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  151. // Then
  152. XCTAssertEqual(urlRequest.url?.query ?? "", "foo%5Bbar%5D=1", "query is incorrect")
  153. } catch {
  154. XCTFail("Test encountered unexpected error: \(error)")
  155. }
  156. }
  157. func testURLParameterEncodeStringKeyNestedDictionaryValueParameter() {
  158. do {
  159. // Given
  160. let parameters = ["foo": ["bar": ["baz": 1]]]
  161. // When
  162. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  163. // Then
  164. XCTAssertEqual(urlRequest.url?.query ?? "", "foo%5Bbar%5D%5Bbaz%5D=1", "query is incorrect")
  165. } catch {
  166. XCTFail("Test encountered unexpected error: \(error)")
  167. }
  168. }
  169. func testURLParameterEncodeStringKeyNestedDictionaryArrayValueParameter() {
  170. do {
  171. // Given
  172. let parameters = ["foo": ["bar": ["baz": ["a", 1, true]]]]
  173. // When
  174. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  175. // Then
  176. let expectedQuery = "foo%5Bbar%5D%5Bbaz%5D%5B%5D=a&foo%5Bbar%5D%5Bbaz%5D%5B%5D=1&foo%5Bbar%5D%5Bbaz%5D%5B%5D=1"
  177. XCTAssertEqual(urlRequest.url?.query ?? "", expectedQuery, "query is incorrect")
  178. } catch {
  179. XCTFail("Test encountered unexpected error: \(error)")
  180. }
  181. }
  182. // MARK: Tests - All Reserved / Unreserved / Illegal Characters According to RFC 3986
  183. func testThatReservedCharactersArePercentEscapedMinusQuestionMarkAndForwardSlash() {
  184. do {
  185. // Given
  186. let generalDelimiters = ":#[]@"
  187. let subDelimiters = "!$&'()*+,;="
  188. let parameters = ["reserved": "\(generalDelimiters)\(subDelimiters)"]
  189. // When
  190. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  191. // Then
  192. let expectedQuery = "reserved=%3A%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D"
  193. XCTAssertEqual(urlRequest.url?.query ?? "", expectedQuery, "query is incorrect")
  194. } catch {
  195. XCTFail("Test encountered unexpected error: \(error)")
  196. }
  197. }
  198. func testThatReservedCharactersQuestionMarkAndForwardSlashAreNotPercentEscaped() {
  199. do {
  200. // Given
  201. let parameters = ["reserved": "?/"]
  202. // When
  203. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  204. // Then
  205. XCTAssertEqual(urlRequest.url?.query ?? "", "reserved=?/", "query is incorrect")
  206. } catch {
  207. XCTFail("Test encountered unexpected error: \(error)")
  208. }
  209. }
  210. func testThatUnreservedNumericCharactersAreNotPercentEscaped() {
  211. do {
  212. // Given
  213. let parameters = ["numbers": "0123456789"]
  214. // When
  215. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  216. // Then
  217. XCTAssertEqual(urlRequest.url?.query ?? "", "numbers=0123456789", "query is incorrect")
  218. } catch {
  219. XCTFail("Test encountered unexpected error: \(error)")
  220. }
  221. }
  222. func testThatUnreservedLowercaseCharactersAreNotPercentEscaped() {
  223. do {
  224. // Given
  225. let parameters = ["lowercase": "abcdefghijklmnopqrstuvwxyz"]
  226. // When
  227. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  228. // Then
  229. XCTAssertEqual(urlRequest.url?.query ?? "", "lowercase=abcdefghijklmnopqrstuvwxyz", "query is incorrect")
  230. } catch {
  231. XCTFail("Test encountered unexpected error: \(error)")
  232. }
  233. }
  234. func testThatUnreservedUppercaseCharactersAreNotPercentEscaped() {
  235. do {
  236. // Given
  237. let parameters = ["uppercase": "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
  238. // When
  239. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  240. // Then
  241. XCTAssertEqual(urlRequest.url?.query ?? "", "uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ", "query is incorrect")
  242. } catch {
  243. XCTFail("Test encountered unexpected error: \(error)")
  244. }
  245. }
  246. func testThatIllegalASCIICharactersArePercentEscaped() {
  247. do {
  248. // Given
  249. let parameters = ["illegal": " \"#%<>[]\\^`{}|"]
  250. // When
  251. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  252. // Then
  253. let expectedQuery = "illegal=%20%22%23%25%3C%3E%5B%5D%5C%5E%60%7B%7D%7C"
  254. XCTAssertEqual(urlRequest.url?.query ?? "", expectedQuery, "query is incorrect")
  255. } catch {
  256. XCTFail("Test encountered unexpected error: \(error)")
  257. }
  258. }
  259. // MARK: Tests - Special Character Queries
  260. func testURLParameterEncodeStringWithAmpersandKeyStringWithAmpersandValueParameter() {
  261. do {
  262. // Given
  263. let parameters = ["foo&bar": "baz&qux", "foobar": "bazqux"]
  264. // When
  265. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  266. // Then
  267. XCTAssertEqual(urlRequest.url?.query ?? "", "foo%26bar=baz%26qux&foobar=bazqux", "query is incorrect")
  268. } catch {
  269. XCTFail("Test encountered unexpected error: \(error)")
  270. }
  271. }
  272. func testURLParameterEncodeStringWithQuestionMarkKeyStringWithQuestionMarkValueParameter() {
  273. do {
  274. // Given
  275. let parameters = ["?foo?": "?bar?"]
  276. // When
  277. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  278. // Then
  279. XCTAssertEqual(urlRequest.url?.query ?? "", "?foo?=?bar?", "query is incorrect")
  280. } catch {
  281. XCTFail("Test encountered unexpected error: \(error)")
  282. }
  283. }
  284. func testURLParameterEncodeStringWithSlashKeyStringWithQuestionMarkValueParameter() {
  285. do {
  286. // Given
  287. let parameters = ["foo": "/bar/baz/qux"]
  288. // When
  289. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  290. // Then
  291. XCTAssertEqual(urlRequest.url?.query ?? "", "foo=/bar/baz/qux", "query is incorrect")
  292. } catch {
  293. XCTFail("Test encountered unexpected error: \(error)")
  294. }
  295. }
  296. func testURLParameterEncodeStringWithSpaceKeyStringWithSpaceValueParameter() {
  297. do {
  298. // Given
  299. let parameters = [" foo ": " bar "]
  300. // When
  301. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  302. // Then
  303. XCTAssertEqual(urlRequest.url?.query ?? "", "%20foo%20=%20bar%20", "query is incorrect")
  304. } catch {
  305. XCTFail("Test encountered unexpected error: \(error)")
  306. }
  307. }
  308. func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameter() {
  309. do {
  310. // Given
  311. let parameters = ["+foo+": "+bar+"]
  312. // When
  313. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  314. // Then
  315. XCTAssertEqual(urlRequest.url?.query ?? "", "%2Bfoo%2B=%2Bbar%2B", "query is incorrect")
  316. } catch {
  317. XCTFail("Test encountered unexpected error: \(error)")
  318. }
  319. }
  320. func testURLParameterEncodeStringKeyPercentEncodedStringValueParameter() {
  321. do {
  322. // Given
  323. let parameters = ["percent": "%25"]
  324. // When
  325. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  326. // Then
  327. XCTAssertEqual(urlRequest.url?.query ?? "", "percent=%2525", "query is incorrect")
  328. } catch {
  329. XCTFail("Test encountered unexpected error: \(error)")
  330. }
  331. }
  332. func testURLParameterEncodeStringKeyNonLatinStringValueParameter() {
  333. do {
  334. // Given
  335. let parameters = [
  336. "french": "français",
  337. "japanese": "日本語",
  338. "arabic": "العربية",
  339. "emoji": "😃"
  340. ]
  341. // When
  342. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  343. // Then
  344. let expectedParameterValues = [
  345. "arabic=%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9",
  346. "emoji=%F0%9F%98%83",
  347. "french=fran%C3%A7ais",
  348. "japanese=%E6%97%A5%E6%9C%AC%E8%AA%9E"
  349. ]
  350. let expectedQuery = expectedParameterValues.joined(separator: "&")
  351. XCTAssertEqual(urlRequest.url?.query ?? "", expectedQuery, "query is incorrect")
  352. } catch {
  353. XCTFail("Test encountered unexpected error: \(error)")
  354. }
  355. }
  356. func testURLParameterEncodeStringForRequestWithPrecomposedQuery() {
  357. do {
  358. // Given
  359. let url = URL(string: "https://example.com/movies?hd=[1]")!
  360. let parameters = ["page": "0"]
  361. // When
  362. let urlRequest = try encoding.encode(URLRequest(url: url), with: parameters)
  363. // Then
  364. XCTAssertEqual(urlRequest.url?.query ?? "", "hd=%5B1%5D&page=0", "query is incorrect")
  365. } catch {
  366. XCTFail("Test encountered unexpected error: \(error)")
  367. }
  368. }
  369. func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameterForRequestWithPrecomposedQuery() {
  370. do {
  371. // Given
  372. let url = URL(string: "https://example.com/movie?hd=[1]")!
  373. let parameters = ["+foo+": "+bar+"]
  374. // When
  375. let urlRequest = try encoding.encode(URLRequest(url: url), with: parameters)
  376. // Then
  377. XCTAssertEqual(urlRequest.url?.query ?? "", "hd=%5B1%5D&%2Bfoo%2B=%2Bbar%2B", "query is incorrect")
  378. } catch {
  379. XCTFail("Test encountered unexpected error: \(error)")
  380. }
  381. }
  382. func testURLParameterEncodeStringWithThousandsOfChineseCharacters() {
  383. do {
  384. // Given
  385. let repeatedCount = 2_000
  386. let url = URL(string: "https://example.com/movies")!
  387. let parameters = ["chinese": String(count: repeatedCount, repeatedString: "一二三四五六七八九十")]
  388. // When
  389. let urlRequest = try encoding.encode(URLRequest(url: url), with: parameters)
  390. // Then
  391. var expected = "chinese="
  392. for _ in 0..<repeatedCount {
  393. expected += "%E4%B8%80%E4%BA%8C%E4%B8%89%E5%9B%9B%E4%BA%94%E5%85%AD%E4%B8%83%E5%85%AB%E4%B9%9D%E5%8D%81"
  394. }
  395. XCTAssertEqual(urlRequest.url?.query ?? "", expected, "query is incorrect")
  396. } catch {
  397. XCTFail("Test encountered unexpected error: \(error)")
  398. }
  399. }
  400. // MARK: Tests - Varying HTTP Methods
  401. func testThatURLParameterEncodingEncodesGETParametersInURL() {
  402. do {
  403. // Given
  404. var mutableURLRequest = self.urlRequest.urlRequest
  405. mutableURLRequest.httpMethod = HTTPMethod.get.rawValue
  406. let parameters = ["foo": 1, "bar": 2]
  407. // When
  408. let urlRequest = try encoding.encode(mutableURLRequest, with: parameters)
  409. // Then
  410. XCTAssertEqual(urlRequest.url?.query ?? "", "bar=2&foo=1", "query is incorrect")
  411. XCTAssertNil(urlRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should be nil")
  412. XCTAssertNil(urlRequest.httpBody, "HTTPBody should be nil")
  413. } catch {
  414. XCTFail("Test encountered unexpected error: \(error)")
  415. }
  416. }
  417. func testThatURLParameterEncodingEncodesPOSTParametersInHTTPBody() {
  418. do {
  419. // Given
  420. var mutableURLRequest = self.urlRequest.urlRequest
  421. mutableURLRequest.httpMethod = HTTPMethod.post.rawValue
  422. let parameters = ["foo": 1, "bar": 2]
  423. // When
  424. let urlRequest = try encoding.encode(mutableURLRequest, with: parameters)
  425. // Then
  426. XCTAssertEqual(urlRequest.value(forHTTPHeaderField: "Content-Type"), "application/x-www-form-urlencoded; charset=utf-8")
  427. XCTAssertNotNil(urlRequest.httpBody, "HTTPBody should not be nil")
  428. if
  429. let httpBody = urlRequest.httpBody,
  430. let decodedHTTPBody = String(data: httpBody, encoding: String.Encoding.utf8)
  431. {
  432. XCTAssertEqual(decodedHTTPBody, "bar=2&foo=1", "HTTPBody is incorrect")
  433. } else {
  434. XCTFail("decoded http body should not be nil")
  435. }
  436. } catch {
  437. XCTFail("Test encountered unexpected error: \(error)")
  438. }
  439. }
  440. func testThatURLEncodedInURLParameterEncodingEncodesPOSTParametersInURL() {
  441. do {
  442. // Given
  443. var mutableURLRequest = self.urlRequest.urlRequest
  444. mutableURLRequest.httpMethod = HTTPMethod.post.rawValue
  445. let parameters = ["foo": 1, "bar": 2]
  446. // When
  447. let urlRequest = try ParameterEncoding.urlEncodedInURL.encode(mutableURLRequest, with: parameters)
  448. // Then
  449. XCTAssertEqual(urlRequest.url?.query ?? "", "bar=2&foo=1", "query is incorrect")
  450. XCTAssertNil(urlRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should be nil")
  451. XCTAssertNil(urlRequest.httpBody, "HTTPBody should be nil")
  452. } catch {
  453. XCTFail("Test encountered unexpected error: \(error)")
  454. }
  455. }
  456. }
  457. // MARK: -
  458. class JSONParameterEncodingTestCase: ParameterEncodingTestCase {
  459. // MARK: Properties
  460. let encoding: ParameterEncoding = .json
  461. // MARK: Tests
  462. func testJSONParameterEncodeNilParameters() {
  463. do {
  464. // Given, When
  465. let URLRequest = try encoding.encode(self.urlRequest, with: nil)
  466. // Then
  467. XCTAssertNil(URLRequest.url?.query, "query should be nil")
  468. XCTAssertNil(URLRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should be nil")
  469. XCTAssertNil(URLRequest.httpBody, "HTTPBody should be nil")
  470. } catch {
  471. XCTFail("Test encountered unexpected error: \(error)")
  472. }
  473. }
  474. func testJSONParameterEncodeComplexParameters() {
  475. do {
  476. // Given
  477. let parameters: [String: Any] = [
  478. "foo": "bar",
  479. "baz": ["a", 1, true],
  480. "qux": [
  481. "a": 1,
  482. "b": [2, 2],
  483. "c": [3, 3, 3]
  484. ]
  485. ]
  486. // When
  487. let URLRequest = try encoding.encode(self.urlRequest, with: parameters)
  488. // Then
  489. XCTAssertNil(URLRequest.url?.query, "query should be nil")
  490. XCTAssertNotNil(URLRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should not be nil")
  491. XCTAssertEqual(
  492. URLRequest.value(forHTTPHeaderField: "Content-Type") ?? "",
  493. "application/json",
  494. "Content-Type should be application/json"
  495. )
  496. XCTAssertNotNil(URLRequest.httpBody, "HTTPBody should not be nil")
  497. if let HTTPBody = URLRequest.httpBody {
  498. do {
  499. let JSON = try JSONSerialization.jsonObject(with: HTTPBody, options: .allowFragments)
  500. if let JSON = JSON as? NSObject {
  501. XCTAssertEqual(JSON, parameters as NSObject, "HTTPBody JSON does not equal parameters")
  502. } else {
  503. XCTFail("JSON should be an NSObject")
  504. }
  505. } catch {
  506. XCTFail("JSON should not be nil")
  507. }
  508. } else {
  509. XCTFail("JSON should not be nil")
  510. }
  511. } catch {
  512. XCTFail("Test encountered unexpected error: \(error)")
  513. }
  514. }
  515. func testJSONParameterEncodeParametersRetainsCustomContentType() {
  516. do {
  517. // Given
  518. var mutableURLRequest = URLRequest(url: URL(string: "https://example.com/")!)
  519. mutableURLRequest.setValue("application/custom-json-type+json", forHTTPHeaderField: "Content-Type")
  520. let parameters = ["foo": "bar"]
  521. // When
  522. let urlRequest = try encoding.encode(mutableURLRequest, with: parameters)
  523. // Then
  524. XCTAssertNil(urlRequest.url?.query)
  525. XCTAssertEqual(urlRequest.value(forHTTPHeaderField: "Content-Type"), "application/custom-json-type+json")
  526. } catch {
  527. XCTFail("Test encountered unexpected error: \(error)")
  528. }
  529. }
  530. }
  531. // MARK: -
  532. class PropertyListParameterEncodingTestCase: ParameterEncodingTestCase {
  533. // MARK: Properties
  534. let encoding: ParameterEncoding = .propertyList(.xml, 0)
  535. // MARK: Tests
  536. func testPropertyListParameterEncodeNilParameters() {
  537. do {
  538. // Given, When
  539. let urlRequest = try encoding.encode(self.urlRequest, with: nil)
  540. // Then
  541. XCTAssertNil(urlRequest.url?.query, "query should be nil")
  542. XCTAssertNil(urlRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should be nil")
  543. XCTAssertNil(urlRequest.httpBody, "HTTPBody should be nil")
  544. } catch {
  545. XCTFail("Test encountered unexpected error: \(error)")
  546. }
  547. }
  548. func testPropertyListParameterEncodeComplexParameters() {
  549. do {
  550. // Given
  551. let parameters: [String: Any] = [
  552. "foo": "bar",
  553. "baz": ["a", 1, true],
  554. "qux": [
  555. "a": 1,
  556. "b": [2, 2],
  557. "c": [3, 3, 3]
  558. ]
  559. ]
  560. // When
  561. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  562. // Then
  563. XCTAssertNil(urlRequest.url?.query, "query should be nil")
  564. XCTAssertNotNil(urlRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should not be nil")
  565. XCTAssertEqual(
  566. urlRequest.value(forHTTPHeaderField: "Content-Type") ?? "",
  567. "application/x-plist",
  568. "Content-Type should be application/x-plist"
  569. )
  570. XCTAssertNotNil(urlRequest.httpBody, "HTTPBody should not be nil")
  571. if let HTTPBody = urlRequest.httpBody {
  572. do {
  573. let plist = try PropertyListSerialization.propertyList(
  574. from: HTTPBody,
  575. options: PropertyListSerialization.MutabilityOptions(),
  576. format: nil
  577. )
  578. if let plist = plist as? NSObject {
  579. XCTAssertEqual(plist, parameters as NSObject, "HTTPBody plist does not equal parameters")
  580. } else {
  581. XCTFail("plist should be an NSObject")
  582. }
  583. } catch {
  584. XCTFail("plist should not be nil")
  585. }
  586. }
  587. } catch {
  588. XCTFail("Test encountered unexpected error: \(error)")
  589. }
  590. }
  591. func testPropertyListParameterEncodeDateAndDataParameters() {
  592. do {
  593. // Given
  594. let date: Date = Date()
  595. let data: Data = "data".data(using: String.Encoding.utf8, allowLossyConversion: false)!
  596. let parameters: [String: Any] = [
  597. "date": date,
  598. "data": data
  599. ]
  600. // When
  601. let urlRequest = try encoding.encode(self.urlRequest, with: parameters)
  602. // Then
  603. XCTAssertNil(urlRequest.url?.query, "query should be nil")
  604. XCTAssertNotNil(urlRequest.value(forHTTPHeaderField: "Content-Type"), "Content-Type should not be nil")
  605. XCTAssertEqual(
  606. urlRequest.value(forHTTPHeaderField: "Content-Type") ?? "",
  607. "application/x-plist",
  608. "Content-Type should be application/x-plist"
  609. )
  610. XCTAssertNotNil(urlRequest.httpBody, "HTTPBody should not be nil")
  611. if let HTTPBody = urlRequest.httpBody {
  612. do {
  613. let plist = try PropertyListSerialization.propertyList(
  614. from: HTTPBody,
  615. options: PropertyListSerialization.MutabilityOptions(),
  616. format: nil
  617. ) as AnyObject
  618. XCTAssertTrue(plist.value(forKey: "date") is Date, "date is not Date")
  619. XCTAssertTrue(plist.value(forKey: "data") is Data, "data is not Data")
  620. } catch {
  621. XCTFail("plist should not be nil")
  622. }
  623. } else {
  624. XCTFail("HTTPBody should not be nil")
  625. }
  626. } catch {
  627. XCTFail("Test encountered unexpected error: \(error)")
  628. }
  629. }
  630. func testPropertyListParameterEncodeParametersRetainsCustomContentType() {
  631. do {
  632. // Given
  633. var mutableURLRequest = URLRequest(url: URL(string: "https://example.com/")!)
  634. mutableURLRequest.setValue("application/custom-plist-type+plist", forHTTPHeaderField: "Content-Type")
  635. let parameters = ["foo": "bar"]
  636. // When
  637. let urlRequest = try encoding.encode(mutableURLRequest, with: parameters)
  638. // Then
  639. XCTAssertNil(urlRequest.url?.query)
  640. XCTAssertEqual(urlRequest.value(forHTTPHeaderField: "Content-Type"), "application/custom-plist-type+plist")
  641. } catch {
  642. XCTFail("Test encountered unexpected error: \(error)")
  643. }
  644. }
  645. }
  646. // MARK: -
  647. class CustomParameterEncodingTestCase: ParameterEncodingTestCase {
  648. // MARK: Tests
  649. func testCustomParameterEncode() {
  650. do {
  651. // Given
  652. let encodingClosure: (URLRequestConvertible, [String: Any]?) throws -> URLRequest = { urlRequest, parameters in
  653. guard let parameters = parameters else { return urlRequest.urlRequest }
  654. var urlString = urlRequest.urlRequest.urlString + "?"
  655. parameters.forEach { urlString += "\($0)=\($1)" }
  656. var mutableURLRequest = urlRequest.urlRequest
  657. mutableURLRequest.url = URL(string: urlString)!
  658. return mutableURLRequest
  659. }
  660. // When
  661. let encoding: ParameterEncoding = .custom(encodingClosure)
  662. // Then
  663. let url = URL(string: "https://example.com")!
  664. let urlRequest = URLRequest(url: url)
  665. let parameters = ["foo": "bar"]
  666. let result = try encoding.encode(urlRequest, with: parameters)
  667. XCTAssertEqual(result.urlString, "https://example.com?foo=bar")
  668. } catch {
  669. XCTFail("Test encountered unexpected error: \(error)")
  670. }
  671. }
  672. }