ParameterEncoderTests.swift 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. //
  2. // ParameterEncoderTests.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 XCTest
  26. final class JSONParameterEncoderTests: BaseTestCase {
  27. func testThatDataIsProperlyEncodedAndProperContentTypeIsSet() throws {
  28. // Given
  29. let encoder = JSONParameterEncoder()
  30. let request = URLRequest.makeHTTPBinRequest()
  31. // When
  32. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  33. // Then
  34. XCTAssertEqual(newRequest.headers["Content-Type"], "application/json")
  35. XCTAssertEqual(newRequest.httpBody?.asString, "{\"property\":\"property\"}")
  36. }
  37. func testThatDataIsProperlyEncodedButContentTypeIsNotSetIfRequestAlreadyHasAContentType() throws {
  38. // Given
  39. let encoder = JSONParameterEncoder()
  40. var request = URLRequest.makeHTTPBinRequest()
  41. request.headers.update(.contentType("type"))
  42. // When
  43. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  44. // Then
  45. XCTAssertEqual(newRequest.headers["Content-Type"], "type")
  46. XCTAssertEqual(newRequest.httpBody?.asString, "{\"property\":\"property\"}")
  47. }
  48. func testThatJSONEncoderCanBeCustomized() throws {
  49. // Given
  50. let jsonEncoder = JSONEncoder()
  51. jsonEncoder.outputFormatting = .prettyPrinted
  52. let encoder = JSONParameterEncoder(encoder: jsonEncoder)
  53. let request = URLRequest.makeHTTPBinRequest()
  54. // When
  55. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  56. // Then
  57. let expected = """
  58. {
  59. "property" : "property"
  60. }
  61. """
  62. XCTAssertEqual(newRequest.httpBody?.asString, expected)
  63. }
  64. func testThatJSONEncoderDefaultWorks() throws {
  65. // Given
  66. let encoder = JSONParameterEncoder.default
  67. let request = URLRequest.makeHTTPBinRequest()
  68. // When
  69. let encoded = try encoder.encode(HTTPBinParameters.default, into: request)
  70. // Then
  71. let expected = """
  72. {"property":"property"}
  73. """
  74. XCTAssertEqual(encoded.httpBody?.asString, expected)
  75. }
  76. func testThatJSONEncoderPrettyPrintedPrintsPretty() throws {
  77. // Given
  78. let encoder = JSONParameterEncoder.prettyPrinted
  79. let request = URLRequest.makeHTTPBinRequest()
  80. // When
  81. let encoded = try encoder.encode(HTTPBinParameters.default, into: request)
  82. // Then
  83. let expected = """
  84. {
  85. "property" : "property"
  86. }
  87. """
  88. XCTAssertEqual(encoded.httpBody?.asString, expected)
  89. }
  90. }
  91. final class SortedKeysJSONParameterEncoderTests: BaseTestCase {
  92. func testTestJSONEncoderSortedKeysHasSortedKeys() throws {
  93. guard #available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) else { return }
  94. // Given
  95. let encoder = JSONParameterEncoder.sortedKeys
  96. let request = URLRequest.makeHTTPBinRequest()
  97. // When
  98. let encoded = try encoder.encode(["z": "z", "a": "a", "p": "p"], into: request)
  99. // Then
  100. let expected = """
  101. {"a":"a","p":"p","z":"z"}
  102. """
  103. XCTAssertEqual(encoded.httpBody?.asString, expected)
  104. }
  105. }
  106. final class URLEncodedFormParameterEncoderTests: BaseTestCase {
  107. func testThatQueryIsBodyEncodedAndProperContentTypeIsSetForPOSTRequest() throws {
  108. // Given
  109. let encoder = URLEncodedFormParameterEncoder()
  110. let request = URLRequest.makeHTTPBinRequest(method: .post)
  111. // When
  112. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  113. // Then
  114. XCTAssertEqual(newRequest.headers["Content-Type"], "application/x-www-form-urlencoded; charset=utf-8")
  115. XCTAssertEqual(newRequest.httpBody?.asString, "property=property")
  116. }
  117. func testThatQueryIsBodyEncodedButContentTypeIsNotSetWhenRequestAlreadyHasContentType() throws {
  118. // Given
  119. let encoder = URLEncodedFormParameterEncoder()
  120. var request = URLRequest.makeHTTPBinRequest(method: .post)
  121. request.headers.update(.contentType("type"))
  122. // When
  123. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  124. // Then
  125. XCTAssertEqual(newRequest.headers["Content-Type"], "type")
  126. XCTAssertEqual(newRequest.httpBody?.asString, "property=property")
  127. }
  128. func testThatEncoderCanBeCustomized() throws {
  129. // Given
  130. let urlEncoder = URLEncodedFormEncoder(boolEncoding: .literal)
  131. let encoder = URLEncodedFormParameterEncoder(encoder: urlEncoder)
  132. let request = URLRequest.makeHTTPBinRequest()
  133. // When
  134. let newRequest = try encoder.encode(["bool": true], into: request)
  135. // Then
  136. let components = URLComponents(url: newRequest.url!, resolvingAgainstBaseURL: false)
  137. XCTAssertEqual(components?.percentEncodedQuery, "bool=true")
  138. }
  139. func testThatQueryIsInURLWhenDestinationIsURLAndMethodIsPOST() throws {
  140. // Given
  141. let encoder = URLEncodedFormParameterEncoder(destination: .queryString)
  142. let request = URLRequest.makeHTTPBinRequest(method: .post)
  143. // When
  144. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  145. // Then
  146. let components = URLComponents(url: newRequest.url!, resolvingAgainstBaseURL: false)
  147. XCTAssertEqual(components?.percentEncodedQuery, "property=property")
  148. }
  149. }
  150. final class URLEncodedFormEncoderTests: BaseTestCase {
  151. func testEncoderThrowsErrorWhenAttemptingToEncodeNilInKeyedContainer() {
  152. // Given
  153. let encoder = URLEncodedFormEncoder()
  154. let parameters = FailingOptionalStruct(testedContainer: .keyed)
  155. // When
  156. let result = AFResult<String> { try encoder.encode(parameters) }
  157. // Then
  158. XCTAssertTrue(result.isFailure)
  159. }
  160. func testEncoderThrowsErrorWhenAttemptingToEncodeNilInUnkeyedContainer() {
  161. // Given
  162. let encoder = URLEncodedFormEncoder()
  163. let parameters = FailingOptionalStruct(testedContainer: .unkeyed)
  164. // When
  165. let result = AFResult<String> { try encoder.encode(parameters) }
  166. // Then
  167. XCTAssertTrue(result.isFailure)
  168. }
  169. func testEncoderCanEncodeDictionary() {
  170. // Given
  171. let encoder = URLEncodedFormEncoder()
  172. let parameters = ["a": "a"]
  173. // When
  174. let result = AFResult<String> { try encoder.encode(parameters) }
  175. // Then
  176. XCTAssertEqual(result.value, "a=a")
  177. }
  178. func testEncoderCanEncodeDouble() {
  179. // Given
  180. let encoder = URLEncodedFormEncoder()
  181. let parameters = ["a": 1.0]
  182. // When
  183. let result = AFResult<String> { try encoder.encode(parameters) }
  184. // Then
  185. XCTAssertEqual(result.value, "a=1.0")
  186. }
  187. func testEncoderCanEncodeFloat() {
  188. // Given
  189. let encoder = URLEncodedFormEncoder()
  190. let parameters: [String: Float] = ["a": 1.0]
  191. // When
  192. let result = AFResult<String> { try encoder.encode(parameters) }
  193. // Then
  194. XCTAssertEqual(result.value, "a=1.0")
  195. }
  196. func testEncoderCanEncodeInt8() {
  197. // Given
  198. let encoder = URLEncodedFormEncoder()
  199. let parameters: [String: Int8] = ["a": 1]
  200. // When
  201. let result = AFResult<String> { try encoder.encode(parameters) }
  202. // Then
  203. XCTAssertEqual(result.value, "a=1")
  204. }
  205. func testEncoderCanEncodeInt16() {
  206. // Given
  207. let encoder = URLEncodedFormEncoder()
  208. let parameters: [String: Int16] = ["a": 1]
  209. // When
  210. let result = AFResult<String> { try encoder.encode(parameters) }
  211. // Then
  212. XCTAssertEqual(result.value, "a=1")
  213. }
  214. func testEncoderCanEncodeInt32() {
  215. // Given
  216. let encoder = URLEncodedFormEncoder()
  217. let parameters: [String: Int32] = ["a": 1]
  218. // When
  219. let result = AFResult<String> { try encoder.encode(parameters) }
  220. // Then
  221. XCTAssertEqual(result.value, "a=1")
  222. }
  223. func testEncoderCanEncodeInt64() {
  224. // Given
  225. let encoder = URLEncodedFormEncoder()
  226. let parameters: [String: Int64] = ["a": 1]
  227. // When
  228. let result = AFResult<String> { try encoder.encode(parameters) }
  229. // Then
  230. XCTAssertEqual(result.value, "a=1")
  231. }
  232. func testEncoderCanEncodeUInt() {
  233. // Given
  234. let encoder = URLEncodedFormEncoder()
  235. let parameters: [String: UInt] = ["a": 1]
  236. // When
  237. let result = AFResult<String> { try encoder.encode(parameters) }
  238. // Then
  239. XCTAssertEqual(result.value, "a=1")
  240. }
  241. func testEncoderCanEncodeUInt8() {
  242. // Given
  243. let encoder = URLEncodedFormEncoder()
  244. let parameters: [String: UInt8] = ["a": 1]
  245. // When
  246. let result = AFResult<String> { try encoder.encode(parameters) }
  247. // Then
  248. XCTAssertEqual(result.value, "a=1")
  249. }
  250. func testEncoderCanEncodeUInt16() {
  251. // Given
  252. let encoder = URLEncodedFormEncoder()
  253. let parameters: [String: UInt16] = ["a": 1]
  254. // When
  255. let result = AFResult<String> { try encoder.encode(parameters) }
  256. // Then
  257. XCTAssertEqual(result.value, "a=1")
  258. }
  259. func testEncoderCanEncodeUInt32() {
  260. // Given
  261. let encoder = URLEncodedFormEncoder()
  262. let parameters: [String: UInt32] = ["a": 1]
  263. // When
  264. let result = AFResult<String> { try encoder.encode(parameters) }
  265. // Then
  266. XCTAssertEqual(result.value, "a=1")
  267. }
  268. func testEncoderCanEncodeUInt64() {
  269. // Given
  270. let encoder = URLEncodedFormEncoder()
  271. let parameters: [String: UInt64] = ["a": 1]
  272. // When
  273. let result = AFResult<String> { try encoder.encode(parameters) }
  274. // Then
  275. XCTAssertEqual(result.value, "a=1")
  276. }
  277. func testThatNestedDictionariesHaveBracketedKeys() {
  278. // Given
  279. let encoder = URLEncodedFormEncoder()
  280. let parameters = ["a": ["b": "b"]]
  281. // When
  282. let result = AFResult<String> { try encoder.encode(parameters) }
  283. // Then
  284. XCTAssertEqual(result.value, "a%5Bb%5D=b")
  285. }
  286. func testThatEncodableStructCanBeEncoded() {
  287. // Given
  288. let encoder = URLEncodedFormEncoder()
  289. let parameters = EncodableStruct()
  290. // When
  291. let result = AFResult<String> { try encoder.encode(parameters) }
  292. // Then
  293. let expected = "four%5B%5D=1&four%5B%5D=2&four%5B%5D=3&three=1&one=one&two=2&five%5Ba%5D=a&six%5Ba%5D%5Bb%5D=b&seven%5Ba%5D=a"
  294. XCTAssertQueryEqual(result.value, expected)
  295. }
  296. func testThatManuallyEncodableStructCanBeEncoded() {
  297. // Given
  298. let encoder = URLEncodedFormEncoder()
  299. let parameters = ManuallyEncodableStruct()
  300. // When
  301. let result = AFResult<String> { try encoder.encode(parameters) }
  302. // Then
  303. let expected = "root%5B%5D%5B%5D=1&root%5B%5D%5B%5D=2&root%5B%5D%5B%5D=3&root%5B%5D%5Ba%5D%5Bstring%5D=string&root%5B%5D%5B%5D%5B%5D=1&root%5B%5D%5B%5D%5B%5D=2&root%5B%5D%5B%5D%5B%5D=3"
  304. XCTAssertQueryEqual(result.value, expected)
  305. }
  306. func testThatEncodableClassWithNoInheritanceCanBeEncoded() {
  307. // Given
  308. let encoder = URLEncodedFormEncoder()
  309. let parameters = EncodableSuperclass()
  310. // When
  311. let result = AFResult<String> { try encoder.encode(parameters) }
  312. // Then
  313. XCTAssertQueryEqual(result.value, "two=2&one=one&three=1")
  314. }
  315. func testThatEncodableSubclassCanBeEncoded() {
  316. // Given
  317. let encoder = URLEncodedFormEncoder()
  318. let parameters = EncodableSubclass()
  319. // When
  320. let result = AFResult<String> { try encoder.encode(parameters) }
  321. // Then
  322. let expected = "four%5B%5D=1&four%5B%5D=2&four%5B%5D=3&two=2&five%5Ba%5D=a&five%5Bb%5D=b&three=1&one=one"
  323. XCTAssertQueryEqual(result.value, expected)
  324. }
  325. func testThatManuallyEncodableSubclassCanBeEncoded() {
  326. // Given
  327. let encoder = URLEncodedFormEncoder()
  328. let parameters = ManuallyEncodableSubclass()
  329. // When
  330. let result = AFResult<String> { try encoder.encode(parameters) }
  331. // Then
  332. let expected = "five%5Ba%5D=a&five%5Bb%5D=b&four%5Bfour%5D=one&four%5Bfive%5D=2"
  333. XCTAssertQueryEqual(result.value, expected)
  334. }
  335. func testThatARootArrayCannotBeEncoded() {
  336. // Given
  337. let encoder = URLEncodedFormEncoder()
  338. let parameters = [1]
  339. // When
  340. let result = AFResult<String> { try encoder.encode(parameters) }
  341. // Then
  342. XCTAssertFalse(result.isSuccess)
  343. }
  344. func testThatARootValueCannotBeEncoded() {
  345. // Given
  346. let encoder = URLEncodedFormEncoder()
  347. let parameters = "string"
  348. // When
  349. let result = AFResult<String> { try encoder.encode(parameters) }
  350. // Then
  351. XCTAssertFalse(result.isSuccess)
  352. }
  353. func testThatOptionalValuesCannotBeEncoded() {
  354. // Givenp
  355. let encoder = URLEncodedFormEncoder()
  356. let parameters: [String: String?] = ["string": nil]
  357. // When
  358. let result = AFResult<String> { try encoder.encode(parameters) }
  359. // Then
  360. XCTAssertFalse(result.isSuccess)
  361. }
  362. func testThatBoolsCanBeLiteralEncoded() {
  363. // Given
  364. let encoder = URLEncodedFormEncoder(boolEncoding: .literal)
  365. let parameters = ["bool": true]
  366. // When
  367. let result = AFResult<String> { try encoder.encode(parameters) }
  368. // Then
  369. XCTAssertEqual(result.value, "bool=true")
  370. }
  371. func testThatArraysCanBeEncodedWithoutBrackets() {
  372. // Given
  373. let encoder = URLEncodedFormEncoder(arrayEncoding: .noBrackets)
  374. let parameters = ["array": [1, 2]]
  375. // When
  376. let result = AFResult<String> { try encoder.encode(parameters) }
  377. // Then
  378. XCTAssertQueryEqual(result.value, "array=1&array=2")
  379. }
  380. func testThatSpacesCanBeEncodedAsPluses() {
  381. // Given
  382. let encoder = URLEncodedFormEncoder(spaceEncoding: .plusReplaced)
  383. let parameters = ["spaces": "replace with spaces"]
  384. // When
  385. let result = AFResult<String> { try encoder.encode(parameters) }
  386. // Then
  387. XCTAssertEqual(result.value, "spaces=replace+with+spaces")
  388. }
  389. func testThatEscapedCharactersCanBeCustomized() {
  390. // Given
  391. var allowed = CharacterSet.afURLQueryAllowed
  392. allowed.remove(charactersIn: "?/")
  393. let encoder = URLEncodedFormEncoder(allowedCharacters: allowed)
  394. let parameters = ["allowed": "?/"]
  395. // When
  396. let result = AFResult<String> { try encoder.encode(parameters) }
  397. // Then
  398. XCTAssertEqual(result.value, "allowed=%3F%2F")
  399. }
  400. func testThatUnreservedCharactersAreNotPercentEscaped() {
  401. // Given
  402. let encoder = URLEncodedFormEncoder()
  403. let parameters = ["lowercase": "abcdefghijklmnopqrstuvwxyz",
  404. "uppercase": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  405. "numbers": "0123456789"]
  406. // When
  407. let result = AFResult<String> { try encoder.encode(parameters) }
  408. // Then
  409. XCTAssertQueryEqual(result.value,
  410. "uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ&numbers=0123456789&lowercase=abcdefghijklmnopqrstuvwxyz")
  411. }
  412. func testThatReseredCharactersArePercentEscaped() {
  413. // Given
  414. let encoder = URLEncodedFormEncoder()
  415. let generalDelimiters = ":#[]@"
  416. let subDelimiters = "!$&'()*+,;="
  417. let parameters = ["reserved": "\(generalDelimiters)\(subDelimiters)"]
  418. // When
  419. let result = AFResult<String> { try encoder.encode(parameters) }
  420. // Then
  421. XCTAssertEqual(result.value, "reserved=%3A%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D")
  422. }
  423. func testThatIllegalASCIICharactersArePercentEscaped() {
  424. // Given
  425. let encoder = URLEncodedFormEncoder()
  426. let parameters = ["illegal": " \"#%<>[]\\^`{}|"]
  427. // When
  428. let result = AFResult<String> { try encoder.encode(parameters) }
  429. // Then
  430. XCTAssertEqual(result.value, "illegal=%20%22%23%25%3C%3E%5B%5D%5C%5E%60%7B%7D%7C")
  431. }
  432. func testThatAmpersandsInKeysAndValuesArePercentEscaped() {
  433. // Given
  434. let encoder = URLEncodedFormEncoder()
  435. let parameters = ["foo&bar": "baz&qux", "foobar": "bazqux"]
  436. // When
  437. let result = AFResult<String> { try encoder.encode(parameters) }
  438. // Then
  439. XCTAssertQueryEqual(result.value, "foobar=bazqux&foo%26bar=baz%26qux")
  440. }
  441. func testThatQuestionMarksInKeysAndValuesAreNotPercentEscaped() {
  442. // Given
  443. let encoder = URLEncodedFormEncoder()
  444. let parameters = ["?foo?": "?bar?"]
  445. // When
  446. let result = AFResult<String> { try encoder.encode(parameters) }
  447. // Then
  448. XCTAssertEqual(result.value, "?foo?=?bar?")
  449. }
  450. func testThatSlashesInKeysAndValuesAreNotPercentEscaped() {
  451. // Given
  452. let encoder = URLEncodedFormEncoder()
  453. let parameters = ["foo": "/bar/baz/qux"]
  454. // When
  455. let result = AFResult<String> { try encoder.encode(parameters) }
  456. // Then
  457. XCTAssertEqual(result.value, "foo=/bar/baz/qux")
  458. }
  459. func testThatSpacesInKeysAndValuesArePercentEscaped() {
  460. // Given
  461. let encoder = URLEncodedFormEncoder()
  462. let parameters = [" foo ": " bar "]
  463. // When
  464. let result = AFResult<String> { try encoder.encode(parameters) }
  465. // Then
  466. XCTAssertEqual(result.value, "%20foo%20=%20bar%20")
  467. }
  468. func testThatPlusesInKeysAndValuesArePercentEscaped() {
  469. // Given
  470. let encoder = URLEncodedFormEncoder()
  471. let parameters = ["+foo+": "+bar+"]
  472. // When
  473. let result = AFResult<String> { try encoder.encode(parameters) }
  474. // Then
  475. XCTAssertEqual(result.value, "%2Bfoo%2B=%2Bbar%2B")
  476. }
  477. func testThatPercentsInKeysAndValuesArePercentEscaped() {
  478. // Given
  479. let encoder = URLEncodedFormEncoder()
  480. let parameters = ["percent%": "%25"]
  481. // When
  482. let result = AFResult<String> { try encoder.encode(parameters) }
  483. // Then
  484. XCTAssertEqual(result.value, "percent%25=%2525")
  485. }
  486. func testThatNonLatinCharactersArePercentEscaped() {
  487. // Given
  488. let encoder = URLEncodedFormEncoder()
  489. let parameters = [
  490. "french": "français",
  491. "japanese": "日本語",
  492. "arabic": "العربية",
  493. "emoji": "😃"
  494. ]
  495. // When
  496. let result = AFResult<String> { try encoder.encode(parameters) }
  497. // Then
  498. let expectedParameterValues = [
  499. "arabic=%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9",
  500. "japanese=%E6%97%A5%E6%9C%AC%E8%AA%9E",
  501. "french=fran%C3%A7ais",
  502. "emoji=%F0%9F%98%83"
  503. ].joined(separator: "&")
  504. XCTAssertQueryEqual(result.value, expectedParameterValues)
  505. }
  506. func testStringWithThousandsOfChineseCharactersIsPercentEscaped() {
  507. // Given
  508. let encoder = URLEncodedFormEncoder()
  509. let repeatedCount = 2_000
  510. let parameters = ["chinese": String(repeating: "一二三四五六七八九十", count: repeatedCount)]
  511. // When
  512. let result = AFResult<String> { try encoder.encode(parameters) }
  513. // Then
  514. let escaped = String(repeating: "%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",
  515. count: repeatedCount)
  516. let expected = "chinese=\(escaped)"
  517. XCTAssertEqual(result.value, expected)
  518. }
  519. }
  520. private struct EncodableStruct: Encodable {
  521. let one = "one"
  522. let two = 2
  523. let three = true
  524. let four = [1, 2, 3]
  525. let five = ["a": "a"]
  526. let six = ["a": ["b": "b"]]
  527. let seven = NestedEncodableStruct()
  528. }
  529. private struct NestedEncodableStruct: Encodable {
  530. let a = "a"
  531. }
  532. private class EncodableSuperclass: Encodable {
  533. let one = "one"
  534. let two = 2
  535. let three = true
  536. }
  537. private final class EncodableSubclass: EncodableSuperclass {
  538. let four = [1, 2, 3]
  539. let five = ["a": "a", "b": "b"]
  540. private enum CodingKeys: String, CodingKey {
  541. case four, five
  542. }
  543. override func encode(to encoder: Encoder) throws {
  544. try super.encode(to: encoder)
  545. var container = encoder.container(keyedBy: CodingKeys.self)
  546. try container.encode(four, forKey: .four)
  547. try container.encode(five, forKey: .five)
  548. }
  549. }
  550. private final class ManuallyEncodableSubclass: EncodableSuperclass {
  551. let four = [1, 2, 3]
  552. let five = ["a": "a", "b": "b"]
  553. private enum CodingKeys: String, CodingKey {
  554. case four, five
  555. }
  556. override func encode(to encoder: Encoder) throws {
  557. var keyedContainer = encoder.container(keyedBy: CodingKeys.self)
  558. try keyedContainer.encode(four, forKey: .four)
  559. try keyedContainer.encode(five, forKey: .five)
  560. let superEncoder = keyedContainer.superEncoder()
  561. var superContainer = superEncoder.container(keyedBy: CodingKeys.self)
  562. try superContainer.encode(one, forKey: .four)
  563. let keyedSuperEncoder = keyedContainer.superEncoder(forKey: .four)
  564. var superKeyedContainer = keyedSuperEncoder.container(keyedBy: CodingKeys.self)
  565. try superKeyedContainer.encode(two, forKey: .five)
  566. var unkeyedContainer = keyedContainer.nestedUnkeyedContainer(forKey: .four)
  567. let unkeyedSuperEncoder = unkeyedContainer.superEncoder()
  568. var keyedUnkeyedSuperContainer = unkeyedSuperEncoder.container(keyedBy: CodingKeys.self)
  569. try keyedUnkeyedSuperContainer.encode(one, forKey: .four)
  570. }
  571. }
  572. private struct ManuallyEncodableStruct: Encodable {
  573. let a = ["string": "string"]
  574. let b = [1, 2, 3]
  575. private enum RootKey: String, CodingKey {
  576. case root
  577. }
  578. private enum TypeKeys: String, CodingKey {
  579. case a, b
  580. }
  581. func encode(to encoder: Encoder) throws {
  582. var container = encoder.container(keyedBy: RootKey.self)
  583. var nestedKeyedContainer = container.nestedContainer(keyedBy: TypeKeys.self, forKey: .root)
  584. try nestedKeyedContainer.encode(a, forKey: .a)
  585. var nestedUnkeyedContainer = container.nestedUnkeyedContainer(forKey: .root)
  586. try nestedUnkeyedContainer.encode(b)
  587. var nestedUnkeyedKeyedContainer = nestedUnkeyedContainer.nestedContainer(keyedBy: TypeKeys.self)
  588. try nestedUnkeyedKeyedContainer.encode(a, forKey: .a)
  589. var nestedUnkeyedUnkeyedContainer = nestedUnkeyedContainer.nestedUnkeyedContainer()
  590. try nestedUnkeyedUnkeyedContainer.encode(b)
  591. }
  592. }
  593. private struct FailingOptionalStruct: Encodable {
  594. enum TestedContainer {
  595. case keyed, unkeyed
  596. }
  597. enum CodingKeys: String, CodingKey { case a }
  598. let testedContainer: TestedContainer
  599. func encode(to encoder: Encoder) throws {
  600. var container = encoder.container(keyedBy: CodingKeys.self)
  601. switch testedContainer {
  602. case .keyed:
  603. var nested = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .a)
  604. try nested.encodeNil(forKey: .a)
  605. case .unkeyed:
  606. var nested = container.nestedUnkeyedContainer(forKey: .a)
  607. try nested.encodeNil()
  608. }
  609. }
  610. }
  611. private func XCTAssertQueryEqual(_ query1: String?, _ query2: String?) {
  612. let items1 = query1?.split(separator: "&").sorted()
  613. let items2 = query2?.split(separator: "&").sorted()
  614. XCTAssertEqual(items1, items2)
  615. }