diff --git a/README.md b/README.md index a8a99f3..ea7b1f6 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,8 @@ struct ContentView: View { } } } - .onChange(of: oauth.state) { - handle(state: oauth.state) + .onChange(of: oauth.state) { state, _ in + handle(state: state) } } @@ -101,7 +101,7 @@ If you want to customize your OAuth environment or are using modules in your app ```swift - let oauth: OAuth = .init(.module) + let oauth: OAuth = await .init(.module) ``` If you are building your OAuth Providers programatically (recommended for production applications via a CI build pipeline for security purposes), you can pass providers and options as well. @@ -109,7 +109,7 @@ If you are building your OAuth Providers programatically (recommended for produc ```swift let providers: [OAuth.Provider] = ... let options: [OAuth.Option: Sendable] = [.applicationTag: "com.bundle.identifier"] - let oauth: OAuth = .init(providers: providers, options: options) + let oauth: OAuth = await .init(providers: providers, options: options) ``` diff --git a/Sources/OAuthKit/Extensions/Collection+Extensions.swift b/Sources/OAuthKit/Extensions/Collection+Extensions.swift index 95cb424..2c5dae2 100644 --- a/Sources/OAuthKit/Extensions/Collection+Extensions.swift +++ b/Sources/OAuthKit/Extensions/Collection+Extensions.swift @@ -9,8 +9,9 @@ import Foundation extension Collection { + /// Returns true if the collection is not empty. @inlinable public var isNotEmpty: Bool { - return !isEmpty + !isEmpty } } diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index d60972c..58380ca 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -204,8 +204,7 @@ public final class OAuth: NSObject { /// The url session to use for communicating with providers. @ObservationIgnored private lazy var urlSession: URLSession = { - let configuration = URLSessionConfiguration.default - return URLSession(configuration: URLSessionConfiguration.default) + .init(configuration: .default) }() @ObservationIgnored diff --git a/Sources/OAuthKit/Views/OAWebViewCoordinator.swift b/Sources/OAuthKit/Views/OAWebViewCoordinator.swift index acfc2e6..260ca11 100644 --- a/Sources/OAuthKit/Views/OAWebViewCoordinator.swift +++ b/Sources/OAuthKit/Views/OAWebViewCoordinator.swift @@ -17,7 +17,7 @@ public class OAWebViewCoordinator: NSObject { /// The oauth reference. var oauth: OAuth { - return webView.oauth + webView.oauth } /// Initializer diff --git a/Tests/OAuthKitTests/CodableTests.swift b/Tests/OAuthKitTests/CodableTests.swift new file mode 100644 index 0000000..1b72644 --- /dev/null +++ b/Tests/OAuthKitTests/CodableTests.swift @@ -0,0 +1,28 @@ +// +// CodeableTests.swift +// OAuthKit +// +// Created by Kevin McKee +// + +import Foundation +@testable import OAuthKit +import Testing + +@Suite("Codable Tests") +struct CodableTests { + + private let encoder: JSONEncoder = .init() + private let decoder: JSONDecoder = .init() + + @Test("Encoding and Decoding Tokens") + func whenEncodingDecodingTokens() async throws { + + let token: OAuth.Token = .init(accessToken: UUID().uuidString, refreshToken: UUID().uuidString, expiresIn: 3600, state: "xyz", type: "bearer") + + let data = try encoder.encode(token) + let decoded: OAuth.Token = try decoder.decode(OAuth.Token.self, from: data) + #expect(token == decoded) + } + +} diff --git a/Tests/OAuthKitTests/KeychainTests.swift b/Tests/OAuthKitTests/KeychainTests.swift index a792459..c07e6a3 100644 --- a/Tests/OAuthKitTests/KeychainTests.swift +++ b/Tests/OAuthKitTests/KeychainTests.swift @@ -19,14 +19,14 @@ final class KeychainTests { func whenStoring() async throws { let keychain = Keychain.default let key = "Github" - let token = OAuth.Token(accessToken: "1234", refreshToken: nil, expiresIn: 3600, state: "x", type: "bearer") + let token: OAuth.Token = .init(accessToken: "1234", refreshToken: nil, expiresIn: 3600, state: "x", type: "bearer") let inserted = try! keychain.set(token, for: key) #expect(inserted == true) let found: OAuth.Token = try! keychain.get(key: key)! - #expect(token.accessToken != nil) + #expect(token.accessToken.isNotEmpty) #expect(token.accessToken == found.accessToken) #expect(token.expiresIn == found.expiresIn) #expect(token.state == found.state) diff --git a/Tests/OAuthKitTests/OAuthTests.swift b/Tests/OAuthKitTests/OAuthTests.swift index 0ace4d3..055d79e 100644 --- a/Tests/OAuthKitTests/OAuthTests.swift +++ b/Tests/OAuthKitTests/OAuthTests.swift @@ -11,10 +11,16 @@ import Testing @Suite("OAuth Tests", .tags(.oauth)) final class OAuthTests { + let oauth: OAuth + + /// Initializer. + init() async throws { + oauth = await .init(.module) + } + /// Tests the init method using a custom bundle. @Test("Initializing providers") func whenInitializing() async throws { - let oauth: OAuth = await .init(.module) let providers = await oauth.providers #expect(providers.isNotEmpty) } @@ -29,4 +35,27 @@ final class OAuthTests { let timeInterval = expiration - Date.now #expect(timeInterval < 0) } + + /// Tests the authorization request parameters. + @Test("Building Authorization Request") + func whenBuildingAuthorizationRequest() async throws { + let provider = await oauth.providers[0] + let request = provider.request(grantType: .authorizationCode) + #expect(request != nil) + #expect(request!.url!.absoluteString.contains("client_id=")) + #expect(request!.url!.absoluteString.contains("redirect_uri=\(provider.redirectURI!)")) + #expect(request!.url!.absoluteString.contains("response_type=code")) + } + + /// Tests the refresh token request parameters. + @Test("Building Refresh Token Request") + func whenBuildingRefreshTokenRequest() async throws { + let provider = await oauth.providers[0] + let token: OAuth.Token = .init(accessToken: UUID().uuidString, refreshToken: UUID().uuidString, expiresIn: 3600, state: nil, type: "bearer") + let request = provider.request(grantType: .refreshToken, token: token) + #expect(request != nil) + #expect(request!.url!.absoluteString.contains("client_id=")) + #expect(request!.url!.absoluteString.contains("grant_type=refresh_token")) + #expect(request!.url!.absoluteString.contains("refresh_token=\(token.refreshToken!)")) + } }