@qavajs/core
v2.14.0
Published
qavajs framework core
Maintainers
Readme
@qavajs/core
@qavajs/core is the core test runner module of the qavajs automation framework.
It extends CucumberJS with memory management, validation utilities,
fixtures, templates, services, and test composition — all with full ESM, CJS, and TypeScript support.
Requirements: Node.js >= 20
Table of Contents
- Installation
- Running Tests
- Configuration
- World Extensions
- Memory Value Parameter Type
- Validation Parameter Type
- Soft Validation
- Execute Steps from Other Steps
- Execute Other Tests
- Override Step Definition
- Fixture
- Template
- Test Execution Hooks
- Service
- Override Memory Values via CLI
- Pass CLI Params to Workers
Installation
npm install @qavajs/coreRunning Tests
npx qavajs run --config <config> --profile <profile>cucumber-js is also available as an alias:
npx cucumber-js run --config <config>CLI Options
| Flag | Type | Description |
|------|------|-------------|
| --config | string | Config file path |
| --profile | string | Profile name to run |
| --paths | string[] | Paths to feature files |
| --tags, -t | string[] | Tag expression filter (multiple flags are ANDed) |
| --format, -f | string[] | Formatter name/path and optional output file |
| --format-options | string | JSON options for formatters |
| --import, -i | string[] | Support code paths (ESM) |
| --require, -r | string[] | Support code paths (CJS) |
| --require-module | string[] | Transpilation modules to load via require() |
| --name | string[] | Scenario name regex filters |
| --order | string | Run order (defined or random) |
| --parallel | number | Number of worker processes |
| --retry | number | Retry failing tests N times |
| --retry-tag-filter | string[] | Tag expression for retryable scenarios |
| --dry-run, -d | boolean | Prepare run without executing |
| --backtrace, -b | boolean | Show full error backtraces |
| --fail-fast | boolean | Stop on first failure |
| --force-exit | boolean | Call process.exit() after run |
| --strict | boolean | Fail on pending steps |
| --shard | string | Shard tests (x/y) |
| --world-parameters | string | JSON parameters passed to World |
| --memory-values | string | JSON values to override in memory |
| --no-error-exit | boolean | Suppress non-zero exit code on test failure |
Configuration
Config files can be written in JS, CJS, TS, or ESM format.
// config.ts
export default {
paths: ['features/**/*.feature'],
require: ['step_definitions/**/*.ts'],
memory: new Memory(),
defaultTimeout: 30_000,
service: [],
serviceTimeout: 60_000
}| Property | Type | Default | Description |
|------------------|----------|------------|------------------------------------------------------|
| memory | object | {} | Memory instance for storing/retrieving test values |
| defaultTimeout | number | 10_000 | Default step timeout in milliseconds |
| service | array | [] | Services with before/after lifecycle hooks |
| serviceTimeout | number | 60_000 | Timeout for service before/after in milliseconds |
All standard CucumberJS configuration options are also supported.
World Extensions
@qavajs/core extends the CucumberJS World with additional properties and methods:
| Entity | Type | Description | Example |
|---------------|----------|-----------------------------------------------------|----------------------------------------------------------------------|
| config | object | Loaded configuration object | this.config.parallel |
| memory | object | Memory instance | this.memory.$key |
| executeStep | function | Programmatically execute a step definition | await this.executeStep("I type 'user' to 'Username Input'"); |
| executeTest | function | Execute another test scenario by path and title | await this.executeTest('feature/Login.feature', 'Login scenario'); |
| setValue | function | Set a value in memory | this.setValue('key', 'value'); |
| getValue | function | Get a memory value or resolve an expression | await this.getValue('$key'); |
| validation | function | Get a validation function by type | const fn = await this.validation('to equal'); |
TypeScript users can import the IQavajsWorld interface:
import { IQavajsWorld } from '@qavajs/core';
When('I do something', async function(this: IQavajsWorld) {
const value = await this.getValue('$myKey');
});Memory Value Parameter Type
The {value} parameter type provides access to the memory layer. It resolves a memory expression at runtime, and also exposes a set method to write values back.
When('I read memory {value}', async function(memoryValue) {
expect(memoryValue.value()).toEqual('expectedValue');
});
When('I set memory {value} as {string}', async function(memoryKey, value) {
memoryKey.set(value);
});Validation Parameter Type
The {validation} parameter type provides assertion functions for comparing two values. It supports both instant and polling-based verification.
When('I expect {string} {validation} {string}', async function(actual, validate, expected) {
validate(actual, expected);
});Polling validation retries until the condition is met or a timeout is reached:
When('I poll-expect {string} {validation} {string}', async function(actual, validate, expected) {
await validate.poll(
() => actual,
expected,
{ timeout: 5000, interval: 500 }
);
});Soft Validation
Prefix any validation step with softly to allow the scenario to continue even when an assertion fails.
All soft failures are collected and reported at the end of the scenario.
Feature: Soft assertions example
Scenario: verify soft assert
Then I expect '2' to softly equal '1' # fails, but execution continues
And I expect '1' to softly equal '1' # passes
And I expect '2' to softly equal '1' # fails
And I expect '1' to softly equal '1' # passes — all failures reported at endExecute Steps from Other Steps
Use this.executeStep to compose complex step logic from existing steps:
When('I log in as {string}', async function(username: string) {
await this.executeStep(`I type '${username}' to 'Username Input'`);
await this.executeStep(`I type 'secret' to 'Password Input'`);
await this.executeStep(`I click 'Login Button'`);
await this.executeStep(`I fill following fields`, new DataTable([
['Order', '123'],
['Delivery Location', 'New York']
]));
});Execute Other Tests
Use this.executeTest to call another test scenario from within a scenario:
When('I complete checkout', async function() {
await this.executeTest('features/Login.feature', 'User logs in');
await this.executeTest('features/Cart.feature', 'User adds item to cart');
});Override Step Definition
Override replaces an existing step implementation without causing an ambiguous step error.
Useful when extending a shared library's steps with project-specific behavior.
import { Override } from '@qavajs/core';
// original step from a shared library
When('I do test', async function() {});
// replace it without conflicts
Override('I do test', async function() {
console.log('overridden implementation');
});Fixture
Fixture prepares the test environment for scenarios with a specific tag. An optional return value is treated as a teardown function executed after the scenario.
import { Fixture } from '@qavajs/core';
Fixture({ name: 'pdp', tags: '@pdp' }, async function() {
await this.playwright.page.goto('https://my-site/pdp');
// teardown: runs after the scenario
return async function() {
await this.playwright.page.request.get('/cleanCart');
};
});Feature: Product page
@pdp
Scenario: Add item to cart
When I click 'qavajs T-shirt'
And I click 'cart icon'
Then I expect 'qavajs T-shirt cart item' to be visibleTemplate
Template lets you define a step by composing existing Gherkin steps, keeping step definitions DRY.
import { When, Template } from '@qavajs/core';
When('I click {string} and verify {string}', Template((locator, expected) => `
I click '${locator}'
I expect '${locator} > Value' to equal '${expected}'
`));Test Execution Hooks
BeforeExecution and AfterExecution run once before or after the entire test run — useful for
starting/stopping infrastructure that must outlive individual scenarios.
import { BeforeExecution, AfterExecution } from '@qavajs/core';
import { Server } from './server';
const server = new Server();
BeforeExecution(async function() {
await server.start();
});
AfterExecution(async function() {
await server.stop();
});Service
Services provide before/after lifecycle hooks for the full test run. They have access to a typed
options context and receive the run result in after.
import externalService from './externalService';
export default {
service: [
{
options: { baseUrl: 'https://api.example.com' },
async before() {
console.log('Starting with', this.options.baseUrl);
},
async after(result) {
if (!result.success) process.exitCode = 1;
}
},
{
options: { data: 42 },
...externalService
}
]
}Services have a default timeout of 60 seconds. Override it with serviceTimeout (in milliseconds):
export default {
serviceTimeout: 120_000 // 2 minutes
}Override Memory Values via CLI
Pass a JSON object via --memory-values to override specific memory keys at runtime — useful for
running the same suite against different environments.
npx qavajs run --config config.ts --memory-values '{"url": "https://staging.example.com"}'This overrides $url in the memory layer for the entire test run.
Pass CLI Params to Workers
All CLI arguments passed to qavajs are forwarded to child workers via the CLI_ARGV environment variable,
allowing step definitions and config files running in worker processes to read them.
