Implementation:DevExpress Testcafe Role
| Knowledge Sources | |
|---|---|
| Domains | Testing, Authentication, State Management |
| Principle | User authentication roles |
| Last Updated | 2026-02-12 12:00 GMT |
Overview
Role encapsulates a reusable user authentication state -- a login URL, an initialization function, and a captured browser state snapshot -- so that tests can switch between authenticated user contexts without repeating login steps.
Description
Defined in src/role/role.ts, the Role class extends EventEmitter and manages the lifecycle of an authentication role through three phases (defined in RolePhase):
uninitialized-- The role has a login URL and init function but has not yet been executed.pendingInitialization-- The role is currently executing its initialization sequence.initialized-- The role has completed initialization and its browser state snapshot is captured and ready for reuse.
If no loginUrl is provided, the role starts in the initialized phase (representing an anonymous/unauthenticated role).
The initialization sequence (initialize method) performs these steps in order:
- Sets phase to
pendingInitialization. - Switches the test run to a clean browser session and navigates to the login URL via
_switchToCleanRun. - Executes the user-provided
_initFn(the login steps) within the test run, with action events and debug breakpoints configured via decorators. - Captures the browser's state snapshot (cookies, local storage, etc.) via
_storeStateSnapshot. - If
preserveUrlis enabled, stores the current URL as the redirect URL. - Sets phase to
initializedand emits an'initialized'event.
Errors during any step are captured into initErr rather than thrown, allowing the framework to report them appropriately. The static Role.from method reconstructs a Role instance from a serialized representation.
Each role gets a unique 7-character ID via nanoid.
Usage
Use Role when tests require switching between different authenticated user states (e.g., admin vs. regular user). Roles are initialized lazily on first use and then cached, so subsequent t.useRole() calls skip the login steps and restore the saved state snapshot directly.
Code Reference
Source Location
- Repository: DevExpress_Testcafe
- File: src/role/role.ts
- Lines: 1-128
Signature
export interface RedirectUrl {
[testId: string]: string;
}
export default class Role extends EventEmitter {
public id: string;
public phase: RolePhase;
public loginUrl: string | null;
public redirectUrl: RedirectUrl | string | null;
public _initFn: Function | null;
public opts: RoleOptions;
public initErr: null | Error | TestCafeErrorList;
public stateSnapshot: StateSnapshot;
public constructor (
loginUrl: string | null,
initFn: Function | null,
options?: {}
);
private async _storeStateSnapshot (testRun: TestRun): Promise<void>;
private async _setInitError (err: Error): Promise<void>;
private async _executeInitFn (testRun: TestRun): Promise<void>;
private _prepareLoginUrl (loginUrl: string, baseUrl: string): string;
private async _switchToCleanRun (testRun: TestRun): Promise<void>;
public async initialize (testRun: TestRun): Promise<void>;
public async setCurrentUrlAsRedirectUrl (testRun: TestRun): Promise<void>;
public static from (init: unknown): Role | null;
}
Import
import Role from '../role/role';
// Public API:
// import { Role } from 'testcafe';
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| loginUrl | null | Yes | The URL to navigate to before running the init function. Pass null for an anonymous (no-login) role.
|
| initFn | null | Yes | An async function containing the login steps (e.g., typing credentials, clicking submit). Receives the testRun as its argument. Pass null for anonymous roles.
|
| options | Object |
No | Role options. Currently supports preserveUrl: boolean which, when true, restores the URL the role was on after initialization completes.
|
Outputs
| Name | Type | Description |
|---|---|---|
| id | string |
Unique 7-character identifier for the role instance. |
| phase | RolePhase |
Current lifecycle phase: 'uninitialized', 'pendingInitialization', or 'initialized'.
|
| stateSnapshot | StateSnapshot |
Captured browser state (cookies, local storage, etc.) after successful initialization. |
| redirectUrl | string | null | The URL to redirect to after role activation. Per-test when preserveUrl is false; a single string when preserveUrl is true.
|
| initErr | TestCafeErrorList | null | Any error that occurred during initialization, or null if successful.
|
Usage Examples
import { Role, Selector } from 'testcafe';
const adminRole = Role('https://example.com/login', async t => {
await t
.typeText('#username', 'admin')
.typeText('#password', 'admin-password')
.click('#login-button');
});
const userRole = Role('https://example.com/login', async t => {
await t
.typeText('#username', 'user')
.typeText('#password', 'user-password')
.click('#login-button');
}, { preserveUrl: true });
// Anonymous role (resets to unauthenticated state)
const anonymousRole = Role.anonymous();
fixture `Role-Based Tests`
.page `https://example.com`;
test('Admin can access dashboard', async t => {
await t.useRole(adminRole);
await t.expect(Selector('#admin-panel').exists).ok();
});
test('Switch between roles', async t => {
await t.useRole(adminRole);
// ... perform admin actions ...
await t.useRole(userRole);
// ... perform user actions ...
await t.useRole(anonymousRole);
// ... verify unauthenticated state ...
});
Related Pages
Note: This is an orphan Implementation — user authentication roles is an internal API with no dedicated Principle page.