Test emails and phones
Most of Clerk's sign-in and sign-up flows involve verifying ownership of an email address or phone number via a one time passcode (OTP). To confirm that your integration works correctly, you can simulate verification flows without sending an email or SMS, by using reserved values in test mode.
Verification messages are used during sign-up, sign-in, and when adding an email address or phone number to an existing account.
Setup test mode
Every development instance has "test mode" enabled by default. If you need to use "test mode" on a production instance, you can enable it via the Clerk Dashboard or via the Backend API.
You should not be using "test mode" on any instance that manages actual customers.
Test mode via the Clerk Dashboard
To enable test mode via the Clerk Dashboard, navigate to the Settings page in the Clerk Dashboard. In the Enable test mode section, ensure the toggle is toggled on.
How to use test mode
Once test mode is enabled, all you need to do is use the following test numbers as part of your standard flow.
Email addresses
Any email with the +clerk_test
subaddress is a test email address. No emails will be sent, and they can be verified with the code 424242
.
For example:
jane+clerk_test@example.com
doe+clerk_test@example.com
Phone numbers
Any fictional phone number(opens in a new tab) is a test phone number. No SMS will be sent, and they can all be verified with the code 424242
.
Fictional phone numbers have the following structure:
+1 (XXX) 555-0100
to +1 (XXX) 555-0199
For example:
+12015550100
+19735550133
Email magic links
Testing magic links in E2E suites is an uphill task. We recommend turning on email verification codes, and using that flow to authenticate your tests. The flows are very similar.
Code examples
Testing sign in via email code
const testSignInWithEmailCode = async () => { const { signIn } = useSignIn(); const emailAddress = "john+clerk_test@example.com"; const signInResp = await signIn.create({ identifier: emailAddress }); const { emailAddressId } = signInResp.supportedFirstFactors.find( (ff) => ff.strategy === "email_code" && ff.safeIdentifier === emailAddress )! as EmailCodeFactor; await signIn.prepareFirstFactor({ strategy: "email_code", emailAddressId: emailAddressId, }); const attemptResponse = await signIn.attemptFirstFactor({ strategy: "email_code", code: "424242", }); if (attemptResponse.status == "complete") { console.log("success"); } else { console.log("error"); } };
Testing sign up with phone number
const testSignUpWithPhoneNumber = async () => { const { signUp } = useSignUp(); await signUp.create({ phoneNumber: "+12015550100", }); await signUp.preparePhoneNumberVerification(); const res = await signUp.attemptPhoneNumberVerification({ code: "424242", }); if (res.verifications.phoneNumber.status == "verified") { console.log("success"); } else { console.log("error"); } };