Workflow:Nightwatchjs Nightwatch Custom Commands And Assertions
| Knowledge Sources | |
|---|---|
| Domains | E2E_Testing, Framework_Extension, Test_Architecture |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
End-to-end process for extending Nightwatch with reusable custom commands and custom assertions that encapsulate common testing patterns for a specific application domain.
Description
This workflow covers creating custom commands (reusable action sequences) and custom assertions (domain-specific validation logic) that integrate seamlessly into the Nightwatch API. Custom commands appear on the browser object and can be chained like built-in commands. Custom assertions integrate with the assert and verify namespaces. Both mechanisms support async/await, class-based definitions, and namespaced organization for large projects.
Usage
Execute this workflow when your test suite contains repeated multi-step interactions or validation patterns that would benefit from abstraction. Common triggers include repeated login sequences, complex form-filling patterns, application-specific element state checks, or any interaction that appears in three or more test files.
Execution Steps
Step 1: Configure Extension Paths
Set the custom_commands_path and custom_assertions_path in the Nightwatch configuration. These paths tell the framework where to discover and load custom extensions at startup. Multiple paths can be specified as arrays.
Key considerations:
- Paths can be absolute or relative to the project root
- Subdirectories are loaded recursively and can create namespaced commands
- Plugin-provided commands are loaded from the plugin's nightwatch/commands directory
- Assertion paths follow the same pattern as command paths
Step 2: Create Custom Commands
Write command modules that export either a function-style command or an ES6 class. Function-style commands receive arguments and return the browser instance for chaining. Class-style commands extend the base command and implement an async command() method.
What happens:
- Function commands use module.exports with a command property function
- Class commands define an async command() method that performs the action
- Commands access the browser API via this (function-style) or this.api (class-style)
- Commands can compose multiple built-in commands into a single high-level action
- The command name matches the filename (e.g., strictClick.js becomes browser.strictClick())
Step 3: Create Custom Assertions
Write assertion modules that define the validation logic for a custom check. Each assertion module exports an object with expected(), pass(), value(), and command() methods that the framework calls during assertion evaluation.
Key considerations:
- The command() method executes the WebDriver call to retrieve the actual value
- The value() method extracts the relevant value from the command result
- The pass() method compares actual vs. expected and returns a boolean
- Custom assertions appear under browser.assert.assertionName() and browser.verify.assertionName()
- Assertions support retry via the framework's assertion retry mechanism
Step 4: Implement Namespaced Commands
Organize commands into subdirectories to create namespaced access patterns. Commands in subdirectories are accessed via dot notation on the browser object, preventing name collisions in large projects.
What happens:
- Place command files in subdirectories (e.g., custom-commands/auth/login.js)
- Access via browser.auth.login() using the directory as namespace
- Multiple namespace levels are supported via deeper nesting
- Namespace aliases can be defined for convenience
Step 5: Use Extensions in Tests
Reference custom commands and assertions in test files exactly like built-in Nightwatch commands. Custom commands are available on the browser object, custom assertions on browser.assert and browser.verify.
Key considerations:
- Custom commands chain with built-in commands seamlessly
- Custom assertions follow the same pass/fail/retry semantics as built-in assertions
- TypeScript type definitions can be added for custom extensions
- Extensions are available in all test files without explicit import