Overview
DevToolsTestFileCompiler converts Chrome DevTools Recorder JSON recordings into TestCafe-executable test structures, using a factory-based command transformer pipeline.
Description
This implementation spans two files:
DevToolsTestFileCompiler (src/compiler/test-file/formats/dev-tools/compiler.ts, 102 lines) extends RawTestFileCompiler and processes .json files exported from Chrome DevTools Recorder. It parses the JSON recording, extracts the title for fixture and test names, then iterates over the steps array, converting each step into a TestCafe raw command using the CommandTransformerFactory. Before each command, it checks for frame selectors and inserts SwitchToIframeCommandTransformer commands; after each command, it appends a SwitchToMainWindowCommandTransformer command. The preprocessed raw structure is then passed to the parent RawTestFileCompiler.compile() for final test object construction.
CommandTransformerFactory (src/compiler/test-file/formats/dev-tools/commands/factory.ts, 47 lines) is a static factory class that maps DevTools Recorder step types to their corresponding command transformer classes. It handles 12 step types: navigate, setViewport, click (with right-click detection via the secondary button name), doubleClick, hover, change, keyDown, keyUp, scroll, waitForExpression, waitForElement, and close (which returns null, effectively skipping the step). Unrecognized step types throw a GeneralError with the invalidCommandInJsonCompiler runtime error code.
Usage
The DevTools compiler is selected by TestCafe's compiler pipeline for .json files. Users export a recording from Chrome DevTools Recorder as JSON, then pass the file directly to TestCafe (e.g., testcafe chrome recording.json). TestCafe automatically detects the JSON format and routes it through this compiler.
Code Reference
Source Location: Compiler
Source Location: Command Factory
Signature: DevToolsTestFileCompiler
export default class DevToolsTestFileCompiler extends RawTestFileCompiler {
private raw: RawRecording;
_hasTests (): boolean
get _fixture (): RawFixture
get _test (): RawTest
getSupportedExtension (): string
compile (code: string, filename: string): Test[]
_preProcess (code: string, filename: string): string | null
_processStep (step: DevToolsRecorderStep, filename: string, i: number): void
_onBeforeCommandExecute (step: DevToolsRecorderStep): void
_onAfterCommandExecute (step: DevToolsRecorderStep): void
}
Signature: CommandTransformerFactory
export class CommandTransformerFactory {
static create (
step: DevToolsRecorderStep,
filename: string,
callsite: number
): CommandTransformerBase | null
}
Import
import DevToolsTestFileCompiler from '../compiler/test-file/formats/dev-tools/compiler';
import { CommandTransformerFactory } from '../compiler/test-file/formats/dev-tools/commands/factory';
I/O Contract
DevToolsTestFileCompiler.compile(code, filename)
| Input |
Type |
Description
|
| code |
string |
Raw JSON string from a Chrome DevTools Recorder export file
|
| filename |
string |
Absolute path to the .json recording file
|
| Output |
Type |
Description
|
| tests |
Test[] |
Array of TestCafe Test objects ready for execution; returns empty array if JSON parsing fails or steps is missing
|
DevToolsTestFileCompiler._preProcess(code, filename)
| Input |
Type |
Description
|
| code |
string |
Raw JSON string of the DevTools recording
|
| filename |
string |
Path to the source file (passed to factory for error reporting)
|
| Output |
Type |
Description
|
| rawJson |
string or null |
Stringified raw TestCafe fixture/test structure with transformed commands; null if the input is not valid JSON or has no steps
|
CommandTransformerFactory.create(step, filename, callsite)
| Input |
Type |
Description
|
| step |
DevToolsRecorderStep |
A single step object from the recording's steps array
|
| filename |
string |
Source file path for error context
|
| callsite |
number |
Step index for callsite tracking in error messages
|
| Output |
Type |
Description
|
| transformer |
CommandTransformerBase or null |
A transformer instance whose transform() method produces a raw TestCafe command; null for close steps
|
Supported DevTools Command Types
| DevTools Step Type |
TestCafe Transformer |
Notes
|
| navigate |
NavigateCommandTransformer |
|
| setViewport |
SetViewportCommandTransformer |
|
| click |
ClickCommandTransformer |
Default left-click
|
| click (button: 'secondary') |
RightClickCommandTransformer |
Right-click detected by button property
|
| doubleClick |
DoubleClickCommandTransformer |
|
| hover |
HoverCommandTransformer |
|
| change |
ChangeCommandTransformer |
Text input changes
|
| keyDown |
KeyDownCommandTransformer |
|
| keyUp |
KeyUpCommandTransformer |
|
| scroll |
ScrollCommandTransformer |
|
| waitForExpression |
WaitForExpressionCommandTransformer |
|
| waitForElement |
WaitForElementCommandTransformer |
|
| close |
(null -- skipped) |
Browser close steps are ignored
|
DevToolsRecorderStep Type
| Property |
Type |
Description
|
| type |
string |
The step type (e.g., navigate, click, change)
|
| x |
number (optional) |
X coordinate for pointer actions
|
| y |
number (optional) |
Y coordinate for pointer actions
|
| width |
number (optional) |
Viewport width (for setViewport)
|
| height |
number (optional) |
Viewport height (for setViewport)
|
| offsetX |
number (optional) |
Scroll offset X
|
| offsetY |
number (optional) |
Scroll offset Y
|
| value |
string (optional) |
Input value (for change steps)
|
| expression |
string (optional) |
JavaScript expression (for waitForExpression)
|
| frame |
number[] (optional) |
Array of iframe indices to switch into before executing the command
|
Usage Examples
// Run a Chrome DevTools Recorder JSON file directly with TestCafe:
// $ npx testcafe chrome recording.json
// The JSON file format (Chrome DevTools Recorder export):
// {
// "title": "Login Flow",
// "steps": [
// { "type": "navigate", "url": "https://example.com/login" },
// { "type": "click", "selectors": [["#username"]], "offsetX": 50, "offsetY": 10 },
// { "type": "change", "selectors": [["#username"]], "value": "admin" },
// { "type": "click", "selectors": [["#password"]], "offsetX": 50, "offsetY": 10 },
// { "type": "change", "selectors": [["#password"]], "value": "secret" },
// { "type": "click", "selectors": [["#login-btn"]], "offsetX": 40, "offsetY": 15 },
// { "type": "waitForElement", "selectors": [["#dashboard"]] }
// ]
// }
// Internal: how the compiler processes steps
import DevToolsTestFileCompiler from '../compiler/test-file/formats/dev-tools/compiler';
const compiler = new DevToolsTestFileCompiler();
const jsonCode = fs.readFileSync('recording.json', 'utf8');
const tests = compiler.compile(jsonCode, '/path/to/recording.json');
// tests is an array of Test objects with commands derived from each step:
// - navigate -> NavigateCommandTransformer.transform()
// - click -> ClickCommandTransformer.transform()
// - change -> ChangeCommandTransformer.transform()
// Each step also gets SwitchToMainWindow appended after it.
// Steps with frame[] get SwitchToIframe prepended before them.
// Internal: factory usage
import { CommandTransformerFactory } from '../compiler/test-file/formats/dev-tools/commands/factory';
const step = { type: 'click', selectors: [['#btn']], offsetX: 10, offsetY: 5 };
const transformer = CommandTransformerFactory.create(step, 'test.json', 0);
const rawCommand = transformer.transform();
// rawCommand is a TestCafe raw command object for a click action
const rightClickStep = { type: 'click', button: 'secondary', selectors: [['#ctx-menu']] };
const rcTransformer = CommandTransformerFactory.create(rightClickStep, 'test.json', 1);
// rcTransformer is a RightClickCommandTransformer instance
Related Pages