From b438963d0cfda9b295cf4218528778cee46e3043 Mon Sep 17 00:00:00 2001 From: Smartcar Date: Wed, 22 Feb 2023 15:52:32 -0800 Subject: [PATCH] feat: add new errors to SmartcarAuth + update docs --- README.md | 2 +- SmartcarAuth.podspec | 2 +- SmartcarAuth.xcodeproj/project.pbxproj | 6 +- SmartcarAuth/AuthorizationError.swift | 9 +- SmartcarAuth/SmartcarAuth.swift | 8 + .../AuthorizationErrorTests.swift | 34 +- SmartcarAuthTests/SmartcarAuthTests.swift | 55 +++ docs/Classes.html | 74 +--- docs/Classes/AuthorizationError.html | 172 ++++++++ .../Classes/AuthorizationError/ErrorType.html | 260 ++++++++++++ docs/Classes/SCUrlBuilder.html | 325 ++------------ docs/Classes/SmartcarAuth.html | 219 +--------- docs/Classes/VehicleInfo.html | 93 +--- docs/badge.svg | 16 +- docs/css/highlight.css | 400 +++++++++--------- docs/css/jazzy.css | 18 +- .../Contents/Resources/Documents/Classes.html | 74 +--- .../Documents/Classes/AuthorizationError.html | 172 ++++++++ .../Classes/AuthorizationError/ErrorType.html | 260 ++++++++++++ .../Documents/Classes/SCURLBuilder.html | 325 ++------------ .../Documents/Classes/SmartcarAuth.html | 219 +--------- .../Documents/Classes/VehicleInfo.html | 93 +--- .../Contents/Resources/Documents/badge.svg | 16 +- .../Resources/Documents/css/highlight.css | 400 +++++++++--------- .../Resources/Documents/css/jazzy.css | 18 +- .../Contents/Resources/Documents/index.html | 20 +- .../Contents/Resources/Documents/js/jazzy.js | 4 + .../Resources/Documents/js/jazzy.search.js | 4 + .../Resources/Documents/js/jquery.min.js | 4 +- .../Resources/Documents/js/lunr.min.js | 6 +- .../Contents/Resources/Documents/search.json | 2 +- .../Resources/Documents/undocumented.json | 110 +++++ .../Contents/Resources/docSet.dsidx | Bin 12288 -> 12288 bytes docs/docsets/SmartcarAuth.tgz | Bin 75062 -> 74504 bytes docs/index.html | 20 +- docs/js/jazzy.js | 4 + docs/js/jazzy.search.js | 4 + docs/js/jquery.min.js | 4 +- docs/js/lunr.min.js | 6 +- docs/search.json | 2 +- 40 files changed, 1743 insertions(+), 1717 deletions(-) create mode 100644 docs/Classes/AuthorizationError.html create mode 100644 docs/Classes/AuthorizationError/ErrorType.html create mode 100644 docs/docsets/SmartcarAuth.docset/Contents/Resources/Documents/Classes/AuthorizationError.html create mode 100644 docs/docsets/SmartcarAuth.docset/Contents/Resources/Documents/Classes/AuthorizationError/ErrorType.html create mode 100644 docs/docsets/SmartcarAuth.docset/Contents/Resources/Documents/undocumented.json diff --git a/README.md b/README.md index 79795e7..53badcc 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ appDelegate.smartcar = SmartcarAuth( clientId: "afb0b7d3-807f-4c61-9b04-352e91fe3134", redirectUri: "scafb0b7d3-807f-4c61-9b04-352e91fe3134://exchange", scope: ["read_vin", "read_vehicle_info", "read_odometer"], - completion: completionHandler + completionHandler: completionHandler ) let smartcar = appDelegate.smartcar diff --git a/SmartcarAuth.podspec b/SmartcarAuth.podspec index 3909c9b..d0f632c 100755 --- a/SmartcarAuth.podspec +++ b/SmartcarAuth.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'SmartcarAuth' - s.version = '4.1.3' + s.version = '4.2.3' s.summary = 'Smartcar Authentication SDK for iOS written in Swift 5.' s.description = <<-DESC diff --git a/SmartcarAuth.xcodeproj/project.pbxproj b/SmartcarAuth.xcodeproj/project.pbxproj index 9a70b76..1782532 100644 --- a/SmartcarAuth.xcodeproj/project.pbxproj +++ b/SmartcarAuth.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ A69F57AB2374EAB9005971D2 /* AuthorizationErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69F57AA2374EAB9005971D2 /* AuthorizationErrorTests.swift */; }; A6B8653E2374EDE4008BFD7F /* VehicleInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B8653D2374EDE4008BFD7F /* VehicleInfoTests.swift */; }; BD6F87320FA50DDC202ADF59 /* Pods_SmartcarAuthTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C65C9D0D291B77BE47281A0 /* Pods_SmartcarAuthTests.framework */; }; + D15D84821DCE86EDAF31A781 /* Pods_SmartcarAuth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDAA0663C03D09F19916FFCA /* Pods_SmartcarAuth.framework */; }; F80C4ABD208E54AE00F8C47F /* SmartcarAuthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F9288F1E2B2F6B009F07E5 /* SmartcarAuthTests.swift */; }; F85ABF81208C191D00FB2F3E /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = F85ABF80208C191D00FB2F3E /* Podfile */; }; F85ABF82208C196200FB2F3E /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = F85ABF80208C191D00FB2F3E /* Podfile */; }; @@ -52,6 +53,7 @@ F8F9288F1E2B2F6B009F07E5 /* SmartcarAuthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartcarAuthTests.swift; sourceTree = ""; }; F8F928911E2B2F6B009F07E5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F8F928A31E2B2FED009F07E5 /* SmartcarAuth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartcarAuth.swift; sourceTree = ""; }; + FDAA0663C03D09F19916FFCA /* Pods_SmartcarAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SmartcarAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -59,6 +61,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D15D84821DCE86EDAF31A781 /* Pods_SmartcarAuth.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -78,6 +81,7 @@ isa = PBXGroup; children = ( 4C65C9D0D291B77BE47281A0 /* Pods_SmartcarAuthTests.framework */, + FDAA0663C03D09F19916FFCA /* Pods_SmartcarAuth.framework */, ); name = Frameworks; sourceTree = ""; @@ -158,9 +162,9 @@ buildConfigurationList = F8F928951E2B2F6B009F07E5 /* Build configuration list for PBXNativeTarget "SmartcarAuth" */; buildPhases = ( D8883AFEA3976721048A426A /* [CP] Check Pods Manifest.lock */, + F8F9287E1E2B2F6A009F07E5 /* Headers */, F8F9287C1E2B2F6A009F07E5 /* Sources */, F8F9287D1E2B2F6A009F07E5 /* Frameworks */, - F8F9287E1E2B2F6A009F07E5 /* Headers */, F8F9287F1E2B2F6A009F07E5 /* Resources */, ); buildRules = ( diff --git a/SmartcarAuth/AuthorizationError.swift b/SmartcarAuth/AuthorizationError.swift index ba3f151..d0cfbac 100644 --- a/SmartcarAuth/AuthorizationError.swift +++ b/SmartcarAuth/AuthorizationError.swift @@ -28,19 +28,26 @@ case missingQueryParameters case missingAuthCode case accessDenied + case configurationError case vehicleIncompatible case invalidSubscription + case noVehicles + case serverError case userExitedFlow case unknownError } public let type: ErrorType public let errorDescription: String? + public let statusCode: String? + public let errorMessage: String? var vehicleInfo: VehicleInfo? - init(type: ErrorType, errorDescription: String? = nil, vehicleInfo: VehicleInfo? = nil) { + init(type: ErrorType, errorDescription: String? = nil, vehicleInfo: VehicleInfo? = nil, statusCode: String? = nil, errorMessage: String? = nil) { self.type = type self.errorDescription = errorDescription self.vehicleInfo = vehicleInfo + self.statusCode = statusCode + self.errorMessage = errorMessage } } diff --git a/SmartcarAuth/SmartcarAuth.swift b/SmartcarAuth/SmartcarAuth.swift index 6bbbe04..af6ee86 100644 --- a/SmartcarAuth/SmartcarAuth.swift +++ b/SmartcarAuth/SmartcarAuth.swift @@ -182,6 +182,14 @@ Smartcar Authentication SDK for iOS written in Swift 5. authorizationError = AuthorizationError(type: .invalidSubscription, errorDescription: errorDescription) case "access_denied": authorizationError = AuthorizationError(type: .accessDenied, errorDescription: errorDescription) + case "no_vehicles": + authorizationError = AuthorizationError(type: .noVehicles, errorDescription: errorDescription) + case "configuration_error": + let statusCode = query.filter({$0.name == "status_code"}).first?.value; + let errorMessage = query.filter({$0.name == "error_message"}).first?.value; + authorizationError = AuthorizationError(type: .configurationError, errorDescription: errorDescription, statusCode: statusCode, errorMessage: errorMessage) + case "server_error": + authorizationError = AuthorizationError(type: .serverError, errorDescription: errorDescription) default: authorizationError = AuthorizationError(type: .unknownError, errorDescription: errorDescription) } diff --git a/SmartcarAuthTests/AuthorizationErrorTests.swift b/SmartcarAuthTests/AuthorizationErrorTests.swift index 5ae532e..064d3a8 100644 --- a/SmartcarAuthTests/AuthorizationErrorTests.swift +++ b/SmartcarAuthTests/AuthorizationErrorTests.swift @@ -29,6 +29,8 @@ class AuthorizationErrorTests: XCTestCase { expect(error.type).to(equal(.accessDenied)) expect(error.errorDescription).to(beNil()) expect(error.vehicleInfo).to(beNil()) + expect(error.statusCode).to(beNil()) + expect(error.errorMessage).to(beNil()) } func testAuthorizationErrorWithErrorDescription() { @@ -37,6 +39,28 @@ class AuthorizationErrorTests: XCTestCase { expect(error.type).to(equal(.accessDenied)) expect(error.errorDescription).to(equal("Access was denied")) expect(error.vehicleInfo).to(beNil()) + expect(error.statusCode).to(beNil()) + expect(error.errorMessage).to(beNil()) + } + + func testAuthorizationErrorWithStatusCode() { + let error = AuthorizationError(type: .configurationError, errorDescription: "There has been an error in the configuration of your application.", statusCode: "400") + + expect(error.type).to(equal(.configurationError)) + expect(error.errorDescription).to(equal("There has been an error in the configuration of your application.")) + expect(error.vehicleInfo).to(beNil()) + expect(error.statusCode).to(equal("400")) + expect(error.errorMessage).to(beNil()) + } + + func testAuthorizationErrorWithErrorMessage() { + let error = AuthorizationError(type: .configurationError, errorDescription: "There has been an error in the configuration of your application.", errorMessage: "Invalid client ID") + + expect(error.type).to(equal(.configurationError)) + expect(error.errorDescription).to(equal("There has been an error in the configuration of your application.")) + expect(error.vehicleInfo).to(beNil()) + expect(error.statusCode).to(beNil()) + expect(error.errorMessage).to(equal("Invalid client ID")) } func testAuthorizationErrorWithVehicleInfo() { @@ -46,14 +70,18 @@ class AuthorizationErrorTests: XCTestCase { expect(error.type).to(equal(.accessDenied)) expect(error.errorDescription).to(beNil()) expect(error.vehicleInfo).to(beIdenticalTo(vehicleInfo)) + expect(error.statusCode).to(beNil()) + expect(error.errorMessage).to(beNil()) } func testAuthorizationErrorWithAllFields() { let vehicleInfo = VehicleInfo(vin: "12345678901234567", make: "Tesla", model: "Model 3", year: 2019) - let error = AuthorizationError(type: .accessDenied, errorDescription: "Access was denied", vehicleInfo: vehicleInfo) + let error = AuthorizationError(type: .configurationError, errorDescription: "There has been an error in the configuration of your application.", vehicleInfo: vehicleInfo, statusCode: "400", errorMessage: "Invalid client ID") - expect(error.type).to(equal(.accessDenied)) - expect(error.errorDescription).to(equal("Access was denied")) + expect(error.type).to(equal(.configurationError)) + expect(error.errorDescription).to(equal("There has been an error in the configuration of your application.")) expect(error.vehicleInfo).to(beIdenticalTo(vehicleInfo)) + expect(error.statusCode).to(equal("400")) + expect(error.errorMessage).to(equal("Invalid client ID")) } } diff --git a/SmartcarAuthTests/SmartcarAuthTests.swift b/SmartcarAuthTests/SmartcarAuthTests.swift index b3fa9d6..ea5134e 100644 --- a/SmartcarAuthTests/SmartcarAuthTests.swift +++ b/SmartcarAuthTests/SmartcarAuthTests.swift @@ -128,6 +128,61 @@ class SmartcarAuthTests: XCTestCase { smartcar.handleCallback(callbackUrl: url) } + func testHandleCallbackNoVehicles() { + let smartcar = SmartcarAuth(clientId: clientId, redirectUri: redirectUri, scope: scope, completionHandler: { code, state, err in + expect(code).to(beNil()) + expect(state).to(beNil()) + + expect(err?.errorDescription).to(equal("User does not have any vehicles connected to this connected services account")) + expect(err?.type).to(equal(.noVehicles)) + expect(err?.vehicleInfo).to(beNil()) + }) + + let urlString = redirectUri + "?error=no_vehicles&error_description=User%20does%20not%20have%20any%20vehicles%20connected%20to%20this%20connected%20services%20account" + + let url = URL(string: urlString)! + + smartcar.handleCallback(callbackUrl: url) + } + + func testHandleCallbackConfigurationError() { + let smartcar = SmartcarAuth(clientId: clientId, redirectUri: redirectUri, scope: scope, completionHandler: { code, state, err in + expect(code).to(beNil()) + expect(state).to(beNil()) + + expect(err?.errorDescription).to(equal("There has been an error in the configuration of your application.")) + expect(err?.type).to(equal(.configurationError)) + expect(err?.vehicleInfo).to(beNil()) + expect(err?.statusCode).to(equal("400")) + expect(err?.errorMessage).to(equal("You have entered a test mode VIN. Please enter a VIN that belongs to a real vehicle.")) + }) + + let urlString = redirectUri + "?error=configuration_error&error_description=There%20has%20been%20an%20error%20in%20the%20configuration%20of%20your%20application.&status_code=400&error_message=You%20have%20entered%20a%20test%20mode%20VIN.%20Please%20enter%20a%20VIN%20that%20belongs%20to%20a%20real%20vehicle." + + let url = URL(string: urlString)! + + smartcar.handleCallback(callbackUrl: url) + } + + func testHandleCallbackServerError() { + let smartcar = SmartcarAuth(clientId: clientId, redirectUri: redirectUri, scope: scope, completionHandler: { code, state, err in + expect(code).to(beNil()) + expect(state).to(beNil()) + + expect(err?.errorDescription).to(equal("Unexpected server error. Please try again.")) + expect(err?.type).to(equal(.serverError)) + expect(err?.vehicleInfo).to(beNil()) + expect(err?.statusCode).to(beNil()) + expect(err?.errorMessage).to(beNil()) + }) + + let urlString = redirectUri + "?error=server_error&error_description=Unexpected%20server%20error.%20Please%20try%20again." + + let url = URL(string: urlString)! + + smartcar.handleCallback(callbackUrl: url) + } + func testHandleCallbackUnrecognizedError() { let smartcar = SmartcarAuth(clientId: clientId, redirectUri: redirectUri, scope: scope, completionHandler: { code, state, err in expect(code).to(beNil()) diff --git a/docs/Classes.html b/docs/Classes.html index 92415da..885dd76 100644 --- a/docs/Classes.html +++ b/docs/Classes.html @@ -17,18 +17,18 @@
-

SmartcarAuth 4.1.1 Docs (100% documented)

-

+

SmartcarAuth 4.2.3 Docs (0% documented)

+
-

+
@@ -39,7 +39,10 @@ Classes