// ParameterEncodingTests.swift // // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import Alamofire import Foundation import XCTest class ParameterEncodingTestCase: BaseTestCase { let URLRequest = NSURLRequest(URL: NSURL(string: "https://example.com/")!) } // MARK: - class URLParameterEncodingTestCase: ParameterEncodingTestCase { let encoding: ParameterEncoding = .URL // MARK: Tests - Parameter Types func testURLParameterEncodeNilParameters() { // Given // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: nil) // Then XCTAssertNil(URLRequest.URL?.query, "query should be nil") } func testURLParameterEncodeEmptyDictionaryParameter() { // Given let parameters: [String: AnyObject] = [:] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertNil(URLRequest.URL?.query, "query should be nil") } func testURLParameterEncodeOneStringKeyStringValueParameter() { // Given let parameters = ["foo": "bar"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=bar", "query is incorrect") } func testURLParameterEncodeOneStringKeyStringValueParameterAppendedToQuery() { // Given let mutableURLRequest = self.URLRequest.URLRequest let URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false)! URLComponents.query = "baz=qux" mutableURLRequest.URL = URLComponents.URL let parameters = ["foo": "bar"] // When let (URLRequest, _) = encoding.encode(mutableURLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "baz=qux&foo=bar", "query is incorrect") } func testURLParameterEncodeTwoStringKeyStringValueParameters() { // Given let parameters = ["foo": "bar", "baz": "qux"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "baz=qux&foo=bar", "query is incorrect") } func testURLParameterEncodeStringKeyIntegerValueParameter() { // Given let parameters = ["foo": 1] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1", "query is incorrect") } func testURLParameterEncodeStringKeyDoubleValueParameter() { // Given let parameters = ["foo": 1.1] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1.1", "query is incorrect") } func testURLParameterEncodeStringKeyBoolValueParameter() { // Given let parameters = ["foo": true] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=1", "query is incorrect") } func testURLParameterEncodeStringKeyArrayValueParameter() { // Given let parameters = ["foo": ["a", 1, true]] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5B%5D=a&foo%5B%5D=1&foo%5B%5D=1", "query is incorrect") } func testURLParameterEncodeStringKeyDictionaryValueParameter() { // Given let parameters = ["foo": ["bar": 1]] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5Bbar%5D=1", "query is incorrect") } func testURLParameterEncodeStringKeyNestedDictionaryValueParameter() { // Given let parameters = ["foo": ["bar": ["baz": 1]]] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%5Bbar%5D%5Bbaz%5D=1", "query is incorrect") } func testURLParameterEncodeStringKeyNestedDictionaryArrayValueParameter() { // Given let parameters = ["foo": ["bar": ["baz": ["a", 1, true]]]] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then 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" XCTAssertEqual(URLRequest.URL?.query ?? "", expectedQuery, "query is incorrect") } // MARK: Tests - All Reserved / Unreserved / Illegal Characters According to RFC 3986 func testThatReservedCharactersArePercentEscapedMinusQuestionMarkAndForwardSlash() { // Given let generalDelimiters = ":#[]@" let subDelimiters = "!$&'()*+,;=" let parameters = ["reserved": "\(generalDelimiters)\(subDelimiters)"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then let expectedQuery = "reserved=%3A%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D" XCTAssertEqual(URLRequest.URL?.query ?? "", expectedQuery, "query is incorrect") } func testThatReservedCharactersQuestionMarkAndForwardSlashAreNotPercentEscaped() { // Given let parameters = ["reserved": "?/"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "reserved=?/", "query is incorrect") } func testThatUnreservedNumericCharactersAreNotPercentEscaped() { // Given let parameters = ["numbers": "0123456789"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "numbers=0123456789", "query is incorrect") } func testThatUnreservedLowercaseCharactersAreNotPercentEscaped() { // Given let parameters = ["lowercase": "abcdefghijklmnopqrstuvwxyz"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "lowercase=abcdefghijklmnopqrstuvwxyz", "query is incorrect") } func testThatUnreservedUppercaseCharactersAreNotPercentEscaped() { // Given let parameters = ["uppercase": "ABCDEFGHIJKLMNOPQRSTUVWXYZ"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ", "query is incorrect") } func testThatIllegalASCIICharactersArePercentEscaped() { // Given let parameters = ["illegal": " \"#%<>[]\\^`{}|"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then let expectedQuery = "illegal=%20%22%23%25%3C%3E%5B%5D%5C%5E%60%7B%7D%7C" XCTAssertEqual(URLRequest.URL?.query ?? "", expectedQuery, "query is incorrect") } // MARK: Tests - Special Character Queries func testURLParameterEncodeStringWithAmpersandKeyStringWithAmpersandValueParameter() { // Given let parameters = ["foo&bar": "baz&qux", "foobar": "bazqux"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo%26bar=baz%26qux&foobar=bazqux", "query is incorrect") } func testURLParameterEncodeStringWithQuestionMarkKeyStringWithQuestionMarkValueParameter() { // Given let parameters = ["?foo?": "?bar?"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "?foo?=?bar?", "query is incorrect") } func testURLParameterEncodeStringWithSlashKeyStringWithQuestionMarkValueParameter() { // Given let parameters = ["foo": "/bar/baz/qux"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "foo=/bar/baz/qux", "query is incorrect") } func testURLParameterEncodeStringWithSpaceKeyStringWithSpaceValueParameter() { // Given let parameters = [" foo ": " bar "] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "%20foo%20=%20bar%20", "query is incorrect") } func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameter() { // Given let parameters = ["+foo+": "+bar+"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "%2Bfoo%2B=%2Bbar%2B", "query is incorrect") } func testURLParameterEncodeStringKeyPercentEncodedStringValueParameter() { // Given let parameters = ["percent": "%25"] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "percent=%2525", "query is incorrect") } func testURLParameterEncodeStringKeyNonLatinStringValueParameter() { // Given let parameters = [ "french": "français", "japanese": "日本語", "arabic": "العربية", "emoji": "😃" ] // When let (URLRequest, _) = encoding.encode(self.URLRequest, parameters: parameters) // Then let expectedParameterValues = [ "arabic=%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9", "emoji=%F0%9F%98%83", "french=fran%C3%A7ais", "japanese=%E6%97%A5%E6%9C%AC%E8%AA%9E" ] let expectedQuery = expectedParameterValues.joinWithSeparator("&") XCTAssertEqual(URLRequest.URL?.query ?? "", expectedQuery, "query is incorrect") } func testURLParameterEncodeStringForRequestWithPrecomposedQuery() { // Given let URL = NSURL(string: "https://example.com/movies?hd=[1]")! let parameters = ["page": "0"] // When let (URLRequest, _) = encoding.encode(NSURLRequest(URL: URL), parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "hd=%5B1%5D&page=0", "query is incorrect") } func testURLParameterEncodeStringWithPlusKeyStringWithPlusValueParameterForRequestWithPrecomposedQuery() { // Given let URL = NSURL(string: "https://example.com/movie?hd=[1]")! let parameters = ["+foo+": "+bar+"] // When let (URLRequest, _) = encoding.encode(NSURLRequest(URL: URL), parameters: parameters) // Then XCTAssertEqual(URLRequest.URL?.query ?? "", "hd=%5B1%5D&%2Bfoo%2B=%2Bbar%2B", "query is incorrect") } func testURLParameterEncodeStringWithThousandsOfChineseCharacters() { // Given let repeatedCount = 2_000 let URL = NSURL(string: "https://example.com/movies")! let parameters = ["chinese": String(count: repeatedCount, repeatedString: "一二三四五六七八九十")] // When let (URLRequest, _) = encoding.encode(NSURLRequest(URL: URL), parameters: parameters) // Then var expected = "chinese=" for _ in 0.. (NSMutableURLRequest, NSError?) = { URLRequest, parameters in guard let parameters = parameters else { return (URLRequest.URLRequest, nil) } var URLString = URLRequest.URLRequest.URLString + "?" parameters.forEach { URLString += "\($0)=\($1)" } let mutableURLRequest = URLRequest.URLRequest mutableURLRequest.URL = NSURL(string: URLString)! return (mutableURLRequest, nil) } // When let encoding: ParameterEncoding = .Custom(encodingClosure) // Then let URL = NSURL(string: "https://example.com")! let URLRequest = NSURLRequest(URL: URL) let parameters: [String: AnyObject] = ["foo": "bar"] XCTAssertEqual( encoding.encode(URLRequest, parameters: parameters).0.URLString, "https://example.com?foo=bar", "the encoded URL should match the expected value" ) } }