16
16
*/
17
17
18
18
// eslint-disable-next-line import/no-extraneous-dependencies
19
- import { OperationType , UserCredential } from '@firebase/auth-exp' ;
20
- import { expect } from 'chai' ;
21
- import { TestFunction } from './util/auth_driver' ;
19
+ import { OperationType , UserCredential , User , OAuthCredential } from '@firebase/auth-exp' ;
20
+ import { expect , use } from 'chai' ;
22
21
import { IdPPage } from './util/idp_page' ;
22
+ import * as chaiAsPromised from 'chai-as-promised' ;
23
23
import { browserDescribe } from './util/test_runner' ;
24
+ import { AnonFunction , CoreFunction , RedirectFunction } from './util/functions' ;
25
+
26
+ use ( chaiAsPromised ) ;
24
27
25
28
browserDescribe ( 'WebDriver redirect IdP test' , driver => {
26
- it ( 'allows users to sign in' , async ( ) => {
29
+ beforeEach ( async ( ) => {
27
30
await driver . pause ( 200 ) ; // Race condition on auth init
28
- await driver . callNoWait ( TestFunction . IDP_REDIRECT ) ;
31
+ } ) ;
32
+
33
+ it ( 'allows users to sign in' , async ( ) => {
34
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
29
35
const widget = new IdPPage ( driver . webDriver ) ;
30
36
31
37
// We're now on the widget page; wait for load
@@ -38,16 +44,194 @@ browserDescribe('WebDriver redirect IdP test', driver => {
38
44
await widget . clickSignIn ( ) ;
39
45
40
46
await driver . reinitOnRedirect ( ) ;
41
-
42
47
const currentUser = await driver . getUserSnapshot ( ) ;
43
48
expect ( currentUser . email ) . to . eq ( '[email protected] ' ) ;
44
49
expect ( currentUser . displayName ) . to . eq ( 'Bob Test' ) ;
45
50
expect ( currentUser . photoURL ) . to . eq ( 'http://bob.test/bob.png' ) ;
46
51
47
52
const redirectResult : UserCredential = await driver . call (
48
- TestFunction . REDIRECT_RESULT
53
+ RedirectFunction . REDIRECT_RESULT
49
54
) ;
50
55
expect ( redirectResult . operationType ) . to . eq ( OperationType . SIGN_IN ) ;
51
56
expect ( redirectResult . user ) . to . eql ( currentUser ) ;
52
57
} ) ;
58
+
59
+
60
+ it ( 'can link with another account account' , async ( ) => {
61
+ // First, sign in anonymously
62
+ const { user : anonUser } : UserCredential = await driver . call ( AnonFunction . SIGN_IN_ANONYMOUSLY ) ;
63
+
64
+ // Then, link with redirect
65
+ driver . callNoWait ( RedirectFunction . IDP_LINK_REDIRECT ) ;
66
+ const widget = new IdPPage ( driver . webDriver ) ;
67
+ await widget . pageLoad ( ) ;
68
+ await widget . clickAddAccount ( ) ;
69
+ await widget . fillEmail ( '[email protected] ' ) ;
70
+ await widget . clickSignIn ( ) ;
71
+
72
+ await driver . reinitOnRedirect ( ) ;
73
+ // Back on page; check for the current user matching the anonymous account
74
+ // as well as the new IdP account
75
+ const user : User = await driver . getUserSnapshot ( ) ;
76
+ expect ( user . uid ) . to . eq ( anonUser . uid ) ;
77
+ expect ( user . email ) . to . eq ( '[email protected] ' ) ;
78
+ } ) ;
79
+
80
+ it ( 'can be converted to a credential' , async ( ) => {
81
+ // Start with redirect
82
+ driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
83
+ const widget = new IdPPage ( driver . webDriver ) ;
84
+ await widget . pageLoad ( ) ;
85
+ await widget . clickAddAccount ( ) ;
86
+ await widget . fillEmail ( '[email protected] ' ) ;
87
+ await widget . clickSignIn ( ) ;
88
+
89
+ // Generate a credential, then store it on the window before logging out
90
+ await driver . reinitOnRedirect ( ) ;
91
+ const first = await driver . getUserSnapshot ( ) ;
92
+ const cred : OAuthCredential = await driver . call ( RedirectFunction . GENERATE_CREDENTIAL_FROM_RESULT ) ;
93
+ expect ( cred . accessToken ) . to . be . a ( 'string' ) ;
94
+ expect ( cred . idToken ) . to . be . a ( 'string' ) ;
95
+ expect ( cred . signInMethod ) . to . eq ( 'google.com' ) ;
96
+
97
+ // We've now generated that credential. Sign out and sign back in using it
98
+ await driver . call ( CoreFunction . SIGN_OUT ) ;
99
+ const { user : second } : UserCredential = await driver . call ( RedirectFunction . SIGN_IN_WITH_REDIRECT_CREDENTIAL ) ;
100
+ expect ( second . uid ) . to . eq ( first . uid ) ;
101
+ expect ( second . providerData ) . to . eql ( first . providerData ) ;
102
+ } ) ;
103
+
104
+ it ( 'handles account exists different credential errors' , async ( ) => {
105
+ // Start with redirect and a verified account
106
+ driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
107
+ const widget = new IdPPage ( driver . webDriver ) ;
108
+ await widget . pageLoad ( ) ;
109
+ await widget . clickAddAccount ( ) ;
110
+ await widget . fillEmail ( '[email protected] ' ) ;
111
+ await widget . clickSignIn ( ) ;
112
+ await driver . reinitOnRedirect ( ) ;
113
+
114
+ const original = await driver . getUserSnapshot ( ) ;
115
+ expect ( original . emailVerified ) . to . be . true ;
116
+
117
+ // Try to sign in with an unverified Facebook account
118
+ // TODO: Convert this to the widget once unverified accounts work
119
+ // Come back and verify error / prepare for link
120
+ await expect ( driver . call ( RedirectFunction . TRY_TO_SIGN_IN_UNVERIFIED , '"[email protected] "' ) ) . to . be . rejected . and . eventually . have . property ( 'code' , 'auth/account-exists-with-different-credential' ) ;
121
+
122
+ // Now do the link
123
+ await driver . call ( RedirectFunction . LINK_WITH_ERROR_CREDENTIAL ) ;
124
+
125
+ // Check the user for both providers
126
+ const user = await driver . getUserSnapshot ( ) ;
127
+ expect ( user . uid ) . to . eq ( original . uid ) ;
128
+ expect ( user . providerData . map ( d => d . providerId ) ) . to . have . members ( [ 'google.com' , 'facebook.com' ] ) ;
129
+ } ) ;
130
+
131
+ context ( 'with existing user' , ( ) => {
132
+ let user1 : User ;
133
+ let user2 : User ;
134
+
135
+ beforeEach ( async ( ) => {
136
+ // Create a couple existing users
137
+ let cred :
UserCredential = await driver . call ( RedirectFunction . CREATE_FAKE_GOOGLE_USER , '"[email protected] "' ) ;
138
+ user1 = cred . user ;
139
+ cred = await driver . call ( RedirectFunction . CREATE_FAKE_GOOGLE_USER , '"[email protected] "' ) ;
140
+ user2 = cred . user ;
141
+ await driver . call ( CoreFunction . SIGN_OUT ) ;
142
+ } ) ;
143
+
144
+ it ( 'a user can sign in again' , async ( ) => {
145
+ // Sign in using pre-poulated user
146
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
147
+
148
+ // This time, select an existing account
149
+ const widget = new IdPPage ( driver . webDriver ) ;
150
+ await widget . pageLoad ( ) ;
151
+ await widget . selectExistingAccountByEmail ( user1 . email ! ) ;
152
+
153
+ // Double check the new sign in matches the old
154
+ await driver . reinitOnRedirect ( ) ;
155
+ const user = await driver . getUserSnapshot ( ) ;
156
+ expect ( user . uid ) . to . eq ( user1 . uid ) ;
157
+ expect ( user . email ) . to . eq ( user1 . email ) ;
158
+ } ) ;
159
+
160
+ it ( 'reauthenticate works for the correct user' , async ( ) => {
161
+ // Sign in using pre-poulated user
162
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
163
+
164
+ const widget = new IdPPage ( driver . webDriver ) ;
165
+ await widget . pageLoad ( ) ;
166
+ await widget . selectExistingAccountByEmail ( user1 . email ! ) ;
167
+
168
+ // Double check the new sign in matches the old
169
+ await driver . reinitOnRedirect ( ) ;
170
+ let user = await driver . getUserSnapshot ( ) ;
171
+ expect ( user . uid ) . to . eq ( user1 . uid ) ;
172
+ expect ( user . email ) . to . eq ( user1 . email ) ;
173
+
174
+ // Reauthenticate specifically
175
+ await driver . callNoWait ( RedirectFunction . IDP_REAUTH_REDIRECT ) ;
176
+ await widget . pageLoad ( ) ;
177
+ await widget . selectExistingAccountByEmail ( user1 . email ! ) ;
178
+
179
+ await driver . reinitOnRedirect ( ) ;
180
+ user = await driver . getUserSnapshot ( ) ;
181
+ expect ( user . uid ) . to . eq ( user1 . uid ) ;
182
+ expect ( user . email ) . to . eq ( user1 . email ) ;
183
+ } )
184
+
185
+ it ( 'reauthenticate throws for wrong user' , async ( ) => {
186
+ // Sign in using pre-poulated user
187
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
188
+
189
+ const widget = new IdPPage ( driver . webDriver ) ;
190
+ await widget . pageLoad ( ) ;
191
+ await widget . selectExistingAccountByEmail ( user1 . email ! ) ;
192
+
193
+ // Immediately reauth but with the wrong user
194
+ await driver . reinitOnRedirect ( ) ;
195
+ await driver . callNoWait ( RedirectFunction . IDP_REAUTH_REDIRECT ) ;
196
+ await widget . pageLoad ( ) ;
197
+ await widget . selectExistingAccountByEmail ( user2 . email ! ) ;
198
+
199
+ await driver . reinitOnRedirect ( ) ;
200
+ await expect ( driver . call ( RedirectFunction . REDIRECT_RESULT ) ) . to . be . rejected . and . eventually . have . property ( 'code' , 'auth/user-mismatch' ) ;
201
+ } ) ;
202
+
203
+ it ( 'handles aborted sign ins' , async ( ) => {
204
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
205
+ const widget = new IdPPage ( driver . webDriver ) ;
206
+
207
+ // Don't actually sign in; go back to the previous page
208
+ await widget . pageLoad ( ) ;
209
+ await driver . goToTestPage ( ) ;
210
+ await driver . reinitOnRedirect ( ) ;
211
+ expect ( await driver . getUserSnapshot ( ) ) . to . be . null ;
212
+
213
+ // Now do sign in
214
+ await driver . callNoWait ( RedirectFunction . IDP_REDIRECT ) ;
215
+ // Use user1
216
+ await widget . pageLoad ( ) ;
217
+ await widget . selectExistingAccountByEmail ( user1 . email ! ) ;
218
+
219
+ // Ensure the user was signed in...
220
+ await driver . reinitOnRedirect ( ) ;
221
+ let user = await driver . getUserSnapshot ( ) ;
222
+ expect ( user . uid ) . to . eq ( user1 . uid ) ;
223
+ expect ( user . email ) . to . eq ( user1 . email ) ;
224
+
225
+ // Now open another sign in, but return
226
+ await driver . callNoWait ( RedirectFunction . IDP_REAUTH_REDIRECT ) ;
227
+ await widget . pageLoad ( ) ;
228
+ await driver . goToTestPage ( ) ;
229
+ await driver . reinitOnRedirect ( ) ;
230
+
231
+ // Make sure state remained
232
+ user = await driver . getUserSnapshot ( ) ;
233
+ expect ( user . uid ) . to . eq ( user1 . uid ) ;
234
+ expect ( user . email ) . to . eq ( user1 . email ) ;
235
+ } ) ;
236
+ } ) ;
53
237
} ) ;
0 commit comments