ParameterEncodingTests.swift 25 KB

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