Implementation:DevExpress Testcafe ApiBasedCompiler
| Knowledge Sources | |
|---|---|
| Domains | Compiler, Test Execution |
| Last Updated | 2026-02-12 12:00 GMT |
Overview
APIBasedTestFileCompilerBase is the abstract base class for all compilers that transpile and execute test files through Node.js module loading, providing the shared infrastructure for ES-next, TypeScript, and CoffeeScript compilation.
Description
APIBasedTestFileCompilerBase lives in src/compiler/test-file/api-based.js and extends TestFileCompilerBase. It implements the full lifecycle of compiling and executing a test file:
- Compilation --
_compileCodeand_precompileCodetransform source code via language-specific transpilers. The_compileCodeForTestFilesmethod wraps compilation with stack-cleaning-hook error handling. - Module execution --
_execAsModuleexecutes compiled code either as a CommonJS module (using Node'sModule._compile) or as an ESM module (using dynamicimport()with a cache-busting suffix for live mode). ESM support checks for Node.js version compatibility (18.19.0+ or 20.8.0+). - Global API injection --
_addGlobalAPIdefinesglobal.fixtureandglobal.testas getters that create newFixture/TestAPI instances bound to the currentTestFile. These globals are removed after execution to prevent leaking into dependencies. - Require hook management --
_setupRequireHooktemporarily overridesrequire.extensionsso that imported files with matching extensions are also compiled. Node modules dependencies are excluded from TestCafe compilation but still go through the original extension handler. - Error handling -- Compilation errors are wrapped as
TestCompilationErrorwith cleaned stack traces. ESM-in-CommonJS imports are detected via theERR_REQUIRE_ESMerror code and re-thrown asImportESMInCommonJSError.
The class uses nanoid to generate a unique cachePrefix per compiler instance, ensuring module caches do not collide across concurrent compilations.
Usage
This class is never used directly. Language-specific compiler subclasses (ES-next, TypeScript, CoffeeScript) extend it and implement _precompileCode and _getRequireCompilers. The compiler pipeline calls compile(code, filename) to transpile and execute a test file, or precompile/execute separately for batch workflows.
Code Reference
Source Location
src/compiler/test-file/api-based.js (259 lines)
Signature
export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase {
constructor ({ baseUrl, esm })
// Static helpers
static _getNodeModulesLookupPath (filename)
static _isNodeModulesDep (filename)
static _isTestCafeLibDep (filename)
// Abstract methods (must be overridden)
_precompileCode (testFilesInfo)
_getRequireCompilers ()
// Compilation
_compileCode (code, filename)
_compileCodeForTestFiles (testFilesInfo)
_compileExternalModule (mod, filename, requireCompiler, origExt)
_compileModule (mod, filename, requireCompiler)
precompile (testFilesInfo)
// Execution
async _execAsModule (code, filename)
async _runCompiledCode (compiledCode, filename)
execute (compiledCode, filename)
async compile (code, filename)
// Require hook management
_setupRequireHook (testFile)
_removeRequireHook ()
// Global API management
_addGlobalAPI (testFile)
_addExportAPI (testFile)
_removeGlobalAPI ()
_hasGlobalAPI ()
// Utility
_hasTests (code)
cleanUp ()
}
Import
import APIBasedTestFileCompilerBase from '../../compiler/test-file/api-based';
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
baseUrl |
string |
Optional base URL for resolving relative test page URLs. |
esm |
boolean |
Whether to use ESM (dynamic import()) instead of CommonJS Module._compile.
|
code |
string |
Raw or pre-compiled source code of the test file. |
filename |
string |
Absolute path to the test file on disk. |
testFilesInfo |
Array<{code, filename}> |
Batch of test file entries for precompilation. |
Outputs
| Method | Return Type | Description |
|---|---|---|
compile(code, filename) |
Promise<Test[]> |
Compiles and executes the file, returning discovered tests from the TestFile instance.
|
precompile(testFilesInfo) |
string[] |
Returns array of transpiled source code strings (one per input file). |
execute(compiledCode, filename) |
Promise<Test[]> |
Executes already-compiled code and returns discovered tests. |
_hasTests(code) |
boolean |
Quick regex check: returns true if the source contains both fixture and test keywords.
|
Usage Examples
Compiling and executing a test file:
const compiler = new ESNextTestFileCompiler({ baseUrl: 'http://localhost:3000', esm: false });
const tests = await compiler.compile(sourceCode, '/path/to/test.js');
// tests is an array of Test structures discovered during execution
Batch precompilation:
const compiledSources = compiler.precompile([
{ code: fileACode, filename: '/tests/a.js' },
{ code: fileBCode, filename: '/tests/b.js' },
]);
// Execute individually
const testsA = await compiler.execute(compiledSources[0], '/tests/a.js');
const testsB = await compiler.execute(compiledSources[1], '/tests/b.js');
Related Pages
- DevExpress_Testcafe_TestFileParserBase -- The complementary parser base class that extracts fixture/test definitions from ASTs without executing them
- DevExpress_Testcafe_StackCleaningHook -- Used by this compiler to clean error stack traces during compilation and execution
- DevExpress_Testcafe_ErrorTypes -- Defines
RUNTIME_ERRORSreferenced for compilation error handling