diff --git a/packages/compiler/test/BUILD.bazel b/packages/compiler/test/BUILD.bazel index e836738546..8a3d929988 100644 --- a/packages/compiler/test/BUILD.bazel +++ b/packages/compiler/test/BUILD.bazel @@ -1,18 +1,24 @@ load("//tools:defaults.bzl", "ts_library", "ts_web_test") load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test") +# Test that should only be run in node +NODE_ONLY = [ + "**/*_node_only_spec.ts", + "aot/**/*.ts", + "render3/**/*.ts", +] + ts_library( name = "test_lib", testonly = 1, srcs = glob( ["**/*.ts"], - exclude = ["**/*_node_only_spec.ts"], + exclude = NODE_ONLY, ), deps = [ "//packages:types", "//packages/common", "//packages/compiler", - "//packages/compiler-cli", "//packages/compiler/testing", "//packages/core", "//packages/core/testing", @@ -25,19 +31,25 @@ ts_library( ts_library( name = "test_node_only_lib", testonly = 1, - srcs = glob(["**/*_node_only_spec.ts"]), + srcs = glob(NODE_ONLY), deps = [ ":test_lib", "//packages/compiler", + "//packages/compiler-cli", "//packages/compiler/testing", + "//packages/core", ], ) jasmine_node_test( name = "test", bootstrap = ["angular/tools/testing/init_node_spec.js"], + data = [ + "//packages/animations:npm_package", + "//packages/common:npm_package", + "//packages/core:npm_package", + ], # dissable since tests are running but not yet passing - tags = ["manual"], deps = [ ":test_lib", ":test_node_only_lib", @@ -49,7 +61,6 @@ jasmine_node_test( ts_web_test( name = "test_web", # disable since tests are running but not yet passing - tags = ["manual"], deps = [ ":test_lib", ], diff --git a/packages/compiler/test/aot/compiler_spec.ts b/packages/compiler/test/aot/compiler_spec.ts index bbb01f14f4..e6ba20fae6 100644 --- a/packages/compiler/test/aot/compiler_spec.ts +++ b/packages/compiler/test/aot/compiler_spec.ts @@ -13,7 +13,7 @@ import {extractSourceMap, originalPositionFor} from '@angular/compiler/testing/s import {NodeFlags} from '@angular/core/src/view/index'; import * as ts from 'typescript'; -import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, settings, setup, toMockFileArray} from './test_util'; +import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, isInBazel, settings, setup, toMockFileArray} from './test_util'; describe('compiler (unbundled Angular)', () => { let angularFiles = setup(); @@ -872,30 +872,31 @@ describe('compiler (unbundled Angular)', () => { }); describe('compiler (bundled Angular)', () => { - setup({compileAngular: false, compileAnimations: false}); - - let angularFiles: Map; + let angularFiles: Map = setup(); beforeAll(() => { - const emittingHost = new EmittingCompilerHost(['@angular/core/index'], {emitMetadata: false}); + if (!isInBazel()) { + // If we are not using Bazel then we need to build these files explicitly + const emittingHost = new EmittingCompilerHost(['@angular/core/index'], {emitMetadata: false}); - // Create the metadata bundled - const indexModule = emittingHost.effectiveName('@angular/core/index'); - const bundler = new MetadataBundler( - indexModule, '@angular/core', new MockMetadataBundlerHost(emittingHost)); - const bundle = bundler.getMetadataBundle(); - const metadata = JSON.stringify(bundle.metadata, null, ' '); - const bundleIndexSource = privateEntriesToIndex('./index', bundle.privates); - emittingHost.override('@angular/core/bundle_index.ts', bundleIndexSource); - emittingHost.addWrittenFile( - '@angular/core/package.json', JSON.stringify({typings: 'bundle_index.d.ts'})); - emittingHost.addWrittenFile('@angular/core/bundle_index.metadata.json', metadata); + // Create the metadata bundled + const indexModule = emittingHost.effectiveName('@angular/core/index'); + const bundler = new MetadataBundler( + indexModule, '@angular/core', new MockMetadataBundlerHost(emittingHost)); + const bundle = bundler.getMetadataBundle(); + const metadata = JSON.stringify(bundle.metadata, null, ' '); + const bundleIndexSource = privateEntriesToIndex('./index', bundle.privates); + emittingHost.override('@angular/core/bundle_index.ts', bundleIndexSource); + emittingHost.addWrittenFile( + '@angular/core/package.json', JSON.stringify({typings: 'bundle_index.d.ts'})); + emittingHost.addWrittenFile('@angular/core/bundle_index.metadata.json', metadata); - // Emit the sources - const bundleIndexName = emittingHost.effectiveName('@angular/core/bundle_index.ts'); - const emittingProgram = ts.createProgram([bundleIndexName], settings, emittingHost); - emittingProgram.emit(); - angularFiles = emittingHost.writtenAngularFiles(); + // Emit the sources + const bundleIndexName = emittingHost.effectiveName('@angular/core/bundle_index.ts'); + const emittingProgram = ts.createProgram([bundleIndexName], settings, emittingHost); + emittingProgram.emit(); + angularFiles = emittingHost.writtenAngularFiles(); + } }); describe('Quickstart', () => { @@ -922,6 +923,11 @@ describe('compiler (bundled Angular)', () => { const emittingHost = new EmittingCompilerHost(['/bolder/index.ts'], {emitMetadata: false, mockData: LIBRARY}); + if (isInBazel()) { + // In bazel we can just add the angular files from the ones read during setup. + emittingHost.addFiles(angularFiles); + } + // Create the metadata bundled const indexModule = '/bolder/public-api'; const bundler = diff --git a/packages/compiler/test/aot/test_util.ts b/packages/compiler/test/aot/test_util.ts index e6f3078463..2a92800aa6 100644 --- a/packages/compiler/test/aot/test_util.ts +++ b/packages/compiler/test/aot/test_util.ts @@ -60,8 +60,6 @@ export interface EmitterOptions { function calcPathsOnDisc() { const moduleFilename = module.filename.replace(/\\/g, '/'); - // TODO(i): this is suspicious because it relies on build.sh output - // which is problematic when we are running tests under bazel - review with Chuck const distIndex = moduleFilename.indexOf('/dist/all'); if (distIndex >= 0) { rootPath = moduleFilename.substr(0, distIndex); @@ -83,7 +81,7 @@ export class EmittingCompilerHost implements ts.CompilerHost { // Rewrite references to scripts with '@angular' to its corresponding location in // the source tree. this.scriptNames = scriptNames.map(f => this.effectiveName(f)); - this.root = rootPath; + this.root = rootPath || this.root; if (options.context) { this.addedFiles = mergeMaps(options.context); } @@ -110,6 +108,12 @@ export class EmittingCompilerHost implements ts.CompilerHost { this.cachedAddedDirectories = undefined; } + public addFiles(map: Map) { + for (const [name, content] of Array.from(map.entries())) { + this.addedFiles.set(name, content); + } + } + public addWrittenFile(fileName: string, content: string) { this.writtenFiles.set(this.effectiveName(fileName), content); } @@ -124,7 +128,7 @@ export class EmittingCompilerHost implements ts.CompilerHost { public effectiveName(fileName: string): string { const prefix = '@angular/'; - return fileName.startsWith('@angular/') ? + return angularSourcePath && fileName.startsWith(prefix) ? path.join(angularSourcePath, fileName.substr(prefix.length)) : fileName; } @@ -566,6 +570,38 @@ const minCoreIndex = ` export * from './src/codegen_private_exports'; `; +function readBazelWrittenFilesFrom( + bazelPackageRoot: string, packageName: string, map: Map, + skip: (name: string, fullName: string) => boolean = () => false) { + function processDirectory(dir: string, dest: string) { + const entries = fs.readdirSync(dir); + for (const name of entries) { + const fullName = path.join(dir, name); + const destName = path.join(dest, name); + const stat = fs.statSync(fullName); + if (!skip(name, fullName)) { + if (stat.isDirectory()) { + processDirectory(fullName, destName); + } else { + const content = fs.readFileSync(fullName, 'utf8'); + map.set(destName, content); + } + } + } + } + try { + processDirectory(bazelPackageRoot, path.join('/node_modules/@angular', packageName)); + } catch (e) { + console.error( + `Consider adding //packages/${packageName} as a data dependency in the BUILD.bazel rule for the failing test`); + throw e; + } +} + +export function isInBazel(): boolean { + return process.env.TEST_SRCDIR != null; +} + export function setup( options: {compileAngular: boolean, compileAnimations: boolean, compileCommon?: boolean} = { compileAngular: true, @@ -575,6 +611,36 @@ export function setup( let angularFiles = new Map(); beforeAll(() => { + const sources = process.env.TEST_SRCDIR; + if (sources) { + // If running under bazel then we get the compiled version of the files from the bazel package + // output. + const bundles = new Set([ + 'bundles', 'esm2015', 'esm5', 'testing', 'testing.d.ts', 'testing.metadata.json', 'browser', + 'browser.d.ts' + ]); + const skipDirs = (name: string) => bundles.has(name); + if (options.compileAngular) { + // If this fails please add //packages/core:npm_package as a test data dependency. + readBazelWrittenFilesFrom( + path.join(sources, 'angular/packages/core/npm_package'), 'core', angularFiles, + skipDirs); + } + if (options.compileAnimations) { + // If this fails please add //packages/animations:npm_package as a test data dependency. + readBazelWrittenFilesFrom( + path.join(sources, 'angular/packages/animations/npm_package'), 'animations', + angularFiles, skipDirs); + } + if (options.compileCommon) { + // If this fails please add //packages/common:npm_package as a test data dependency. + readBazelWrittenFilesFrom( + path.join(sources, 'angular/packages/common/npm_package'), 'common', angularFiles, + skipDirs); + } + return; + } + if (options.compileAngular) { const emittingHost = new EmittingCompilerHost([], {emitMetadata: true}); emittingHost.addScript('@angular/core/index.ts', minCoreIndex);