Overview
TypeScriptTestFileCompiler and TypeScriptTestFileParser together handle compilation and AST-based test discovery for TypeScript test files, using the TypeScript compiler API for both transpilation and parsing.
Description
This implementation spans two files:
TypeScriptTestFileCompiler (src/compiler/test-file/formats/typescript/compiler.ts, 270 lines) extends APIBasedTestFileCompilerBase and uses the TypeScript compiler API (ts.createProgram) to compile .ts and .tsx test files. It supports batch precompilation -- all uncached files are compiled in a single ts.createProgram call for performance, mirroring how tsc works. The compiler loads TypeScript configuration from a tsconfig.json via TypescriptConfiguration, supports custom TypeScript compiler module paths, normalizes filenames (lowercasing on Windows), and injects TestCafe's type definitions (ts-defs/index.d.ts). Two custom TypeScript transformers are applied: testcafeImportPathReplacer rewrites import ... from 'testcafe' to point to the actual lib path, and disableV8OptimizationCodeAppender (ESM mode only) appends an eval("") call to prevent V8 optimization. For .js, .jsx, .cjs, and .mjs dependencies, the compiler falls back to ESNextTestFileCompiler._compileCode.
TypeScriptTestFileParser (src/compiler/test-file/formats/typescript/get-test-list.js, 246 lines) extends TestFileParserBase and uses ts.SyntaxKind token types to traverse the TypeScript AST. It strips comments from the source to fix TypeScript's start-position calculation, then creates a source file with ts.createSourceFile and walks the statements to discover fixture and test declarations. The module exports getTypeScriptTestList and getTypeScriptTestListFromCode.
Usage
The TypeScript compiler is selected by TestCafe's compiler pipeline for .ts and .tsx files. Users can configure it via the compilerOptions.typescript section in .testcaferc.json or runner API, specifying a custom tsconfig.json path or custom compiler module. The parser is used for IDE integration and test discovery without execution.
Code Reference
Source Location: Compiler
Source Location: Parser
Signature: TypeScriptTestFileCompiler
export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompilerBase {
private static tsDefsPath: string;
private readonly _tsConfig: TypescriptConfiguration;
private readonly _compilerPath: string;
private readonly _customCompilerOptions?: object;
public constructor (
compilerOptions?: TypeScriptCompilerOptions,
{ baseUrl, esm }?: OptionalCompilerArguments
)
private static _getCompilerPath (compilerOptions?: TypeScriptCompilerOptions): string
private _loadTypeScriptCompiler (): TypeScriptInstance
private static _normalizeFilename (filename: string): string
private static _getTSDefsPath (): string
private _reportErrors (diagnostics: Readonly<TypeScript.Diagnostic[]>): void
public _compileCodeForTestFiles (testFilesInfo: TestFileInfo[]): Promise<string[]>
private _compileFilesToCache (ts: TypeScriptInstance, filenames: string[]): void
private _getTypescriptTransformers (): TransformerFactory<SourceFile>[]
public _precompileCode (testFilesInfo: TestFileInfo[]): string[]
public _getRequireCompilers (): RequireCompilers
public get canPrecompile (): boolean
public get canCompileInEsm (): boolean
public getSupportedExtension (): string[]
}
// Helper transformer functions (module-level)
function testcafeImportPathReplacer<T extends Node> (esm?: boolean): TransformerFactory<T>
function disableV8OptimizationCodeAppender<T extends Node> (): TransformerFactory<T>
Signature: TypeScriptTestFileParser
class TypeScriptTestFileParser extends TestFileParserBase {
constructor ()
getComputedNameString ({ pos, end }): string
getTokenType (token): number
getCalleeToken (token): object
getMemberFnName (token): string
getKeyValue (prop): { key: string, value: string | null }
getFixedStartOffset (start): number
getLocationByOffsets (start, end): { loc: object, start: number, end: number }
getRValue (token): object
getStringValue (token): string | null
isAsyncFn (token): boolean
getFunctionBody (token): object[]
formatFnData (name, value, token, meta = [{}]): object
analyzeMemberExp (token): object | null
formatFnArg (arg): string | null
getFnCall (token): object | null
getTaggedTemplateExp (token): object | null
analyzeFnCall (token): object | null
parse (code): object[]
}
// Exported bound functions
export const getTypeScriptTestList: (filename: string) => Promise<object[]>
export const getTypeScriptTestListFromCode: (code: string) => object[]
Import
import TypeScriptTestFileCompiler from '../compiler/test-file/formats/typescript/compiler';
import {
getTypeScriptTestList,
getTypeScriptTestListFromCode,
} from '../compiler/test-file/formats/typescript/get-test-list';
I/O Contract
TypeScriptTestFileCompiler Constructor
| Input |
Type |
Description
|
| compilerOptions |
TypeScriptCompilerOptions (optional) |
Object with configPath (path to tsconfig.json), options (custom compiler options object), and customCompilerModulePath (path to alternative TypeScript module)
|
| baseUrl |
string (optional) |
Base URL for resolving relative page URLs in tests
|
| esm |
boolean (optional) |
When true, enables ESM compilation mode with additional V8 optimization disabling
|
_precompileCode(testFilesInfo)
| Input |
Type |
Description
|
| testFilesInfo |
TestFileInfo[] |
Array of { filename: string } objects identifying test files to compile
|
| Output |
Type |
Description
|
| compiledCodes |
string[] |
Array of compiled JavaScript strings, one per input file, retrieved from the cache after batch compilation
|
_compileFilesToCache(ts, filenames)
| Input |
Type |
Description
|
| ts |
TypeScriptInstance |
The loaded TypeScript compiler module
|
| filenames |
string[] |
Array of absolute paths to .ts/.tsx files to compile
|
| Output |
Type |
Description
|
| (side effect) |
void |
Populates this.cache with compiled JavaScript keyed by normalized filename; throws on diagnostic errors
|
TypeScriptTestFileParser.parse(code)
| Input |
Type |
Description
|
| code |
string |
TypeScript source code to parse for fixture/test declarations
|
| Output |
Type |
Description
|
| testList |
object[] |
Array of fixture/test descriptors with fnName, value, loc, start, end, meta, isSkipped
|
Supported File Extensions
| Extension |
Compiled By |
Notes
|
| .ts |
TypeScriptTestFileCompiler |
Native TypeScript compilation
|
| .tsx |
TypeScriptTestFileCompiler |
TypeScript with JSX
|
| .js |
ESNextTestFileCompiler (fallback) |
Babel-based compilation for JS dependencies
|
| .jsx |
ESNextTestFileCompiler (fallback) |
Babel-based compilation for JSX dependencies
|
| .cjs |
ESNextTestFileCompiler (fallback) |
CommonJS modules
|
| .mjs |
ESNextTestFileCompiler (fallback) |
ESM modules (only in ESM mode)
|
Usage Examples
// Compile TypeScript test files (internal usage):
import TypeScriptTestFileCompiler from '../compiler/test-file/formats/typescript/compiler';
const compiler = new TypeScriptTestFileCompiler(
{ configPath: './tsconfig.json', options: { strict: true } },
{ baseUrl: null, esm: false }
);
// Batch precompilation (more efficient than one-by-one):
const testFiles = [
{ filename: '/tests/login.ts' },
{ filename: '/tests/dashboard.ts' },
];
const compiledCodes = await compiler._compileCodeForTestFiles(testFiles);
// compiledCodes[0] = compiled JS for login.ts
// compiledCodes[1] = compiled JS for dashboard.ts
// Discover tests from TypeScript source without executing:
import { getTypeScriptTestListFromCode } from '../compiler/test-file/formats/typescript/get-test-list';
const code = `
import { Selector } from 'testcafe';
fixture('Admin Panel')
.page('https://example.com/admin');
test('should display dashboard', async (t: TestController) => {
await t.expect(Selector('#dashboard').exists).ok();
});
test.skip('should export data', async (t: TestController) => {
// not yet implemented
});
`;
const tests = getTypeScriptTestListFromCode(code);
// tests = [
// { fnName: 'fixture', value: 'Admin Panel', loc: {...}, ... },
// { fnName: 'test', value: 'should display dashboard', isSkipped: false, ... },
// { fnName: 'test', value: 'should export data', isSkipped: true, ... },
// ]
// User-facing configuration in .testcaferc.json:
// {
// "compilerOptions": {
// "typescript": {
// "configPath": "tsconfig.testcafe.json",
// "customCompilerModulePath": "typescript",
// "options": {
// "strict": true,
// "esModuleInterop": true
// }
// }
// }
// }
Related Pages