@@ -227,6 +227,153 @@ describe('SignInFactorOne', () => {
227
227
} ) ;
228
228
} ) ;
229
229
} ) ;
230
+
231
+ it ( 'Prompts the user to reset their password via email if it has been pwned' , async ( ) => {
232
+ const { wrapper, fixtures } = await createFixtures ( f => {
233
+ f . withEmailAddress ( ) ;
234
+ f . withPassword ( ) ;
235
+ f . withPreferredSignInStrategy ( { strategy : 'password' } ) ;
236
+ f . startSignInWithEmailAddress ( {
237
+ supportPassword : true ,
238
+ supportEmailCode : true ,
239
+ supportResetPassword : true ,
240
+ } ) ;
241
+ } ) ;
242
+ fixtures . signIn . prepareFirstFactor . mockReturnValueOnce ( Promise . resolve ( { } as SignInResource ) ) ;
243
+
244
+ const errJSON = {
245
+ code : 'form_password_pwned' ,
246
+ long_message :
247
+ 'Password has been found in an online data breach. For account safety, please reset your password.' ,
248
+ message : 'Password has been found in an online data breach. For account safety, please reset your password.' ,
249
+ meta : { param_name : 'password' } ,
250
+ } ;
251
+
252
+ fixtures . signIn . attemptFirstFactor . mockRejectedValueOnce (
253
+ new ClerkAPIResponseError ( 'Error' , {
254
+ data : [ errJSON ] ,
255
+ status : 422 ,
256
+ } ) ,
257
+ ) ;
258
+
259
+ await runFakeTimers ( async ( ) => {
260
+ const { userEvent } = render ( < SignInFactorOne /> , { wrapper } ) ;
261
+ await userEvent . type ( screen . getByLabelText ( 'Password' ) , '123456' ) ;
262
+ await userEvent . click ( screen . getByText ( 'Continue' ) ) ;
263
+
264
+ await waitFor ( ( ) => {
265
+ screen . getByText ( 'Password compromised' ) ;
266
+ screen . getByText (
267
+ 'This password has been found as part of a breach and can not be used, please reset your password.' ,
268
+ ) ;
269
+ screen . getByText ( 'Or, sign in with another method' ) ;
270
+ } ) ;
271
+
272
+ await userEvent . click ( screen . getByText ( 'Reset your password' ) ) ;
273
+ screen . getByText ( 'First, enter the code sent to your email ID' ) ;
274
+ } ) ;
275
+ } ) ;
276
+
277
+ it ( 'Prompts the user to reset their password via phone if it has been pwned' , async ( ) => {
278
+ const { wrapper, fixtures } = await createFixtures ( f => {
279
+ f . withEmailAddress ( ) ;
280
+ f . withPassword ( ) ;
281
+ f . withPreferredSignInStrategy ( { strategy : 'password' } ) ;
282
+ f . startSignInWithPhoneNumber ( {
283
+ supportPassword : true ,
284
+ supportPhoneCode : true ,
285
+ supportResetPassword : true ,
286
+ } ) ;
287
+ } ) ;
288
+ fixtures . signIn . prepareFirstFactor . mockReturnValueOnce ( Promise . resolve ( { } as SignInResource ) ) ;
289
+
290
+ const errJSON = {
291
+ code : 'form_password_pwned' ,
292
+ long_message :
293
+ 'Password has been found in an online data breach. For account safety, please reset your password.' ,
294
+ message : 'Password has been found in an online data breach. For account safety, please reset your password.' ,
295
+ meta : { param_name : 'password' } ,
296
+ } ;
297
+
298
+ fixtures . signIn . attemptFirstFactor . mockRejectedValueOnce (
299
+ new ClerkAPIResponseError ( 'Error' , {
300
+ data : [ errJSON ] ,
301
+ status : 422 ,
302
+ } ) ,
303
+ ) ;
304
+
305
+ await runFakeTimers ( async ( ) => {
306
+ const { userEvent } = render ( < SignInFactorOne /> , { wrapper } ) ;
307
+ await userEvent . type ( screen . getByLabelText ( 'Password' ) , '123456' ) ;
308
+ await userEvent . click ( screen . getByText ( 'Continue' ) ) ;
309
+
310
+ await waitFor ( ( ) => {
311
+ screen . getByText ( 'Password compromised' ) ;
312
+ screen . getByText (
313
+ 'This password has been found as part of a breach and can not be used, please reset your password.' ,
314
+ ) ;
315
+ screen . getByText ( 'Or, sign in with another method' ) ;
316
+ } ) ;
317
+
318
+ await userEvent . click ( screen . getByText ( 'Reset your password' ) ) ;
319
+ screen . getByText ( 'First, enter the code sent to your phone' ) ;
320
+ } ) ;
321
+ } ) ;
322
+
323
+ it ( 'entering a pwned password, then going back and clicking forgot password should result in the correct title' , async ( ) => {
324
+ const { wrapper, fixtures } = await createFixtures ( f => {
325
+ f . withEmailAddress ( ) ;
326
+ f . withPassword ( ) ;
327
+ f . withPreferredSignInStrategy ( { strategy : 'password' } ) ;
328
+ f . startSignInWithEmailAddress ( {
329
+ supportPassword : true ,
330
+ supportEmailCode : true ,
331
+ supportResetPassword : true ,
332
+ } ) ;
333
+ } ) ;
334
+ fixtures . signIn . prepareFirstFactor . mockReturnValueOnce ( Promise . resolve ( { } as SignInResource ) ) ;
335
+
336
+ const errJSON = {
337
+ code : 'form_password_pwned' ,
338
+ long_message :
339
+ 'Password has been found in an online data breach. For account safety, please reset your password.' ,
340
+ message : 'Password has been found in an online data breach. For account safety, please reset your password.' ,
341
+ meta : { param_name : 'password' } ,
342
+ } ;
343
+
344
+ fixtures . signIn . attemptFirstFactor . mockRejectedValueOnce (
345
+ new ClerkAPIResponseError ( 'Error' , {
346
+ data : [ errJSON ] ,
347
+ status : 422 ,
348
+ } ) ,
349
+ ) ;
350
+
351
+ await runFakeTimers ( async ( ) => {
352
+ const { userEvent } = render ( < SignInFactorOne /> , { wrapper } ) ;
353
+ await userEvent . type ( screen . getByLabelText ( 'Password' ) , '123456' ) ;
354
+ await userEvent . click ( screen . getByText ( 'Continue' ) ) ;
355
+
356
+ await waitFor ( ( ) => {
357
+ screen . getByText ( 'Password compromised' ) ;
358
+ screen . getByText (
359
+ 'This password has been found as part of a breach and can not be used, please reset your password.' ,
360
+ ) ;
361
+ screen . getByText ( 'Or, sign in with another method' ) ;
362
+ } ) ;
363
+
364
+ // Go back
365
+ await userEvent . click ( screen . getByText ( 'Back' ) ) ;
366
+
367
+ // Choose to reset password via "Forgot password" instead
368
+ await userEvent . click ( screen . getByText ( / F o r g o t p a s s w o r d / i) ) ;
369
+ screen . getByText ( 'Forgot Password?' ) ;
370
+ expect (
371
+ screen . queryByText (
372
+ 'This password has been found as part of a breach and can not be used, please reset your password.' ,
373
+ ) ,
374
+ ) . not . toBeInTheDocument ( ) ;
375
+ } ) ;
376
+ } ) ;
230
377
} ) ;
231
378
232
379
describe ( 'Forgot Password' , ( ) => {
0 commit comments