ParameterEncoderTests.swift 24 KB

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