ParameterEncodingTests.swift 27 KB

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