/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import {runOneBuild} from '@angular/bazel'; import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; import {createTsConfig} from './tsconfig_template'; export interface TestSupport { basePath: string; runfilesPath: string; angularCorePath: string; typesRoots: string; writeConfig({ srcTargetPath, depPaths, pathMapping, }: { srcTargetPath: string, depPaths?: string[], pathMapping?: Array<{moduleName: string; path: string;}>, }): {compilerOptions: ts.CompilerOptions}; read(fileName: string): string; write(fileName: string, content: string): void; writeFiles(...mockDirs: {[fileName: string]: string}[]): void; shouldExist(fileName: string): void; shouldNotExist(fileName: string): void; runOneBuild(): boolean; } export function setup({ bazelBin = 'bazel-bin', tsconfig = 'tsconfig.json', }: { bazelBin?: string, tsconfig?: string, } = {}): TestSupport { const runfilesPath = process.env['TEST_SRCDIR']; const basePath = makeTempDir(runfilesPath); const bazelBinPath = path.resolve(basePath, bazelBin); fs.mkdirSync(bazelBinPath); const angularCorePath = path.dirname(require.resolve('angular/packages/core')); const tsConfigJsonPath = path.resolve(basePath, tsconfig); const emptyTsConfig = ts.readConfigFile( require.resolve('angular/packages/bazel/test/ngc-wrapped/empty/empty_tsconfig.json'), read); const typesRoots = (emptyTsConfig as any).config.compilerOptions.typeRoots[0]; return { basePath, runfilesPath, angularCorePath, typesRoots, write, read, writeFiles, writeConfig, shouldExist, shouldNotExist, runOneBuild: runOneBuildImpl, }; // ----------------- // helpers function mkdirp(dirname: string) { const parent = path.dirname(dirname); if (!fs.existsSync(parent)) { mkdirp(parent); } fs.mkdirSync(dirname); } function write(fileName: string, content: string) { const dir = path.dirname(fileName); if (dir != '.') { const newDir = path.resolve(basePath, dir); if (!fs.existsSync(newDir)) mkdirp(newDir); } fs.writeFileSync(path.resolve(basePath, fileName), content, {encoding: 'utf-8'}); } function read(fileName: string) { return fs.readFileSync(path.resolve(basePath, fileName), {encoding: 'utf-8'}); } function writeFiles(...mockDirs: {[fileName: string]: string}[]) { mockDirs.forEach((dir) => { Object.keys(dir).forEach((fileName) => { write(fileName, dir[fileName]); }); }); } function writeConfig({ srcTargetPath, depPaths = [], pathMapping = [], }: { srcTargetPath: string, depPaths?: string[], pathMapping?: Array<{moduleName: string; path: string;}>, }) { srcTargetPath = path.resolve(basePath, srcTargetPath); const compilationTargetSrc = listFilesRecursive(srcTargetPath); const target = '//' + path.relative(basePath, srcTargetPath); const files = [...compilationTargetSrc]; depPaths = depPaths.concat([angularCorePath]); pathMapping = pathMapping.concat([ {moduleName: '@angular/core', path: angularCorePath}, {moduleName: 'angular/packages/core', path: angularCorePath} ]); for (const depPath of depPaths) { files.push(...listFilesRecursive(depPath).filter(f => f.endsWith('.d.ts'))); } const pathMappingObj = {}; for (const mapping of pathMapping) { pathMappingObj[mapping.moduleName] = [mapping.path]; pathMappingObj[path.posix.join(mapping.moduleName, '*')] = [path.posix.join(mapping.path, '*')]; } const emptyTsConfig = ts.readConfigFile( require.resolve('angular/packages/bazel/test/ngc-wrapped/empty/empty_tsconfig.json'), read); const tsconfig = createTsConfig({ defaultTsConfig: emptyTsConfig.config, rootDir: basePath, target: target, outDir: bazelBinPath, compilationTargetSrc, files: files, pathMapping: pathMappingObj, }); write(path.resolve(basePath, tsConfigJsonPath), JSON.stringify(tsconfig, null, 2)); return tsconfig; } function shouldExist(fileName: string) { if (!fs.existsSync(path.resolve(basePath, fileName))) { throw new Error(`Expected ${fileName} to be emitted (basePath: ${basePath})`); } } function shouldNotExist(fileName: string) { if (fs.existsSync(path.resolve(basePath, fileName))) { throw new Error(`Did not expect ${fileName} to be emitted (basePath: ${basePath})`); } } function runOneBuildImpl(): boolean { return runOneBuild(['@' + tsConfigJsonPath]); } } function makeTempDir(baseDir: string): string { const id = (Math.random() * 1000000).toFixed(0); const dir = path.join(baseDir, `tmp.${id}`); fs.mkdirSync(dir); return dir; } export function listFilesRecursive(dir: string, fileList: string[] = []) { fs.readdirSync(dir).forEach(file => { if (fs.statSync(path.join(dir, file)).isDirectory()) { listFilesRecursive(path.join(dir, file), fileList); } else { fileList.push(path.join(dir, file)); } }); return fileList; }