Skip to content

Instantly share code, notes, and snippets.

@Hotell
Last active October 6, 2017 16:21
Show Gist options
  • Save Hotell/f88c7588d6e878df87fe01f12019de1f to your computer and use it in GitHub Desktop.
Save Hotell/f88c7588d6e878df87fe01f12019de1f to your computer and use it in GitHub Desktop.
tweaking testcafe to consume user tsconfig.json -> testcafe/src/compiler/test-file/formats/typescript/compiler.js
const path = require('path')
const fs = require('fs')
const _ = require('lodash')
const normalizeTsLib = lib => lib.map(libName => `lib.${libName}.d.ts`)
export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompilerBase {
static _getTypescriptOptions () {
// NOTE: lazy load the compiler
const ts = require('typescript');
const PATH_TO_TESTCAFE_ROOT = '../../../../../'
const PROJECT_ROOT = _path.resolve(__dirname, `${PATH_TO_TESTCAFE_ROOT}/../..`)
const defaultTSconfig = {
allowJs: true,
pretty: true,
inlineSourceMap: true,
noImplicitAny: false,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2015,
lib: ['lib.es6.d.ts'],
baseUrl: __dirname,
paths: { testcafe: [`${PATH_TO_TESTCAFE_ROOT}ts-defs/index.d.ts`] },,
suppressOutputPathCheck: true,
skipLibCheck: true,
}
const tsFileConfigPath = ts.findConfigFile(PROJECT_ROOT, filename => fs.existsSync(filename) )
const tsConfigRawFile = tsFileConfigPath ? fs.readFileSync(tsFileConfigPath, 'utf8') : '{}'
const { config: tsConfig } = ts.parseConfigFileTextToJson(tsFileConfigPath, tsConfigRawFile, true)
const finalTSconfigCompileOptions = Object.assign(
{},
defaultTSconfig,
pickCompilerOptions,
{
lib: defaultTSconfig.lib.concat(normalizeTsLib(tsConfig.compilerOptions.lib || [])),
paths: tsConfig.compilerOptions.paths || {},
}
)
return finalTSconfigCompileOptions
}
static _reportErrors (diagnostics) {
// NOTE: lazy load the compiler
var ts = require('typescript');
var errMsg = 'TypeScript compilation failed.\n';
diagnostics.forEach(d => {
var file = d.file;
var { line, character } = file.getLineAndCharacterOfPosition(d.start);
var message = ts.flattenDiagnosticMessageText(d.messageText, '\n');
errMsg += `${file.fileName} (${line + 1}, ${character + 1}): ${message}\n`;
});
throw new Error(errMsg);
}
static _normalizeFilename (filename) {
filename = path.resolve(filename);
if (OS.win)
filename = filename.toLowerCase();
return filename;
}
_compileCode (code, filename) {
// NOTE: lazy load the compiler
var ts = require('typescript');
var normalizedFilename = TypeScriptTestFileCompiler._normalizeFilename(filename);
if (this.cache[normalizedFilename])
return this.cache[normalizedFilename];
var opts = TypeScriptTestFileCompiler._getTypescriptOptions();
var program = ts.createProgram([filename], opts);
program.getSourceFiles().forEach(sourceFile => {
sourceFile.renamedDependencies = RENAMED_DEPENDENCIES_MAP;
});
var diagnostics = ts.getPreEmitDiagnostics(program);
if (diagnostics.length)
TypeScriptTestFileCompiler._reportErrors(diagnostics);
// NOTE: The first argument of emit() is a source file to be compiled. If it's undefined, all files in
// <program> will be compiled. <program> contains a file specified in createProgram() plus all its dependencies.
// This mode is much faster than compiling files one-by-one, and it is used in the tsc CLI compiler.
program.emit(void 0, (outputName, result, writeBOM, onError, sources) => {
var sourcePath = TypeScriptTestFileCompiler._normalizeFilename(sources[0].fileName);
this.cache[sourcePath] = result;
});
return this.cache[normalizedFilename];
}
_getRequireCompilers () {
return {
'.ts': (code, filename) => this._compileCode(code, filename),
'.js': (code, filename) => ESNextTestFileCompiler.prototype._compileCode.call(this, code, filename)
};
}
getSupportedExtension () {
return '.ts';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment