Skip to content

Commit 4a796c4

Browse files
authored
test: Adding additional unit tests for Auth, Push Notifications and Storage plugins (#3291)
1 parent b6f5bc9 commit 4a796c4

File tree

26 files changed

+4637
-199
lines changed

26 files changed

+4637
-199
lines changed

.swiftpm/xcode/xcshareddata/xcschemes/AWSCognitoAuthPlugin.xcscheme

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,6 @@
4848
BlueprintName = "AWSCognitoAuthPluginUnitTests"
4949
ReferencedContainer = "container:">
5050
</BuildableReference>
51-
<SkippedTests>
52-
<Test
53-
Identifier = "EscapeHatchTests">
54-
</Test>
55-
</SkippedTests>
5651
</TestableReference>
5752
<TestableReference
5853
skipped = "NO">

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AWSAuthCognitoSession.swift

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,6 @@ public struct AWSAuthCognitoSession: AuthSession,
7676

7777
}
7878

79-
/// Internal Helpers for managing session tokens
80-
internal extension AWSAuthCognitoSession {
81-
func areTokensExpiring(in seconds: TimeInterval? = nil) -> Bool {
82-
83-
guard let tokens = try? userPoolTokensResult.get(),
84-
let idTokenClaims = try? AWSAuthService().getTokenClaims(tokenString: tokens.idToken).get(),
85-
let accessTokenClaims = try? AWSAuthService().getTokenClaims(tokenString: tokens.idToken).get(),
86-
let idTokenExpiration = idTokenClaims["exp"]?.doubleValue,
87-
let accessTokenExpiration = accessTokenClaims["exp"]?.doubleValue else {
88-
return true
89-
}
90-
91-
// If the session expires < X minutes return it
92-
return (Date(timeIntervalSince1970: idTokenExpiration).compare(Date(timeIntervalSinceNow: seconds ?? 0)) == .orderedDescending &&
93-
Date(timeIntervalSince1970: accessTokenExpiration).compare(Date(timeIntervalSinceNow: seconds ?? 0)) == .orderedDescending)
94-
}
95-
}
96-
9779
extension AWSAuthCognitoSession: Equatable {
9880
public static func == (lhs: AWSAuthCognitoSession, rhs: AWSAuthCognitoSession) -> Bool {
9981
switch (lhs.getCognitoTokens(), rhs.getCognitoTokens()) {

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AWSCognitoUserPoolTokens.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ public struct AWSCognitoUserPoolTokens: AuthCognitoTokens {
6565
case (.some(let idTokenValue), .none):
6666
expirationDoubleValue = idTokenValue
6767
case (.none, .none):
68-
expirationDoubleValue = 0
68+
expirationDoubleValue = Date().timeIntervalSince1970
6969
}
7070

71-
self.expiration = Date().addingTimeInterval(TimeInterval((expirationDoubleValue ?? 0)))
71+
self.expiration = Date(timeIntervalSince1970: TimeInterval(expirationDoubleValue))
7272
}
7373
}
7474

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Helpers/AuthCognitoSignedOutSessionHelper.swift

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,6 @@ struct AuthCognitoSignedOutSessionHelper {
2525
return authSession
2626
}
2727

28-
/// Guest/SignedOut session with any unhandled error
29-
///
30-
/// The unhandled error is passed as identityId and aws credentials result. UserSub and Cognito Tokens will still
31-
/// have signOut error.
32-
///
33-
/// - Parameter error: Unhandled error
34-
/// - Returns: Session will have isSignedIn = false
35-
private static func makeSignedOutSession(withUnhandledError error: AuthError) -> AWSAuthCognitoSession {
36-
37-
let identityIdError = error
38-
let awsCredentialsError = error
39-
40-
let tokensError = makeCognitoTokensSignedOutError()
41-
42-
let authSession = AWSAuthCognitoSession(isSignedIn: false,
43-
identityIdResult: .failure(identityIdError),
44-
awsCredentialsResult: .failure(awsCredentialsError),
45-
cognitoTokensResult: .failure(tokensError))
46-
return authSession
47-
}
48-
4928
/// Guest/SignOut session when the guest access is not enabled.
5029
/// - Returns: Session with isSignedIn = false
5130
static func makeSessionWithNoGuestAccess() -> AWSAuthCognitoSession {
@@ -68,26 +47,6 @@ struct AuthCognitoSignedOutSessionHelper {
6847
return authSession
6948
}
7049

71-
private static func makeOfflineSignedOutSession() -> AWSAuthCognitoSession {
72-
let identityIdError = AuthError.service(
73-
AuthPluginErrorConstants.identityIdOfflineError.errorDescription,
74-
AuthPluginErrorConstants.identityIdOfflineError.recoverySuggestion,
75-
AWSCognitoAuthError.network)
76-
77-
let awsCredentialsError = AuthError.service(
78-
AuthPluginErrorConstants.awsCredentialsOfflineError.errorDescription,
79-
AuthPluginErrorConstants.awsCredentialsOfflineError.recoverySuggestion,
80-
AWSCognitoAuthError.network)
81-
82-
let tokensError = makeCognitoTokensSignedOutError()
83-
84-
let authSession = AWSAuthCognitoSession(isSignedIn: false,
85-
identityIdResult: .failure(identityIdError),
86-
awsCredentialsResult: .failure(awsCredentialsError),
87-
cognitoTokensResult: .failure(tokensError))
88-
return authSession
89-
}
90-
9150
/// Guest/SignedOut session with couldnot retreive either aws credentials or identity id.
9251
/// - Returns: Session will have isSignedIn = false
9352
private static func makeSignedOutSessionWithServiceIssue() -> AWSAuthCognitoSession {
@@ -109,13 +68,6 @@ struct AuthCognitoSignedOutSessionHelper {
10968
return authSession
11069
}
11170

112-
private static func makeUserSubSignedOutError() -> AuthError {
113-
let userSubError = AuthError.signedOut(
114-
AuthPluginErrorConstants.userSubSignOutError.errorDescription,
115-
AuthPluginErrorConstants.userSubSignOutError.recoverySuggestion)
116-
return userSubError
117-
}
118-
11971
private static func makeCognitoTokensSignedOutError() -> AuthError {
12072
let tokensError = AuthError.signedOut(
12173
AuthPluginErrorConstants.cognitoTokensSignOutError.errorDescription,

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIASWebAuthenticationSession.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class HostedUIASWebAuthenticationSession: NSObject, HostedUISessionBehavior {
2222
callback: @escaping (Result<[URLQueryItem], HostedUIError>) -> Void) {
2323
#if os(iOS) || os(macOS)
2424
self.webPresentation = presentationAnchor
25-
let aswebAuthenticationSession = ASWebAuthenticationSession(
25+
let aswebAuthenticationSession = createAuthenticationSession(
2626
url: url,
2727
callbackURLScheme: callbackScheme,
2828
completionHandler: { url, error in
@@ -58,6 +58,16 @@ class HostedUIASWebAuthenticationSession: NSObject, HostedUISessionBehavior {
5858
}
5959

6060
#if os(iOS) || os(macOS)
61+
var authenticationSessionFactory = ASWebAuthenticationSession.init(url:callbackURLScheme:completionHandler:)
62+
63+
private func createAuthenticationSession(
64+
url: URL,
65+
callbackURLScheme: String?,
66+
completionHandler: @escaping ASWebAuthenticationSession.CompletionHandler
67+
) -> ASWebAuthenticationSession {
68+
return authenticationSessionFactory(url, callbackURLScheme, completionHandler)
69+
}
70+
6171
private func convertHostedUIError(_ error: Error) -> HostedUIError {
6272
if let asWebAuthError = error as? ASWebAuthenticationSessionError {
6373
switch asWebAuthError.code {

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ActionTests/CredentialStore/MigrateLegacyCredentialStoreTests.swift

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,122 @@ class MigrateLegacyCredentialStoreTests: XCTestCase {
121121

122122
await fulfillment(
123123
of: [migrationCompletionInvoked],
124+
124125
timeout: 0.1
125126
)
126127
}
128+
129+
/// - Given: A credential store with an invalid environment
130+
/// - When: The migration legacy store action is executed
131+
/// - Then: An error event of type configuration is dispatched
132+
func testExecute_withInvalidEnvironment_shouldDispatchError() async {
133+
let expectation = expectation(description: "noEnvironment")
134+
let action = MigrateLegacyCredentialStore()
135+
await action.execute(
136+
withDispatcher: MockDispatcher { event in
137+
guard let event = event as? CredentialStoreEvent,
138+
case let .throwError(error) = event.eventType else {
139+
XCTFail("Expected failure due to no CredentialEnvironment")
140+
expectation.fulfill()
141+
return
142+
}
143+
XCTAssertEqual(error, .configuration(message: AuthPluginErrorConstants.configurationError))
144+
expectation.fulfill()
145+
},
146+
environment: MockInvalidEnvironment()
147+
)
148+
await fulfillment(of: [expectation], timeout: 1)
149+
}
150+
151+
/// - Given: A credential store with an environment that only has identity pool
152+
/// - When: The migration legacy store action is executed
153+
/// - Then:
154+
/// - A .loadCredentialStore event with type .amplifyCredentials is dispatched
155+
/// - An .identityPoolOnly credential is saved
156+
func testExecute_withoutUserPool_andWithoutLoginsTokens_shouldDispatchLoadEvent() async {
157+
let expectation = expectation(description: "noUserPoolTokens")
158+
let action = MigrateLegacyCredentialStore()
159+
await action.execute(
160+
withDispatcher: MockDispatcher { event in
161+
guard let event = event as? CredentialStoreEvent,
162+
case .loadCredentialStore(let type) = event.eventType else {
163+
XCTFail("Expected .loadCredentialStore")
164+
expectation.fulfill()
165+
return
166+
}
167+
XCTAssertEqual(type, .amplifyCredentials)
168+
expectation.fulfill()
169+
},
170+
environment: CredentialEnvironment(
171+
authConfiguration: .identityPools(.testData),
172+
credentialStoreEnvironment: BasicCredentialStoreEnvironment(
173+
amplifyCredentialStoreFactory: {
174+
MockAmplifyCredentialStoreBehavior(
175+
saveCredentialHandler: { codableCredentials in
176+
guard let amplifyCredentials = codableCredentials as? AmplifyCredentials,
177+
case .identityPoolOnly(_, let credentials) = amplifyCredentials else {
178+
XCTFail("Expected .identityPoolOnly")
179+
return
180+
}
181+
XCTAssertFalse(credentials.sessionToken.isEmpty)
182+
}
183+
)
184+
},
185+
legacyKeychainStoreFactory: { _ in
186+
MockKeychainStoreBehavior(data: "hostedUI")
187+
}),
188+
logger: MigrateLegacyCredentialStore.log
189+
)
190+
)
191+
await fulfillment(of: [expectation], timeout: 1)
192+
}
193+
194+
/// - Given: A credential store with an environment that only has identity pool
195+
/// - When: The migration legacy store action is executed
196+
/// - A .loadCredentialStore event with type .amplifyCredentials is dispatched
197+
/// - An .identityPoolWithFederation credential is saved
198+
func testExecute_withoutUserPool_andWithLoginsTokens_shouldDispatchLoadEvent() async {
199+
let expectation = expectation(description: "noUserPoolTokens")
200+
let action = MigrateLegacyCredentialStore()
201+
await action.execute(
202+
withDispatcher: MockDispatcher { event in
203+
guard let event = event as? CredentialStoreEvent,
204+
case .loadCredentialStore(let type) = event.eventType else {
205+
XCTFail("Expected .loadCredentialStore")
206+
expectation.fulfill()
207+
return
208+
}
209+
XCTAssertEqual(type, .amplifyCredentials)
210+
expectation.fulfill()
211+
},
212+
environment: CredentialEnvironment(
213+
authConfiguration: .identityPools(.testData),
214+
credentialStoreEnvironment: BasicCredentialStoreEnvironment(
215+
amplifyCredentialStoreFactory: {
216+
MockAmplifyCredentialStoreBehavior(
217+
saveCredentialHandler: { codableCredentials in
218+
guard let amplifyCredentials = codableCredentials as? AmplifyCredentials,
219+
case .identityPoolWithFederation(let token, _, _) = amplifyCredentials else {
220+
XCTFail("Expected .identityPoolWithFederation")
221+
return
222+
}
223+
224+
XCTAssertEqual(token.token, "token")
225+
XCTAssertEqual(token.provider.userPoolProviderName, "provider")
226+
}
227+
)
228+
},
229+
legacyKeychainStoreFactory: { _ in
230+
let data = try! JSONEncoder().encode([
231+
"provider": "token"
232+
])
233+
return MockKeychainStoreBehavior(
234+
data: String(decoding: data, as: UTF8.self)
235+
)
236+
}),
237+
logger: action.log
238+
)
239+
)
240+
await fulfillment(of: [expectation], timeout: 1)
241+
}
127242
}

0 commit comments

Comments
 (0)