Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new errors to SmartcarAuth + update docs #68

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion SmartcarAuth.podspec
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 5 additions & 1 deletion SmartcarAuth.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -52,13 +53,15 @@
F8F9288F1E2B2F6B009F07E5 /* SmartcarAuthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartcarAuthTests.swift; sourceTree = "<group>"; };
F8F928911E2B2F6B009F07E5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F8F928A31E2B2FED009F07E5 /* SmartcarAuth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartcarAuth.swift; sourceTree = "<group>"; };
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 */
F8F9287D1E2B2F6A009F07E5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D15D84821DCE86EDAF31A781 /* Pods_SmartcarAuth.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -78,6 +81,7 @@
isa = PBXGroup;
children = (
4C65C9D0D291B77BE47281A0 /* Pods_SmartcarAuthTests.framework */,
FDAA0663C03D09F19916FFCA /* Pods_SmartcarAuth.framework */,
);
name = Frameworks;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 = (
Expand Down
9 changes: 8 additions & 1 deletion SmartcarAuth/AuthorizationError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
8 changes: 8 additions & 0 deletions SmartcarAuth/SmartcarAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
34 changes: 31 additions & 3 deletions SmartcarAuthTests/AuthorizationErrorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand All @@ -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"))
}
}
55 changes: 55 additions & 0 deletions SmartcarAuthTests/SmartcarAuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Loading