Reset the Supabase Database in Cypress

Resetting your database during E2E tests is important to prevent flakiness. In this tutorial, we'll show you how to reset the Supabase database in Cypress E2E tests.

Resetting your database state when executing your E2E tests is a common practice to ensure that your tests are isolated from each other. This is important because you don't want to have to write your tests in a specific order or rely on the state from a previous test.

This is a common cause of flakiness, and it's best to avoid it. In this tutorial, we'll show you how to reset the Supabase database in Cypress E2E tests, so that you can write your tests in any order and not worry about the state of the database.

While this tutorial is written for Cypress, the same principles apply to other E2E testing frameworks.

When should you reset the database?

There are two ways to reset the database in Supabase:

  1. by writing a plugin that resets the database before each spec (or test)
  2. by manually resetting the database in your tests where you need it

While the first option is the easiest, it may not always be the best. If you have a lot of tests, resetting the database before each test can slow down your tests significantly.

Generally speaking, if your tests are well-written, you may not need to reset the database before each test. If you find that your tests are flaky, then you should consider resetting the database before each test.

Writing an NPM script to reset the database

First, we want to add a new npm script to our package.json file

"supabase:db:reset": "supabase db reset"

If you want to debug the database reset, you can add the --debug flag to the command.

"supabase:db:reset": "supabase db reset --debug"

Writing a Cypress plugin to reset the database before each test

Let's take a look at how we can write a Cypress plugin to reset the database before each test.

If you are using a newer version of Cypress, we will write plugins using the configuration file cypress.config.ts.

Let's write a function that calls the npm script we wrote earlier.

cypress.config.ts
import { execSync } from 'child_process';
function resetDb() {
console.log(`Resetting database...`);
try {
execSync('npm run supabase:db:reset');
console.log(`DB reset successful`);
return true;
} catch (error) {
console.error(`DB reset failed`, error);
}
return false;
}

Now, we can use this function in a Cypress plugin. To do so, we will use the setupNodeEvents function:

cypress.config.ts
setupNodeEvents(on, config) {
on('before:spec', () => {
resetDb();
});
}

If you want to use this plugin in the windowed/interactive version of Cypress, we need to activate an experimental flag. To do so, add the following property to your Cypress configuration:

cypress.config.ts
{
experimentalInteractiveRunEvents: true,
}

I suggest doing it, since running the tests in the interactive mode that updates the DB will most likely fail if you don't reset the database on each test.

Now, go on and run your tests. You should see the database being reset before each test! 🎉 Yay!

Manually resetting the database in your tests

If you don't want to reset the database before each test, you can also reset the database manually in your tests.

Let's add a custom Cypress command to do so.

Writing the Cypress task that will execute the npm script

First, we need to write a Cypress task that will execute the npm script we wrote earlier.

We will add this next to the on event we wrote earlier in setupNodeEvents:

cypress.config.ts
setupNodeEvents(on, config) {
on('task', {
resetDatabase() {
return resetDb();
},
});
}

Adding a custom Cypress command to reset the database

If you use Typescript, we need to augment the Cypress namespace to add our custom command. Add the snippet below to your global typings file and ensure it's picked up by your tsconfig.json file:

declare global {
namespace Cypress {
interface Chainable {
resetDatabase(): void;
}
}
}

Now, we can add the command to the commands.ts file

cypress/support/commands.ts
Cypress.Commands.add(`resetDatabase`, () => {
cy.task(`resetDatabase`);
});

We can now call cy.resetDatabase() in our tests to reset the database. For example, we can add it to the before hook of a specific test:

cypress/integration/my-test.spec.ts
describe('My test', () => {
before(() => {
cy.resetDatabase();
// wait for the database to reset
cy.wait(1000)
});
it('should do something', () => {
// ...
});
});

Conclusion

In this tutorial, we learned how to reset the Supabase database in Cypress E2E tests. We saw how to write an npm script to reset the database, and how to write a Cypress plugin to reset the database before each test. We also saw how to write a custom Cypress command to reset the database manually in our tests.

If you have any questions, feel free to reach out to us on Discord or Twitter. We're happy to help!