Kristiyan Kostadinov 3f9be429fc test(compiler-cli): error when running tests on non-posix systems (#39005)
We weren't resolving a path correctly which resulted in an error on Windows.
For reference, here's the error. Note the extra slash before `C:`:

```
Error: ENOENT: no such file or directory, scandir '/C:/bazel_output_root/yxvwd24o/external/npm/node_modules/typescript'
    at Object.readdirSync (fs.js:854:3)
```

PR Close #39005
2020-09-28 16:27:01 -04:00

118 lines
3.8 KiB
TypeScript

/**
* @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
*/
/// <reference types="node" />
import {readdirSync, readFileSync, statSync} from 'fs';
import {resolve} from 'path';
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '..';
import {AbsoluteFsPath, FileSystem, getFileSystem} from '../../../src/ngtsc/file_system';
import {Folder, MockFileSystemPosix, TestFile} from '../../../src/ngtsc/file_system/testing';
export function loadTestFiles(files: TestFile[]) {
const fs = getFileSystem();
files.forEach(file => {
fs.ensureDir(fs.dirname(file.name));
fs.writeFile(file.name, file.contents);
});
}
/**
* A folder that is lazily loaded upon first access and then cached.
*/
class CachedFolder {
private folder: Folder|null = null;
constructor(private loader: () => Folder) {}
get(): Folder {
if (this.folder === null) {
this.folder = this.loader();
}
return this.folder;
}
}
const typescriptFolder = new CachedFolder(() => loadFolder(resolveNpmTreeArtifact('typescript')));
const angularFolder = new CachedFolder(loadAngularFolder);
const rxjsFolder = new CachedFolder(() => loadFolder(resolveNpmTreeArtifact('rxjs')));
export function loadStandardTestFiles(
{fakeCore = true, rxjs = false}: {fakeCore?: boolean, rxjs?: boolean} = {}): Folder {
const tmpFs = new MockFileSystemPosix(true);
const basePath = '/' as AbsoluteFsPath;
tmpFs.mount(tmpFs.resolve('/node_modules/typescript'), typescriptFolder.get());
loadTsLib(tmpFs, basePath);
if (fakeCore) {
loadFakeCore(tmpFs, basePath);
} else {
tmpFs.mount(tmpFs.resolve('/node_modules/@angular'), angularFolder.get());
}
if (rxjs) {
tmpFs.mount(tmpFs.resolve('/node_modules/rxjs'), rxjsFolder.get());
}
return tmpFs.dump();
}
export function loadTsLib(fs: FileSystem, basePath: string = '/') {
loadTestDirectory(
fs, resolveNpmTreeArtifact('tslib'), fs.resolve(basePath, 'node_modules/tslib'));
}
export function loadFakeCore(fs: FileSystem, basePath: string = '/') {
loadTestDirectory(
fs, resolveNpmTreeArtifact('angular/packages/compiler-cli/test/ngtsc/fake_core/npm_package'),
fs.resolve(basePath, 'node_modules/@angular/core'));
}
function loadFolder(path: string): Folder {
const tmpFs = new MockFileSystemPosix(true);
// Note that we intentionally pass the native `path`, without resolving it through the file
// system, because the mock posix file system may break paths coming from a non-posix system.
loadTestDirectory(tmpFs, path, tmpFs.resolve('/'));
return tmpFs.dump();
}
function loadAngularFolder(): Folder {
const tmpFs = new MockFileSystemPosix(true);
getAngularPackagesFromRunfiles().forEach(({name, pkgPath}) => {
loadTestDirectory(tmpFs, pkgPath, tmpFs.resolve(name));
});
return tmpFs.dump();
}
/**
* Load real files from the real file-system into a mock file-system.
* @param fs the file-system where the directory is to be loaded.
* @param directoryPath the path to the directory we want to load.
* @param mockPath the path within the mock file-system where the directory is to be loaded.
*/
export function loadTestDirectory(
fs: FileSystem, directoryPath: string, mockPath: AbsoluteFsPath): void {
readdirSync(directoryPath).forEach(item => {
const srcPath = resolve(directoryPath, item);
const targetPath = fs.resolve(mockPath, item);
try {
if (statSync(srcPath).isDirectory()) {
fs.ensureDir(targetPath);
loadTestDirectory(fs, srcPath, targetPath);
} else {
fs.ensureDir(fs.dirname(targetPath));
fs.writeFile(targetPath, readFileSync(srcPath, 'utf-8'));
}
} catch (e) {
console.warn(`Failed to add ${srcPath} to the mock file-system: ${e.message}`);
}
});
}