Skip to content

Commit

Permalink
Authentication property added to NativeAuthTransaction Protocol
Browse files Browse the repository at this point in the history
Improved NativeAuthTransaction tests
  • Loading branch information
cocojoe committed Jan 31, 2017
1 parent ba6990f commit 1c7d306
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 59 deletions.
4 changes: 3 additions & 1 deletion Auth0/NativeAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public protocol NativeAuthTransaction: AuthTransaction {
var connection: String { get }
/// Additional authentication parameters sent to Auth0 to perform the final auth
var parameters: [String: Any] { get }
/// Authenticaton object to perform the Auth0 social auth
var authentication: Authentication { get }

/// Callback where the result of the native authentication is sent
typealias Callback = (Result<NativeAuthCredentials>) -> ()
Expand Down Expand Up @@ -107,7 +109,7 @@ public extension NativeAuthTransaction {
case .success(let credentials):
var parameters: [String: Any] = self.parameters
credentials.extras.forEach { parameters[$0] = $1 }
authentication().loginSocial(token: credentials.token, connection: self.connection, scope: self.scope, parameters: parameters)
self.authentication.loginSocial(token: credentials.token, connection: self.connection, scope: self.scope, parameters: parameters)
.start(callback)
case .failure(let error):
callback(.failure(error: error))
Expand Down
161 changes: 103 additions & 58 deletions Auth0Tests/NativeAuthSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,28 @@ import OHHTTPStubs
private let ClientId = "CLIENT_ID"
private let Domain = "samples.auth0.com"
private let DomainURL = URL(fileURLWithPath: Domain)
private let Connection = "facebook"
private let Scope = "openid"
private let Parameters: [String: Any] = [:]
private let Timeout: TimeInterval = 2

private let AccessToken = UUID().uuidString.replacingOccurrences(of: "-", with: "")
private let IdToken = UUID().uuidString.replacingOccurrences(of: "-", with: "")
private let FacebookToken = UUID().uuidString.replacingOccurrences(of: "-", with: "")
private let InvalidFacebookToken = UUID().uuidString.replacingOccurrences(of: "-", with: "")

class MockNativeAuthTransaction: NativeAuthTransaction {
var connection: String = "facebook"
var scope: String = "openid"
var parameters: [String : Any] = [:]

var nativeError: Bool = false
var connection: String
var scope: String
var parameters: [String : Any]
var authentication: Authentication

init(connection: String, scope: String, parameters: [String: Any], authentication: Authentication) {
self.connection = connection
self.scope = scope
self.parameters = parameters
self.authentication = authentication
}

var delayed: NativeAuthTransaction.Callback = { _ in }

Expand All @@ -55,25 +65,14 @@ class MockNativeAuthTransaction: NativeAuthTransaction {
}

func resume(_ url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
guard !self.nativeError else {
self.cancel()
return false
}
self.delayed(.success(result: NativeAuthCredentials(token: FacebookToken, extras: [:])))
self.delayed(self.onNativeAuth())
self.delayed = { _ in }
return true
}

public func start(callback: @escaping (Result<Credentials>) -> ()) {
TransactionStore.shared.store(self)
self.auth { result in
switch result {
case .success(_):
callback(.success(result: Credentials(accessToken: FacebookToken)))
case .failure(let error):
callback(.failure(error: error))
}
}
/// Test Hooks
var onNativeAuth: () -> Result<NativeAuthCredentials> = {
return .success(result: NativeAuthCredentials(token: FacebookToken, extras: [:]))
}
}

Expand All @@ -82,76 +81,122 @@ class NativeAuthSpec: QuickSpec {
override func spec() {

var nativeTransaction: MockNativeAuthTransaction!
var error: Error?
var nativeCredentials: NativeAuthCredentials!
let authentication = Auth0Authentication(clientId: ClientId, url: URL(string: "https://\(Domain)")!)

beforeEach {
error = nil
nativeCredentials = nil
nativeTransaction = MockNativeAuthTransaction()
nativeTransaction.auth { result in
switch result {
case .success(let credentials):
nativeCredentials = credentials
case .failure(let nativeError):
error = nativeError
}
}
stub(condition: isHost(Domain)) { _ in
return OHHTTPStubsResponse.init(error: NSError(domain: "com.auth0", code: -99999, userInfo: nil))
}.name = "YOU SHALL NOT PASS!"

nativeTransaction = MockNativeAuthTransaction(connection: Connection , scope: Scope, parameters: Parameters, authentication: authentication)
}

afterEach {
OHHTTPStubs.removeAllStubs()
}

describe("Default values set") {
describe("Initializer values set") {

it("should have connection") {
expect(nativeTransaction.connection) == "facebook"
expect(nativeTransaction.connection) == Connection
}

it("should have scope") {
expect(nativeTransaction.scope) == "openid"
expect(nativeTransaction.scope) == Scope
}

it("should have parameters") {
it("should have empty parameters") {
expect(nativeTransaction.parameters).to(haveCount(0))
}
}

describe("auth") {
describe("start") {

beforeEach {
stub(condition: isOAuthAccessToken(Domain) && hasAtLeast(["access_token":FacebookToken, "connection": "facebook", "scope": "openid"])) { _ in return authResponse(accessToken: AccessToken, idToken: IdToken) }.name = "Facebook Auth OpenID"
stub(condition: isOAuthAccessToken(Domain) && hasAtLeast(["access_token":InvalidFacebookToken, "connection": "facebook", "scope": "openid"])) { _ in return authFailure(error: "invalid_token", description: "invalid_token") }.name = "invalid token"
}

it("should store transaction in store") {
nativeTransaction.start { _ in }
expect(TransactionStore.shared.current?.state) == nativeTransaction.state
}

it("should return credentials on success") {
nativeTransaction.start { result in
expect(result).to(haveCredentials())
}
_ = nativeTransaction.resume(DomainURL, options: [:])
it("should nil transaction in store after resume") {
nativeTransaction.start { _ in }
_ = Auth0.resumeAuth(DomainURL, options: [:])
expect(TransactionStore.shared.current).to(beNil())
}
}

describe("resume") {
it("should yield credentials on success") {
waitUntil(timeout: Timeout) { done in
nativeTransaction
.start { result in
switch result {
case .success(let result):
expect(result.accessToken) == AccessToken
done()
default:
break
}
}
_ = nativeTransaction.resume(DomainURL, options: [:])
}

it("should return true") {
expect(nativeTransaction.resume(DomainURL, options: [:])) == true
}

it("should return native credentials") {
_ = nativeTransaction.resume(DomainURL, options: [:])
expect(error).to(beNil())
expect(nativeCredentials!.token) == FacebookToken
it("should yield error on native auth failure") {
nativeTransaction.onNativeAuth = {
return .failure(error: WebAuthError.missingAccessToken)
}
waitUntil(timeout: Timeout) { done in
nativeTransaction.start { result in
switch result {
case .failure(let error):
expect(error).to(matchError(WebAuthError.missingAccessToken))
done()
default:
break
}
}
_ = nativeTransaction.resume(DomainURL, options: [:])
}

}

it("should return false") {
nativeTransaction.nativeError = true
expect(nativeTransaction.resume(DomainURL, options: [:])) == false
it("should yield auth error on invalid native access token") {
nativeTransaction.onNativeAuth = {
return .success(result: NativeAuthCredentials(token: InvalidFacebookToken, extras: [:]))
}
waitUntil(timeout: Timeout) { done in
nativeTransaction.start { result in
expect(result).to(haveAuthenticationError(code: "invalid_token", description: "invalid_token"))
done()
}
_ = nativeTransaction.resume(DomainURL, options: [:])
}

}
}

it("should return error") {
nativeTransaction.nativeError = true
_ = nativeTransaction.resume(DomainURL, options: [:])
expect(error).toNot(beNil())
describe("cancel") {

it("should yield error on cancel") {
waitUntil(timeout: Timeout) { done in
nativeTransaction.start { result in
switch result {
case .failure(let error):
expect(error).to(matchError(WebAuthError.userCancelled))
done()
default:
break
}
}
_ = nativeTransaction.cancel()
}

}

}

}
Expand Down

0 comments on commit 1c7d306

Please sign in to comment.