Custom Cypress Commands
Table of Contents
cy.createUserWithClaims
Command to create a user and give the user custom claims in one command.
Parameters
properties
CreateRequest The properties of the new user
customClaims
object | null Optional custom claims to be set, or null to remove custom claims
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
const uid = '123SomeUid';
const claims = { role: 'Admin' };
cy.createUserWithClaims(uid, claims);
cy.login
Login to Firebase using custom auth token.
To specify a tenant ID, either pass the ID as a parameter to cy.login
, or set it as environment variable TEST_TENANT_ID
. Read more about Firebase multi-tenancy.
Parameters
uid
string UID of user to login as. Can also be set with environment variable TEST_UID
customClaims
string Optional custom claims to attach to the custom token
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
_Loading TEST_UID
automatically from Cypress env_
cy.login();
Passing a UID
const uid = '123SomeUid';
cy.login(uid);
Passing a tenant ID
const uid = '123SomeUid';
const tenantId = '123SomeTenantId';
cy.login(uid, undefined, tenantId);
cy.loginWithEmailAndPassword
Login to Firebase using an email and password account.
Parameters
email
string Email of user to login as. Can also be set with environment variable TEST_EMAIL
password
string Password of user to login as. Can also be set with environment variable TEST_PASSWORD
extraInfo
CreateRequest Optional additional CreateRequest parameters except for email and password
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
_Loading TEST_EMAIL
and TEST_PASSWORD
automatically from Cypress env_
cy.loginWithEmailAndPassword();
Passing an email and password
const email = 'some@user.com';
const psswd = 'password123';
cy.loginWithEmailAndPassword(email, psswd);
Passing a tenant ID
const email = 'some@user.com';
const psswd = 'password123';
const tenantId = '123SomeTenantId';
cy.loginWithEmailAndPassword(email, psswd, undefined, tenantId);
cy.logout
Log out of Firebase instance
Parameters
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
cy.logout();
Passing a tenant ID
const tenantId = '123SomeTenantId';
cy.logout(tenantId);
cy.deleteAllAuthUsers
Command to recursively delete all firebase auth users. The firebase deleteUsers function (cy.authDeleteUsers) can only remove a maximum amount of users at a time. This command calls the deleteUsers function recursively for every pageToken returned by the previous iteration.
Parameters
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
cy.deleteAllAuthUsers();
Passing a tenant ID
const tenantId = '123SomeTenantId';
cy.deleteAllAuthUsers(tenantId);
cy.callRtdb
Call Real Time Database path with some specified action such as set
, update
and remove
Parameters
action
string The action type to call with (set, push, update, remove)
actionPath
string Path within RTDB that action should be applied
options
object Options
options.limitToFirst
number|boolean Limit to the first <num>
results. If true is passed than query is limited to last 1 item.
options.limitToLast
number|boolean Limit to the last <num>
results. If true is passed than query is limited to last 1 item.
options.orderByKey
boolean Order by key name
options.orderByValue
boolean Order by primitive value
options.orderByChild
string Select a child key by which to order results
options.equalTo
string Restrict results to <val>
(based on specified ordering)
options.startAt
string Start results at <val>
(based on specified ordering)
options.endAt
string End results at <val>
(based on specified ordering)
Examples
Set data
const fakeProject = { some: 'data' };
cy.callRtdb('set', 'projects/ABC123', fakeProject);
Set Data With Meta
const fakeProject = { some: 'data' };
// Adds createdAt and createdBy (current user's uid) on data
cy.callRtdb('set', 'projects/ABC123', fakeProject, { withMeta: true });
Set Data With Timestamps
import firebase from 'firebase/app';
import 'firebase/database';
const fakeProject = {
some: 'data',
createdAt: firebase.database.ServerValue.TIMESTAMP,
};
cy.callRtdb('set', 'projects/ABC123', fakeProject);
With Firebase Web SDK version 9
import firebase from 'firebase/compat/app';
import 'firebase/compat/database';
const fakeProject = {
some: 'data',
createdAt: firebase.database.ServerValue.TIMESTAMP,
};
cy.callRtdb('set', 'projects/ABC123', fakeProject);
Delete Data
// Delete document
cy.callRtdb('delete', 'projects/ABC123');
// Delete filtered collection
cy.callRtdb('delete', 'projects', { where: ['name', '==', 'Test Project'] });
// Delete whole collection - BE CAREFUL!!
cy.callRtdb('delete', 'projectsToDelete');
Get/Verify Data
cy.callRtdb('get', 'projects/ABC123').then((project) => {
// Confirm new data has users uid
cy.wrap(project).its('createdBy').should('equal', Cypress.env('TEST_UID'));
});
Other Args
const opts = { args: ['-d'] };
const fakeProject = { some: 'data' };
cy.callRtdb('update', 'project/test-project', fakeProject, opts);
cy.callFirestore
Call Firestore instance with some specified action. Authentication is through serviceAccount.json since it is at the base
level.
Parameters
action
string The action type to call with (set, push, update, delete)
actionPath
string Path within Firestore that action should be applied
dataOrOptions
string|object Data for write actions or options for get action
options
object Options
options.withMeta
boolean Whether or not to include createdAt
and createdBy
options.merge
boolean Merge data during set
options.batchSize
number Size of batch to use while deleting
options.where
array Filter documents by the specified field and the value should satisfy
- the relation constraint provided
options.orderBy
string|array Order documents
options.limit
number Limit to n number of documents
options.limitToLast
number Limit to last n number of documents
options.statics
admin.firestore Firestore statics (i.e. admin.firestore
). This should only be needed during testing due to @firebase/testing not containing statics
Examples
Basic
cy.callFirestore('set', 'project/test-project', 'fakeProject.json');
Set Data With Server Timestamps
import firebase from 'firebase/app';
import 'firebase/firestore';
const fakeProject = {
some: 'data',
// Use new firebase.firestore.Timestamp.now in place of serverTimestamp()
createdAt: firebase.firestore.Timestamp.now(),
// Or use fromDate if you would like to specify a date
// createdAt: firebase.firestore.Timestamp.fromDate(new Date())
};
cy.callFirestore('set', 'projects/ABC123', fakeProject);
With Firebase Web SDK version 9
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
const fakeProject = {
some: 'data',
// Use new firebase.firestore.Timestamp.now in place of serverTimestamp()
createdAt: firebase.firestore.Timestamp.now(),
// Or use fromDate if you would like to specify a date
// createdAt: firebase.firestore.Timestamp.fromDate(new Date())
};
cy.callFirestore('set', 'projects/ABC123', fakeProject);
Full
describe('Test firestore', () => {
const TEST_UID = Cypress.env('TEST_UID');
const mockAge = 8;
beforeEach(() => {
cy.visit('/');
cy.callFirestore('delete', 'testCollection');
});
it('read/write test', () => {
cy.log('Starting test');
cy.callFirestore('set', `testCollection/${TEST_UID}`, {
name: 'axa',
age: 8,
});
cy.callFirestore('get', `testCollection/${TEST_UID}`).then((r) => {
cy.log('get returned: ', r);
cy.wrap(r).its('data.age').should('equal', mockAge);
});
cy.log('Ended test');
});
});
cy.[authFunction]
Use any of the firebase admin auth methods:
authCreateAuthUser
authImportAuthUsers
authListAuthUsers
authGetAuthUser
authGetAuthUserByEmail
authGetAuthUserByPhoneNumber
authGetAuthUserByProviderUid
authGetAuthUsers
authUpdateAuthUser
authSetAuthUserCustomClaims
authDeleteAuthUser
authDeleteAuthUsers
authCreateCustomToken
authCreateSessionCookie
authVerifyIdToken
authRevokeRefreshTokens
authGenerateEmailVerificationLink
authGeneratePasswordResetLink
authGenerateSignInWithEmailLink
authGenerateVerifyAndChangeEmailLink
authGreateProviderConfig
authGetProviderConfig
authListProviderConfigs
authUpdateProviderCondig
authDeleteProviderConfig
Parameters
The parameters (and return type) depend on the function used. They are the same as for the firebase api function it refers to, with addition of an optional tenantId
parameter as last parameter:
tenantId
string Optional ID of tenant used for multi-tenancy. Can also be set with environment variable TEST_TENANT_ID
Examples
const uid = '123SomeUid';
const email = 'some@user.com';
cy.authCreateUser({ uid });
cy.authUpdateUser(uid, { displayName: 'Test User', email });
cy.authSetCustomUserClaims(uid, { role: 'admin' });
cy.authGetUserByEmail(email).then((user) => {
console.log(user?.displayName); // Test User
console.log(user?.customClaims?.['role']); // admin
});
Plugin
Plugin attaches cypress tasks, which are called by custom commands, and initializes firebase-admin instance. By default cypress-firebase internally initializes firebase-admin using GCLOUD_PROJECT
environment variable for project identification and application-default credentials (set by providing path to service account in GOOGLE_APPLICATION_CREDENTIALS
environment variable) matching Google documentation. This default functionality can be overriden by passing a forth argument to the plugin - this argument is passed directly into the firebase-admin instance as AppOptions on init which means any other config such as databaseURL
, credential
, or databaseAuthVariableOverride
can be included.
import admin from 'firebase-admin';
import { defineConfig } from 'cypress';
import { plugin as cypressFirebasePlugin } from 'cypress-firebase';
const cypressConfig = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
// NOTE: Make supportFile exists if separate location is provided
setupNodeEvents(on, config) {
// e2e testing node events setup code
return cypressFirebasePlugin(on, config, admin);
// NOTE: If not setting GCLOUD_PROJECT env variable, project can be set like so:
// return cypressFirebasePlugin(on, config, admin, { projectId: 'some-project' });
},
},
});
export default cypressConfig;
Plugin Configuration
A fifth argument is used for further configuration of the plugin.
protectProduction
The plugin tries to detect whether or not the firebase emulators are running, based on the respective environment variables being set or not. When the an emulator isn't running, production could be targeted instead which might be dangerous. The protectProduction
key configures the behaviour when the emulator for a specific firebase service hasn't been detected. The options for the behaviour when an emalator is not running are:
'none'
(default) no protection is granted in this case, nor will a warning be output to the console. Production could be targeted.
'warn'
a warning will be output to the console, but no further protection is granted. Production could be targeted.
'error'
an error is thrown, preventing cypress starting alltogether. This makes sure your production cannot be targeted for this service.
import admin from 'firebase-admin';
import { defineConfig } from 'cypress';
import { plugin as cypressFirebasePlugin } from 'cypress-firebase';
const cypressConfig = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
setupNodeEvents(on, config) {
return cypressFirebasePlugin(
on,
config,
admin,
{}, // AppOptions override
{
protectProduction: {
// when rtdb emulator isn't detected, a console warning will appear
rtdb: 'warn',
// plugin will be indifferent to the firestore emulator running or not
firestore: 'none',
// when auth emulator isn't detected, an error is thrown halting cypress
auth: 'error',
},
},
);
},
},
});
export default cypressConfig;