E2E Testing with Cypress
Welcome to the guide on testing Descope flows with Cypress. Whether you are new to end-to-end testing or an experienced tester looking to better understand Descope flows, this guide will provide you with practical knowledge and examples that you can implement straight away. Let's dive in!
Note
This guide covers creating test users manually for testing; however, you can also see our Dynamic Test Users Configuration guide if you would like the ability to create test users dynamically as part of the sign-up-or-in process.
What you'll learn
- Use custom Cypress commands to:
- Programmatically authenticate with Descope
- Authenticate with Descope through the UI
- Including your tests in continuous integration via Github Actions
Cypress Installation
Make sure you have Cypress already installed within your application. If not, you can do so here.
Descope Application Setup
To get started with Descope, an application needs to be setup within the Descope Console via the following steps:
- Visit the Descope Console and create a new project.
- Enter the desired name for your application.
- Get your
projectId
found inSettings/Project
, and create amanagementKey
, found inSettings/Company/Management Keys/+ Mangement Key
Setting Descope app credentials in Cypress
To have access to test user credentials within our tests we need to configure Cypress to use the Descope environment variables set in the .env
file.
- cypress.config.js
- cypress.config.ts
Make sure the corresponding environment variables exist in your .env
file
Custom Command for Descope Authentication
There are two ways you can authenticate to Descope:
- Login with UI
- Programmatic Login
For both methods of log in, you will need to include your environment variables and test user first. Then, you can start the login flow.
Descope UI Login
Below is a command to login into Descope, using the Test User Management API and navigating via the user interface, just as a real user would. It should be added in cypress/support/commands.js
.
The loginViaDescopeUI
command will execute the following steps:
- Use the Test User Management API to perform the login (create user and generate OTP code).
- Then, we enter the user
loginId
andcode
that we just generated to log in via the user interface.
Note
Since Descope renders components via the shadow DOM, remember to add the includeShadowDom: true
field in your cypress.config.js
as noted above or your tests won't be able to interact with the UI.
The other option is to use .shadow()
in each function call as described in the Cypress documentation but this may make your code harder to read.
Programmatic Login
Below is a command to programmatically login into Descope, using the Test User Management API and set an item in localStorage
with the authenticated users details, which we will use in our application code to verify we are authenticated under test.
The loginViaDescopeAPI
command will execute the following steps:
- Use the Test User Management API to perform the programmatic login (create user, generate OTP code, and verify OTP code).
- Finally the
refreshToken
andsessionToken
items are set inlocalStorage
.
We'll also need to clean up the created testing users before starting so we don't go over the limit. This is done with the deleteAllTestUsers function written in the same file.
With our Descope app setup properly in the Descope Developer console, necessary environment variables in place, and our loginViaDescopeApi and/or loginViaDescopeUI command(s) implemented, we will be able to authenticate with Descope while our app is under test. Below is a test to login as a user using our loginViaDescopeAPI function and verify the welcome page is showing.
We can also use our loginViaDescopeUI command in the test. Below is our test to login as a user via Descope and run a basic sanity check.
Running Tests in Parallel
If you'd like to run tests in parallel, you'll have to delete test users individually after the run. Here's a command to do so called deleteIndividualTestUser. You'll also need to modify your login command to return the loginId of the user or you can store it in a global variable.
Here's an example of a test that runs in parallel and deletes the user afterwards.
Adding Continuous Integration with Github Actions
- Add
.env
variables to your Github repository- Navigate to: Settings → Secrets & Variables → Actions → Add “New Repository Secret”
- REACT_APP_DESCOPE_PROJECT_ID="ProjectID"
- REACT_APP_DESCOPE_MANAGEMENT_KEY="ManagementKey"
- Navigate to: Settings → Secrets & Variables → Actions → Add “New Repository Secret”
- Create a
main.yml
file in.github/workflows
- Github Action, completed!
- You've added a configuration file for a GitHub Actions workflow. It is written in YAML and is designed to perform End-to-End (E2E) testing using Cypress on a repository's code whenever a push event is triggered.
Descope Rate Limiting Logins
Be aware of the rate limit statement in the Descope documentation:
Descope SDKs and API endpoints are rate-limited to maintain stable performance and provide a good experience for all users. Descope may limit requests if it detects an unusual spike in requests or abnormal activity in a specific project or across projects. For example, this can happen in a denial-of-service attack. To avoid hitting the rate limit, ensure your app is optimized to make the least number of requests possible based on the need. If a request breaches the rate limit - an error will be returned, together with Retry-After
header, which will specify when to retry the request.
As the size of a test suite increases and parallelized runs are utilized to expedite test run duration, this limit can be reached.
Examples
Sample App
To view an example of setting up E2E tests with Cypress and Descope, please view our sample app on Github.
Other Authentication Methods
Magic Link
Setting up E2E tests via magic link requires a few more steps than the previous methods. First, you'll need to create a custom Cypress command to login via magic link. Then, you'll need to manually go through the flow in your browser to get the host, execution ID, and step ID. Finally, you'll need to visit the magic link in your test and submit the form.
Enchanted Link
Similar to Magic Link, setting up E2E tests via enchanted link requires a few more steps than the previous methods. First, you'll need to create a custom Cypress command to login via enchanted link. Then, you'll need to manually go through the flow in your browser to get the host, execution ID, and step ID. Finally, you'll need to visit the enchanted link in your test and submit the form.
Embedded OTP or Link
Similar to Magic Link, setting up E2E tests via embedded OTP requires a few more steps than the previous methods. The same can be done for embedded link, but the token will simply need to be parsed from the link instead of used directly.
Passwords
For typing codes into a passwords input, you can simply get the component then type in the code as shown.
Phone Number Input
For typing in a phone number, you can get the DOM element that targets a <descope-text-field>
element with the specific attributes (type="tel" and placeholder="Phone").
You can then get the resulting jQuery object, access the first (and likely only) DOM element in the jQuery object, access the shadow DOM (which is how Descope renders components),
and get the input
element. Then, you can directly set the value to the phone number. We add the bubble event to make the event more realistic.