From 3a67542bd412fd8b3bc8c3b7a9da272440c94d22 Mon Sep 17 00:00:00 2001 From: Aliaksandr Bialiauski Date: Thu, 26 Aug 2021 15:52:32 +0300 Subject: [PATCH] Append sku_token to refresh route requests --- Sources/MapboxDirections/Directions.swift | 24 ++++++++----- .../DirectionsCredentials.swift | 2 +- .../DirectionsCredentialsTests.swift | 16 +++++++++ .../DirectionsTests.swift | 35 ++++++++++++++++--- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/Sources/MapboxDirections/Directions.swift b/Sources/MapboxDirections/Directions.swift index d51568c3c..f4c114662 100644 --- a/Sources/MapboxDirections/Directions.swift +++ b/Sources/MapboxDirections/Directions.swift @@ -126,6 +126,17 @@ open class Directions: NSObject { - parameter credentials: A `DirectionsCredentials` object that, optionally, contains customized Token and Endpoint information. If no credentials object is supplied, then defaults are used. */ + + private var authenticationParams: [URLQueryItem] { + var params: [URLQueryItem] = [ + URLQueryItem(name: "access_token", value: credentials.accessToken) + ] + + if let skuToken = credentials.skuToken { + params.append(URLQueryItem(name: "sku", value: skuToken)) + } + return params + } public init(credentials: DirectionsCredentials = .init()) { self.credentials = credentials @@ -479,9 +490,8 @@ open class Directions: NSObject { } open func urlRequest(forRefreshing responseIdentifier: String, routeIndex: Int, fromLegAtIndex startLegIndex: Int) -> URLRequest { - var params: [URLQueryItem] = [] - params += [URLQueryItem(name: "access_token", value: credentials.accessToken)] - + let params: [URLQueryItem] = authenticationParams + var unparameterizedURL = URL(string: "directions-refresh/v1/\(DirectionsProfileIdentifier.automobileAvoidingTraffic.rawValue)", relativeTo: credentials.host)! unparameterizedURL.appendPathComponent(responseIdentifier) unparameterizedURL.appendPathComponent(String(routeIndex)) @@ -520,12 +530,8 @@ open class Directions: NSObject { open func url(forCalculating options: DirectionsOptions, httpMethod: String) -> URL { let includesQuery = httpMethod != "POST" var params = (includesQuery ? options.urlQueryItems : []) - params += [URLQueryItem(name: "access_token", value: credentials.accessToken)] - - if let skuToken = credentials.skuToken { - params += [URLQueryItem(name: "sku", value: skuToken)] - } - + params.append(contentsOf: authenticationParams) + let unparameterizedURL = URL(string: includesQuery ? options.path : options.abridgedPath, relativeTo: credentials.host)! var components = URLComponents(url: unparameterizedURL, resolvingAgainstBaseURL: true)! components.queryItems = params diff --git a/Sources/MapboxDirections/DirectionsCredentials.swift b/Sources/MapboxDirections/DirectionsCredentials.swift index 56cd366f6..79c3d01a0 100644 --- a/Sources/MapboxDirections/DirectionsCredentials.swift +++ b/Sources/MapboxDirections/DirectionsCredentials.swift @@ -23,7 +23,7 @@ public struct DirectionsCredentials: Equatable { The SKU Token associated with the request. Used for billing. */ public var skuToken: String? { - #if os(iOS) + #if !os(Linux) guard let mbx: AnyClass = NSClassFromString("MBXAccounts") else { return nil } guard mbx.responds(to: Selector(("serviceSkuToken"))) else { return nil } return mbx.value(forKeyPath: "serviceSkuToken") as? String diff --git a/Tests/MapboxDirectionsTests/DirectionsCredentialsTests.swift b/Tests/MapboxDirectionsTests/DirectionsCredentialsTests.swift index f9554f1b2..f1238eea1 100644 --- a/Tests/MapboxDirectionsTests/DirectionsCredentialsTests.swift +++ b/Tests/MapboxDirectionsTests/DirectionsCredentialsTests.swift @@ -21,4 +21,20 @@ class DirectionsCredentialsTests: XCTestCase { UserDefaults.standard.set(expected, forKey: "MBXAccessToken") XCTAssertEqual(Directions.shared.credentials.accessToken, expected) } + +#if !os(Linux) + func testSkuToken() { + let expectedToken = "a token" + MBXAccounts.serviceSkuToken = expectedToken + XCTAssertEqual(Directions.shared.credentials.skuToken, expectedToken) + MBXAccounts.serviceSkuToken = nil + } +#endif +} + +#if !os(Linux) +@objc(MBXAccounts) +final class MBXAccounts: NSObject { + @objc static var serviceSkuToken: String? } +#endif diff --git a/Tests/MapboxDirectionsTests/DirectionsTests.swift b/Tests/MapboxDirectionsTests/DirectionsTests.swift index e08562499..7fd31fa03 100644 --- a/Tests/MapboxDirectionsTests/DirectionsTests.swift +++ b/Tests/MapboxDirectionsTests/DirectionsTests.swift @@ -36,13 +36,17 @@ Request ID: RAf2XH13mMVxQ96Z1cVQMPrd-hJoVA6LfaWVFDbdN2j-J1VkzaPvZg== #if !os(Linux) class DirectionsTests: XCTestCase { + private let skuToken: String = "1234567890" + override func setUp() { // Make sure tests run in all time zones NSTimeZone.default = TimeZone(secondsFromGMT: 0)! + MBXAccounts.serviceSkuToken = skuToken } override func tearDown() { HTTPStubs.removeAllStubs() super.tearDown() + MBXAccounts.serviceSkuToken = nil } func testConfiguration() { @@ -61,10 +65,15 @@ class DirectionsTests: XCTestCase { let url = directions.url(forCalculating: options, httpMethod: "GET") XCTAssertLessThanOrEqual(url.absoluteString.count, MaximumURLLength, "maximumCoordinateCount is too high") - let components = URLComponents(string: url.absoluteString) - XCTAssertEqual(components?.queryItems?.count, 7) - XCTAssertTrue(components?.path.contains(coordinates.compactMap { $0.requestDescription }.joined(separator: ";")) ?? false) - + guard let components = URLComponents(string: url.absoluteString), + let queryItems = components.queryItems else { + XCTFail("Invalid url"); return + } + XCTAssertEqual(queryItems.count, 8) + XCTAssertTrue(components.path.contains(coordinates.compactMap { $0.requestDescription }.joined(separator: ";")) ) + XCTAssert(queryItems.contains(where: { $0.name == "sku" && $0.value == skuToken }) == true) + XCTAssert(queryItems.contains(where: { $0.name == "access_token" && $0.value == BogusToken }) == true) + let request = directions.urlRequest(forCalculating: options) XCTAssertEqual(request.httpMethod, "GET") XCTAssertEqual(request.url, url) @@ -79,7 +88,7 @@ class DirectionsTests: XCTestCase { let request = directions.urlRequest(forCalculating: options) XCTAssertEqual(request.httpMethod, "POST") - XCTAssertEqual(request.url?.query, "access_token=\(BogusToken)") + XCTAssertEqual(request.url?.query, "access_token=\(BogusToken)&sku=\(skuToken)") XCTAssertNotNil(request.httpBody) var components = URLComponents() components.query = String(data: request.httpBody ?? Data(), encoding: .utf8) @@ -192,5 +201,21 @@ class DirectionsTests: XCTestCase { }) wait(for: [expectation], timeout: 2.0) } + + func testRefreshRouteRequest() { + let directions = Directions(credentials: BogusCredentials) + guard let url = directions.urlRequest(forRefreshing: "any", routeIndex: 0, fromLegAtIndex: 0).url else { + XCTFail("Incorrect request"); return + } + XCTAssertLessThanOrEqual(url.absoluteString.count, MaximumURLLength, "maximumCoordinateCount is too high") + + guard let queryItems = URLComponents(string: url.absoluteString)?.queryItems else { + XCTFail("Invalid url"); return + } + XCTAssertEqual(queryItems.count, 2) + XCTAssertTrue(queryItems.contains(where: { $0.name == "sku" && $0.value == skuToken })) + XCTAssertTrue(queryItems.contains(where: { $0.name == "access_token" && $0.value == BogusToken })) + } + } #endif