@@ -11,11 +11,13 @@ import XCTest
11
11
@testable import Amplify
12
12
@testable import AWSCognitoAuthPlugin
13
13
import AuthenticationServices
14
+ import AWSCognitoIdentityProvider
14
15
15
16
class AWSAuthHostedUISignInTests : XCTestCase {
16
17
17
- var plugin : AWSCognitoAuthPlugin ?
18
+ var plugin : AWSCognitoAuthPlugin !
18
19
let networkTimeout = TimeInterval ( 5 )
20
+ var mockIdentityProvider : CognitoUserPoolBehavior !
19
21
var mockHostedUIResult : Result < [ URLQueryItem ] , HostedUIError > !
20
22
var mockTokenResult = [ " id_token " : AWSCognitoUserPoolTokens . testData. idToken,
21
23
" access_token " : AWSCognitoUserPoolTokens . testData. accessToken,
@@ -57,11 +59,15 @@ class AWSAuthHostedUISignInTests: XCTestCase {
57
59
hostedUISessionFactory: sessionFactory,
58
60
urlSessionFactory: urlSessionMock,
59
61
randomStringFactory: mockRandomString)
60
- let authEnvironment = Defaults . makeDefaultAuthEnvironment ( hostedUIEnvironment: environment)
61
- let stateMachine = Defaults . authStateMachineWith ( environment: authEnvironment,
62
- initialState: initialState)
62
+ let authEnvironment = Defaults . makeDefaultAuthEnvironment (
63
+ userPoolFactory: { self . mockIdentityProvider } ,
64
+ hostedUIEnvironment: environment)
65
+ let stateMachine = Defaults . authStateMachineWith (
66
+ environment: authEnvironment,
67
+ initialState: initialState
68
+ )
63
69
64
- plugin? . configure (
70
+ plugin. configure (
65
71
authConfiguration: Defaults . makeDefaultAuthConfigData ( withHostedUI: configuration) ,
66
72
authEnvironment: authEnvironment,
67
73
authStateMachine: stateMachine,
@@ -76,16 +82,16 @@ class AWSAuthHostedUISignInTests: XCTestCase {
76
82
. init( name: " state " , value: mockState) ,
77
83
. init( name: " code " , value: mockProof)
78
84
] )
79
- let result = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
80
- XCTAssertTrue ( result! . isSignedIn)
85
+ let result = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
86
+ XCTAssertTrue ( result. isSignedIn)
81
87
}
82
88
83
89
@MainActor
84
90
func testUserCancelSignIn( ) async {
85
91
mockHostedUIResult = . failure( . cancelled)
86
92
let expectation = expectation ( description: " SignIn operation should complete " )
87
93
do {
88
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
94
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
89
95
XCTFail ( " Should not succeed " )
90
96
} catch {
91
97
guard case AuthError . service( _, _, let underlyingError) = error,
@@ -103,7 +109,7 @@ class AWSAuthHostedUISignInTests: XCTestCase {
103
109
mockHostedUIResult = . failure( . cancelled)
104
110
let errorExpectation = expectation ( description: " SignIn operation should complete " )
105
111
do {
106
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
112
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
107
113
XCTFail ( " Should not succeed " )
108
114
} catch {
109
115
guard case AuthError . service( _, _, let underlyingError) = error,
@@ -121,8 +127,8 @@ class AWSAuthHostedUISignInTests: XCTestCase {
121
127
] )
122
128
let signInExpectation = expectation ( description: " SignIn operation should complete " )
123
129
do {
124
- let result = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
125
- XCTAssertTrue ( result! . isSignedIn)
130
+ let result = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
131
+ XCTAssertTrue ( result. isSignedIn)
126
132
signInExpectation. fulfill ( )
127
133
} catch {
128
134
XCTFail ( " Should not fail with error = \( error) " )
@@ -138,7 +144,7 @@ class AWSAuthHostedUISignInTests: XCTestCase {
138
144
] )
139
145
let expectation = expectation ( description: " SignIn operation should complete " )
140
146
do {
141
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
147
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
142
148
XCTFail ( " Should not succeed " )
143
149
} catch {
144
150
guard case AuthError . service = error else {
@@ -155,7 +161,7 @@ class AWSAuthHostedUISignInTests: XCTestCase {
155
161
mockHostedUIResult = . failure( . invalidContext)
156
162
let expectation = expectation ( description: " SignIn operation should complete " )
157
163
do {
158
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
164
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
159
165
XCTFail ( " Should not succeed " )
160
166
} catch {
161
167
guard case AuthError . invalidState = error else {
@@ -183,7 +189,7 @@ class AWSAuthHostedUISignInTests: XCTestCase {
183
189
184
190
let expectation = expectation ( description: " SignIn operation should complete " )
185
191
do {
186
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
192
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
187
193
XCTFail ( " Should not succeed " )
188
194
} catch {
189
195
guard case AuthError . service = error else {
@@ -211,7 +217,7 @@ class AWSAuthHostedUISignInTests: XCTestCase {
211
217
212
218
let expectation = expectation ( description: " SignIn operation should complete " )
213
219
do {
214
- _ = try await plugin? . signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
220
+ _ = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
215
221
XCTFail ( " Should not succeed " )
216
222
} catch {
217
223
guard case AuthError . service = error else {
@@ -223,4 +229,53 @@ class AWSAuthHostedUISignInTests: XCTestCase {
223
229
wait ( for: [ expectation] , timeout: networkTimeout)
224
230
}
225
231
232
+
233
+
234
+ /// Test a signIn restart while another sign in is in progress
235
+ ///
236
+ /// - Given: Given an auth plugin with mocked service and a in progress signIn waiting for SMS verification
237
+ ///
238
+ /// - When:
239
+ /// - I invoke another signIn with valid values
240
+ /// - Then:
241
+ /// - I should get a .done response
242
+ ///
243
+ @MainActor
244
+ func testRestartSignInWithWebUI( ) async {
245
+
246
+ self . mockIdentityProvider = MockIdentityProvider ( mockInitiateAuthResponse: { _ in
247
+ InitiateAuthOutputResponse (
248
+ authenticationResult: . none,
249
+ challengeName: . passwordVerifier,
250
+ challengeParameters: InitiateAuthOutputResponse . validChalengeParams,
251
+ session: " someSession " )
252
+ } , mockRespondToAuthChallengeResponse: { _ in
253
+ RespondToAuthChallengeOutputResponse (
254
+ authenticationResult: . none,
255
+ challengeName: . smsMfa,
256
+ challengeParameters: [ : ] ,
257
+ session: " session " )
258
+ } )
259
+
260
+ let pluginOptions = AWSAuthSignInOptions ( validationData: [ " somekey " : " somevalue " ] ,
261
+ metadata: [ " somekey " : " somevalue " ] )
262
+ let options = AuthSignInRequest . Options ( pluginOptions: pluginOptions)
263
+
264
+ do {
265
+ let result = try await plugin. signIn ( username: " username " , password: " password " , options: options)
266
+ guard case . confirmSignInWithSMSMFACode = result. nextStep else {
267
+ XCTFail ( " Result should be .confirmSignInWithSMSMFACode for next step " )
268
+ return
269
+ }
270
+ XCTAssertFalse ( result. isSignedIn)
271
+ mockHostedUIResult = . success( [
272
+ . init( name: " state " , value: mockState) ,
273
+ . init( name: " code " , value: mockProof)
274
+ ] )
275
+ let result2 = try await plugin. signInWithWebUI ( presentationAnchor: ASPresentationAnchor ( ) , options: nil )
276
+ XCTAssertTrue ( result2. isSignedIn)
277
+ } catch {
278
+ XCTFail ( " Received failure with error \( error) " )
279
+ }
280
+ }
226
281
}
0 commit comments