@@ -170,6 +170,123 @@ void main() {
170
170
skip: kIsWeb || defaultTargetPlatform != TargetPlatform .android,
171
171
);
172
172
173
+ test (
174
+ 'should enroll and unenroll factor with signing out in the middle' ,
175
+ () async {
176
+ String email = generateRandomEmail ();
177
+
178
+ String testPhoneNumber = '+441444555626' ;
179
+ User ? user;
180
+ UserCredential userCredential;
181
+
182
+ userCredential =
183
+ await FirebaseAuth .instance.createUserWithEmailAndPassword (
184
+ email: email,
185
+ password: testPassword,
186
+ );
187
+ user = userCredential.user;
188
+
189
+ await user! .sendEmailVerification ();
190
+ final oobCode = (await emulatorOutOfBandCode (
191
+ email,
192
+ EmulatorOobCodeType .verifyEmail,
193
+ ))! ;
194
+
195
+ await emulatorVerifyEmail (
196
+ oobCode.oobCode! ,
197
+ );
198
+
199
+ await FirebaseAuth .instance.signOut ();
200
+
201
+ await FirebaseAuth .instance.signInWithEmailAndPassword (
202
+ email: email,
203
+ password: testPassword,
204
+ );
205
+
206
+ final multiFactor = user.multiFactor;
207
+ final session = await multiFactor.getSession ();
208
+
209
+ Future <String > getCredential () async {
210
+ Completer completer = Completer <String >();
211
+
212
+ unawaited (
213
+ FirebaseAuth .instance.verifyPhoneNumber (
214
+ phoneNumber: testPhoneNumber,
215
+ multiFactorSession: session,
216
+ verificationCompleted: (PhoneAuthCredential credential) {
217
+ if (! completer.isCompleted) {
218
+ return completer.completeError (
219
+ Exception (
220
+ 'verificationCompleted should not have been called' ,
221
+ ),
222
+ );
223
+ }
224
+ },
225
+ verificationFailed: (FirebaseException e) {
226
+ if (! completer.isCompleted) {
227
+ return completer.completeError (
228
+ Exception (
229
+ 'verificationFailed should not have been called' ,
230
+ ),
231
+ );
232
+ }
233
+ },
234
+ codeSent: (String verificationId, int ? resetToken) {
235
+ completer.complete (verificationId);
236
+ },
237
+ codeAutoRetrievalTimeout: (String foo) {
238
+ if (! completer.isCompleted) {
239
+ return completer.completeError (
240
+ Exception (
241
+ 'codeAutoRetrievalTimeout should not have been called' ,
242
+ ),
243
+ );
244
+ }
245
+ },
246
+ ),
247
+ );
248
+
249
+ return completer.future as FutureOr <String >;
250
+ }
251
+
252
+ final verificationId = await getCredential ();
253
+
254
+ final smsCode = await emulatorPhoneVerificationCode (
255
+ testPhoneNumber,
256
+ );
257
+
258
+ final credential = PhoneAuthProvider .credential (
259
+ verificationId: verificationId,
260
+ smsCode: smsCode! ,
261
+ );
262
+
263
+ expect (credential, isA <PhoneAuthCredential >());
264
+
265
+ await user.multiFactor.enroll (
266
+ PhoneMultiFactorGenerator .getAssertion (
267
+ credential,
268
+ ),
269
+ displayName: 'My phone number' ,
270
+ );
271
+
272
+ final enrolledFactors = await multiFactor.getEnrolledFactors ();
273
+
274
+ // Assertions
275
+ expect (enrolledFactors.length, 1 );
276
+ expect (enrolledFactors.first.displayName, 'My phone number' );
277
+
278
+ await user.multiFactor.unenroll (
279
+ multiFactorInfo: enrolledFactors.first,
280
+ );
281
+
282
+ final enrolledFactorsAfter = await multiFactor.getEnrolledFactors ();
283
+
284
+ // Assertions
285
+ expect (enrolledFactorsAfter.length, 0 );
286
+ },
287
+ skip: kIsWeb || defaultTargetPlatform != TargetPlatform .android,
288
+ );
289
+
173
290
test (
174
291
'should enroll and throw if trying to unenroll an unknown factor' ,
175
292
() async {
0 commit comments