diff --git a/package.json b/package.json index f63207cd1da4..67cdf2a24509 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "homepage": "https://github.com/angular/angular-cli", "dependencies": { "@angular-cli/ast-tools": "^1.0.0", - "@angular/compiler": "2.2.3", - "@angular/compiler-cli": "2.2.3", - "@angular/core": "2.2.3", - "@angular/tsc-wrapped": "0.4.0", + "@angular/compiler": "~2.3.1", + "@angular/compiler-cli": "~2.3.1", + "@angular/core": "~2.3.1", + "@angular/tsc-wrapped": "~0.5.0", "async": "^2.1.4", "autoprefixer": "^6.5.3", "chalk": "^1.1.3", @@ -101,7 +101,7 @@ "resolve": "^1.1.7", "rimraf": "^2.5.3", "rsvp": "^3.0.17", - "rxjs": "5.0.0-beta.12", + "rxjs": "5.0.0-rc.4", "sass-loader": "^4.0.1", "script-loader": "^0.7.0", "semver": "^5.1.0", diff --git a/packages/@angular-cli/ast-tools/package.json b/packages/@angular-cli/ast-tools/package.json index 90430e794519..dd2c6366c0de 100644 --- a/packages/@angular-cli/ast-tools/package.json +++ b/packages/@angular-cli/ast-tools/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@angular/tsc-wrapped": "^0.3.0", - "rxjs": "5.0.0-beta.12", + "rxjs": "5.0.0-rc.4", "denodeify": "^1.2.1", "typescript": "~2.0.3" } diff --git a/packages/@ngtools/webpack/package.json b/packages/@ngtools/webpack/package.json index 865b2a9863bb..0744ba0c3541 100644 --- a/packages/@ngtools/webpack/package.json +++ b/packages/@ngtools/webpack/package.json @@ -31,10 +31,10 @@ "source-map": "^0.5.6" }, "peerDependencies": { - "@angular/compiler": "2.2.3", - "@angular/compiler-cli": "2.2.3", - "@angular/core": "2.2.3", - "@angular/tsc-wrapped": "0.4.0", + "@angular/compiler": "~2.3.1", + "@angular/compiler-cli": "~2.3.1", + "@angular/core": "~2.3.1", + "@angular/tsc-wrapped": "~0.5.0", "typescript": "^2.0.2", "reflect-metadata": "^0.1.8", "webpack": "^2.1.0-beta.25" diff --git a/packages/@ngtools/webpack/src/plugin.ts b/packages/@ngtools/webpack/src/plugin.ts index bedf13c604b6..5870f4b56e97 100644 --- a/packages/@ngtools/webpack/src/plugin.ts +++ b/packages/@ngtools/webpack/src/plugin.ts @@ -2,16 +2,13 @@ import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; -import {NgModule} from '@angular/core'; -import * as ngCompiler from '@angular/compiler-cli'; -import {tsc} from '@angular/tsc-wrapped/src/tsc'; +import {__NGTOOLS_PRIVATE_API_2} from '@angular/compiler-cli'; +import {AngularCompilerOptions} from '@angular/tsc-wrapped'; -import {patchReflectorHost} from './reflector_host'; import {WebpackResourceLoader} from './resource_loader'; import {createResolveDependenciesFromContextMap} from './utils'; import {WebpackCompilerHost} from './compiler_host'; import {resolveEntryModuleFromMain} from './entry_resolver'; -import {StaticSymbol} from '@angular/compiler-cli'; import {Tapable} from './webpack'; import {PathsPlugin} from './paths-plugin'; @@ -29,47 +26,22 @@ export interface AotPluginOptions { i18nFile?: string; i18nFormat?: string; locale?: string; -} - -export interface LazyRoute { - moduleRoute: ModuleRoute; - absolutePath: string; - absoluteGenDirPath: string; -} - - -export interface LazyRouteMap { - [path: string]: LazyRoute; -} - - -export class ModuleRoute { - constructor(public readonly path: string, public readonly className: string = null) {} - - toString() { - return `${this.path}#${this.className}`; - } - - static fromString(entry: string): ModuleRoute { - const split = entry.split('#'); - return new ModuleRoute(split[0], split[1]); - } + // Use tsconfig to include path globs. + exclude?: string | string[]; } export class AotPlugin implements Tapable { - private _entryModule: ModuleRoute; private _compilerOptions: ts.CompilerOptions; - private _angularCompilerOptions: ngCompiler.AngularCompilerOptions; + private _angularCompilerOptions: AngularCompilerOptions; private _program: ts.Program; - private _reflector: ngCompiler.StaticReflector; - private _reflectorHost: ngCompiler.ReflectorHost; private _rootFilePath: string[]; private _compilerHost: WebpackCompilerHost; private _resourceLoader: WebpackResourceLoader; private _lazyRoutes: { [route: string]: string }; private _tsConfigPath: string; + private _entryModule: string; private _donePromise: Promise; private _compiler: any = null; @@ -93,7 +65,12 @@ export class AotPlugin implements Tapable { get compilerHost() { return this._compilerHost; } get compilerOptions() { return this._compilerOptions; } get done() { return this._donePromise; } - get entryModule() { return this._entryModule; } + get entryModule() { + const splitted = this._entryModule.split('#'); + const path = splitted[0]; + const className = splitted[1] || 'default'; + return {path, className}; + } get genDir() { return this._genDir; } get program() { return this._program; } get skipCodeGeneration() { return this._skipCodeGeneration; } @@ -119,19 +96,59 @@ export class AotPlugin implements Tapable { basePath = path.resolve(process.cwd(), options.basePath); } - const tsConfig = tsc.readConfiguration(this._tsConfigPath, basePath); - this._rootFilePath = tsConfig.parsed.fileNames - .filter(fileName => !/\.spec\.ts$/.test(fileName)); + let tsConfigJson: any = null; + try { + tsConfigJson = JSON.parse(fs.readFileSync(this._tsConfigPath, 'utf8')); + } catch (err) { + throw new Error(`An error happened while parsing ${this._tsConfigPath} JSON: ${err}.`); + } + const tsConfig = ts.parseJsonConfigFileContent( + tsConfigJson, ts.sys, basePath, null, this._tsConfigPath); + + let fileNames = tsConfig.fileNames; + if (options.hasOwnProperty('exclude')) { + let exclude: string[] = typeof options.exclude == 'string' + ? [options.exclude as string] : (options.exclude as string[]); + + exclude.forEach((pattern: string) => { + const basePathPattern = '(' + basePath.replace(/\\/g, '/') + .replace(/[\-\[\]\/{}()+?.\\^$|*]/g, '\\$&') + ')?'; + pattern = pattern + // Replace windows path separators with forward slashes. + .replace(/\\/g, '/') + // Escape characters that are used normally in regexes, except stars. + .replace(/[\-\[\]{}()+?.\\^$|]/g, '\\$&') + // Two stars replacement. + .replace(/\*\*/g, '(?:.*)') + // One star replacement. + .replace(/\*/g, '(?:[^/]*)') + // Escape characters from the basePath and make sure it's forward slashes. + .replace(/^/, basePathPattern); + + const re = new RegExp('^' + pattern + '$'); + fileNames = fileNames.filter(x => !x.replace(/\\/g, '/').match(re)); + }); + } else { + fileNames = fileNames.filter(fileName => !/\.spec\.ts$/.test(fileName)); + } + this._rootFilePath = fileNames; // Check the genDir. let genDir = basePath; - if (tsConfig.ngOptions.hasOwnProperty('genDir')) { - genDir = tsConfig.ngOptions.genDir; - } - this._compilerOptions = tsConfig.parsed.options; + this._compilerOptions = tsConfig.options; + this._angularCompilerOptions = Object.assign( + { genDir }, + this._compilerOptions, + tsConfig.raw['angularCompilerOptions'], + { basePath } + ); + + if (this._angularCompilerOptions.hasOwnProperty('genDir')) { + genDir = path.resolve(basePath, this._angularCompilerOptions.genDir); + this._angularCompilerOptions.genDir = genDir; + } - this._angularCompilerOptions = Object.assign({}, tsConfig.ngOptions, { basePath, genDir }); this._basePath = basePath; this._genDir = genDir; @@ -147,21 +164,16 @@ export class AotPlugin implements Tapable { this._rootFilePath, this._compilerOptions, this._compilerHost); if (options.entryModule) { - this._entryModule = ModuleRoute.fromString(options.entryModule); + this._entryModule = options.entryModule; } else { if (options.mainPath) { - const entryModuleString = resolveEntryModuleFromMain(options.mainPath, this._compilerHost, + this._entryModule = resolveEntryModuleFromMain(options.mainPath, this._compilerHost, this._program); - this._entryModule = ModuleRoute.fromString(entryModuleString); } else { - this._entryModule = ModuleRoute.fromString((tsConfig.ngOptions as any).entryModule); + this._entryModule = (tsConfig.raw['angularCompilerOptions'] as any).entryModule; } } - this._reflectorHost = new ngCompiler.ReflectorHost( - this._program, this._compilerHost, this._angularCompilerOptions); - this._reflector = new ngCompiler.StaticReflector(this._reflectorHost); - if (options.hasOwnProperty('i18nFile')) { this._i18nFile = options.i18nFile; } @@ -239,13 +251,6 @@ export class AotPlugin implements Tapable { this._resourceLoader = new WebpackResourceLoader(compilation); - const i18nOptions: ngCompiler.NgcCliOptions = { - i18nFile: this.i18nFile, - i18nFormat: this.i18nFormat, - locale: this.locale, - basePath: this.basePath - }; - this._donePromise = Promise.resolve() .then(() => { if (this._skipCodeGeneration) { @@ -253,20 +258,18 @@ export class AotPlugin implements Tapable { } // Create the Code Generator. - const codeGenerator = ngCompiler.CodeGenerator.create( - this._angularCompilerOptions, - i18nOptions, - this._program, - this._compilerHost, - new ngCompiler.NodeReflectorHostContext(this._compilerHost), - this._resourceLoader - ); - - // We need to temporarily patch the CodeGenerator until either it's patched or allows us - // to pass in our own ReflectorHost. - // TODO: remove this. - patchReflectorHost(codeGenerator); - return codeGenerator.codegen({ transitiveModules: true }); + return __NGTOOLS_PRIVATE_API_2.codeGen({ + basePath: this._basePath, + compilerOptions: this._compilerOptions, + program: this._program, + host: this._compilerHost, + angularCompilerOptions: this._angularCompilerOptions, + i18nFile: this.i18nFile, + i18nFormat: this.i18nFormat, + locale: this.locale, + + readResource: (path: string) => this._resourceLoader.get(path) + }); }) .then(() => { // Create a new Program, based on the old one. This will trigger a resolution of all @@ -298,155 +301,25 @@ export class AotPlugin implements Tapable { .then(() => { // Process the lazy routes this._lazyRoutes = {}; - const allLazyRoutes = this._processNgModule(this._entryModule, null); + const allLazyRoutes = __NGTOOLS_PRIVATE_API_2.listLazyRoutes({ + program: this._program, + host: this._compilerHost, + angularCompilerOptions: this._angularCompilerOptions, + entryModule: this._entryModule + }); Object.keys(allLazyRoutes) .forEach(k => { const lazyRoute = allLazyRoutes[k]; if (this.skipCodeGeneration) { - this._lazyRoutes[k] = lazyRoute.absolutePath + '.ts'; + this._lazyRoutes[k] = lazyRoute; } else { - this._lazyRoutes[k + '.ngfactory'] = lazyRoute.absoluteGenDirPath + '.ngfactory.ts'; + const lr = path.relative(this.basePath, lazyRoute.replace(/\.ts$/, '.ngfactory.ts')); + this._lazyRoutes[k + '.ngfactory'] = path.join(this.genDir, lr); } }); }) - .then(() => cb(), (err: any) => { cb(err); }); - } - - private _resolveModulePath(module: ModuleRoute, containingFile: string) { - if (module.path.startsWith('.')) { - return path.join(path.dirname(containingFile), module.path); - } - return module.path; - } - - private _processNgModule(module: ModuleRoute, containingFile: string | null): LazyRouteMap { - const modulePath = containingFile ? module.path : ('./' + path.basename(module.path)); - if (containingFile === null) { - containingFile = module.path + '.ts'; - } - const relativeModulePath = this._resolveModulePath(module, containingFile); - - const staticSymbol = this._reflectorHost - .findDeclaration(modulePath, module.className, containingFile); - const entryNgModuleMetadata = this.getNgModuleMetadata(staticSymbol); - const loadChildrenRoute: LazyRoute[] = this.extractLoadChildren(entryNgModuleMetadata) - .map(route => { - const moduleRoute = ModuleRoute.fromString(route); - const resolvedModule = ts.resolveModuleName(moduleRoute.path, - relativeModulePath, this._compilerOptions, this._compilerHost); - - if (!resolvedModule.resolvedModule) { - throw new Error(`Could not resolve route "${route}" from file "${relativeModulePath}".`); - } - - const relativePath = path.relative(this.basePath, - resolvedModule.resolvedModule.resolvedFileName).replace(/\.ts$/, ''); - - const absolutePath = path.join(this.basePath, relativePath); - const absoluteGenDirPath = path.join(this._genDir, relativePath); - - return { - moduleRoute, - absoluteGenDirPath, - absolutePath - }; + .then(() => cb(), (err: any) => { + compilation.errors.push(err); }); - const resultMap: LazyRouteMap = loadChildrenRoute - .reduce((acc: LazyRouteMap, curr: LazyRoute) => { - const key = curr.moduleRoute.path; - if (acc[key]) { - if (acc[key].absolutePath != curr.absolutePath) { - throw new Error(`Duplicated path in loadChildren detected: "${key}" is used in 2 ` + - 'loadChildren, but they point to different modules. Webpack cannot distinguish ' + - 'between the two based on context and would fail to load the proper one.'); - } - } else { - acc[key] = curr; - } - return acc; - }, {}); - - // Also concatenate every child of child modules. - for (const lazyRoute of loadChildrenRoute) { - const mr = lazyRoute.moduleRoute; - const children = this._processNgModule(mr, relativeModulePath); - Object.keys(children).forEach(p => { - const child = children[p]; - const key = child.moduleRoute.path; - if (resultMap[key]) { - if (resultMap[key].absolutePath != child.absolutePath) { - throw new Error(`Duplicated path in loadChildren detected: "${key}" is used in 2 ` + - 'loadChildren, but they point to different modules. Webpack cannot distinguish ' + - 'between the two based on context and would fail to load the proper one.'); - } - } else { - resultMap[key] = child; - } - }); - } - return resultMap; - } - - private getNgModuleMetadata(staticSymbol: ngCompiler.StaticSymbol) { - const ngModules = this._reflector.annotations(staticSymbol).filter(s => s instanceof NgModule); - if (ngModules.length === 0) { - throw new Error(`${staticSymbol.name} is not an NgModule`); - } - return ngModules[0]; - } - - private extractLoadChildren(ngModuleDecorator: any): any[] { - const routes = (ngModuleDecorator.imports || []).reduce((mem: any[], m: any) => { - return mem.concat(this.collectRoutes(m.providers)); - }, this.collectRoutes(ngModuleDecorator.providers)); - return this.collectLoadChildren(routes) - .concat((ngModuleDecorator.imports || []) - // Also recursively extractLoadChildren of modules we import. - .map((staticSymbol: any) => { - if (staticSymbol instanceof StaticSymbol) { - const entryNgModuleMetadata = this.getNgModuleMetadata(staticSymbol); - return this.extractLoadChildren(entryNgModuleMetadata); - } else { - return []; - } - }) - // Poor man's flat map. - .reduce((acc: any[], i: any) => acc.concat(i), [])) - .filter(x => !!x); - } - - private collectRoutes(providers: any[]): any[] { - if (!providers) { - return []; - } - const ROUTES = this._reflectorHost.findDeclaration( - '@angular/router/src/router_config_loader', 'ROUTES', undefined); - - return providers.reduce((m, p) => { - if (p.provide === ROUTES) { - return m.concat(p.useValue); - } else if (Array.isArray(p)) { - return m.concat(this.collectRoutes(p)); - } else { - return m; - } - }, []); - } - - private collectLoadChildren(routes: any[]): any[] { - if (!routes) { - return []; - } - return routes.reduce((m, r) => { - if (r.loadChildren) { - return m.concat(r.loadChildren); - } else if (Array.isArray(r)) { - return m.concat(this.collectLoadChildren(r)); - } else if (r.children) { - return m.concat(this.collectLoadChildren(r.children)); - } else { - return m; - } - }, []); } } diff --git a/packages/@ngtools/webpack/src/refactor.ts b/packages/@ngtools/webpack/src/refactor.ts index 9ae55c401fd6..3ad8fc76d922 100644 --- a/packages/@ngtools/webpack/src/refactor.ts +++ b/packages/@ngtools/webpack/src/refactor.ts @@ -16,7 +16,12 @@ function resolve(filePath: string, host: ts.CompilerHost, program: ts.Program) { if (path.isAbsolute(filePath)) { return filePath; } - return path.join(program.getCompilerOptions().baseUrl || process.cwd(), filePath); + const compilerOptions = program.getCompilerOptions(); + const basePath = compilerOptions.baseUrl || compilerOptions.rootDir; + if (!basePath) { + throw new Error(`Trying to resolve '${filePath}' without a basePath.`); + } + return path.join(basePath, filePath); } diff --git a/packages/angular-cli/blueprints/ng2/files/package.json b/packages/angular-cli/blueprints/ng2/files/package.json index 2bd259ef1f0c..1bbbb1f52530 100644 --- a/packages/angular-cli/blueprints/ng2/files/package.json +++ b/packages/angular-cli/blueprints/ng2/files/package.json @@ -13,21 +13,21 @@ }, "private": true, "dependencies": { - "@angular/common": "2.2.3", - "@angular/compiler": "2.2.3", - "@angular/core": "2.2.3", - "@angular/forms": "2.2.3", - "@angular/http": "2.2.3", - "@angular/platform-browser": "2.2.3", - "@angular/platform-browser-dynamic": "2.2.3", + "@angular/common": "~2.3.1", + "@angular/compiler": "~2.3.1", + "@angular/core": "~2.3.1", + "@angular/forms": "~2.3.1", + "@angular/http": "~2.3.1", + "@angular/platform-browser": "~2.3.1", + "@angular/platform-browser-dynamic": "~2.3.1", "@angular/router": "3.2.3", "core-js": "^2.4.1", - "rxjs": "5.0.0-beta.12", + "rxjs": "5.0.0-rc.4", "ts-helpers": "^1.1.1", - "zone.js": "^0.6.23" + "zone.js": "^0.7.2" }, "devDependencies": { - "@angular/compiler-cli": "2.2.3", + "@angular/compiler-cli": "~2.3.1", "@types/jasmine": "2.5.38", "@types/node": "^6.0.42", "angular-cli": "<%= version %>", diff --git a/packages/angular-cli/commands/build.ts b/packages/angular-cli/commands/build.ts index 821b74e10d81..6584be61078d 100644 --- a/packages/angular-cli/commands/build.ts +++ b/packages/angular-cli/commands/build.ts @@ -1,3 +1,4 @@ +import {Version} from '../upgrade/version'; const Command = require('../ember-cli/lib/models/command'); import WebpackBuild from '../tasks/build-webpack'; import WebpackBuildWatch from '../tasks/build-webpack-watch'; @@ -59,6 +60,10 @@ const BuildCommand = Command.extend({ } const project = this.project; + + // Check angular version. + Version.assertAngularVersionIs2_3_1OrHigher(project.root); + const ui = this.ui; const buildTask = commandOptions.watch ? new WebpackBuildWatch({ diff --git a/packages/angular-cli/commands/serve.ts b/packages/angular-cli/commands/serve.ts index 38836cf50e46..abb0013f8e3d 100644 --- a/packages/angular-cli/commands/serve.ts +++ b/packages/angular-cli/commands/serve.ts @@ -4,6 +4,7 @@ const SilentError = require('silent-error'); const PortFinder = require('portfinder'); const Command = require('../ember-cli/lib/models/command'); import ServeWebpackTask from '../tasks/serve-webpack'; +import {Version} from '../upgrade/version'; PortFinder.basePort = 49152; @@ -121,6 +122,8 @@ const ServeCommand = Command.extend({ } } + // Check angular version. + Version.assertAngularVersionIs2_3_1OrHigher(this.project.root); commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host; return this._checkExpressPort(commandOptions) diff --git a/packages/angular-cli/models/webpack-build-typescript.ts b/packages/angular-cli/models/webpack-build-typescript.ts index 40de6bb09dd9..67940af47ab8 100644 --- a/packages/angular-cli/models/webpack-build-typescript.ts +++ b/packages/angular-cli/models/webpack-build-typescript.ts @@ -23,6 +23,10 @@ export const getWebpackNonAotConfigPartial = function(projectRoot: string, appCo new AotPlugin({ tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig), mainPath: path.join(projectRoot, appConfig.root, appConfig.main), + exclude: [ + path.join(projectRoot, appConfig.root, appConfig.test), + '**/*.spec.ts' + ], skipCodeGeneration: true }), ] @@ -47,8 +51,12 @@ export const getWebpackAotConfigPartial = function(projectRoot: string, appConfi mainPath: path.join(projectRoot, appConfig.root, appConfig.main), i18nFile: i18nFile, i18nFormat: i18nFormat, - locale: locale - }), + locale: locale, + exclude: [ + path.join(projectRoot, appConfig.root, appConfig.test), + '**/*.spec.ts' + ] + }) ] }; }; diff --git a/packages/angular-cli/package.json b/packages/angular-cli/package.json index c554acd35c3b..669496611686 100644 --- a/packages/angular-cli/package.json +++ b/packages/angular-cli/package.json @@ -27,9 +27,9 @@ "dependencies": { "@angular-cli/ast-tools": "^1.0.1", "@angular-cli/base-href-webpack": "^1.0.0", - "@angular/compiler": "2.2.3", - "@angular/compiler-cli": "2.2.3", - "@angular/core": "2.2.3", + "@angular/compiler": "~2.3.1", + "@angular/compiler-cli": "~2.3.1", + "@angular/core": "~2.3.1", "@ngtools/webpack": "^1.0.0", "async": "^2.1.4", "autoprefixer": "^6.5.3", diff --git a/packages/angular-cli/upgrade/version.ts b/packages/angular-cli/upgrade/version.ts index ac380c68500b..15decc70923f 100644 --- a/packages/angular-cli/upgrade/version.ts +++ b/packages/angular-cli/upgrade/version.ts @@ -45,6 +45,8 @@ export class Version { isReleaseCandidate() { return this.qualifier == 'rc'; } isKnown() { return this._version !== null; } + isLocal() { return this.isKnown() && path.isAbsolute(this._version); } + get major() { return this._parse()[0] || 0; } get minor() { return this._parse()[1] || 0; } get patch() { return this._parse()[2] || 0; } @@ -91,6 +93,36 @@ export class Version { } } + static assertAngularVersionIs2_3_1OrHigher(projectRoot: string) { + const angularCorePath = path.join(projectRoot, 'node_modules/@angular/core'); + const pkgJson = existsSync(angularCorePath) + ? JSON.parse(readFileSync(path.join(angularCorePath, 'package.json'), 'utf8')) + : null; + + // Just check @angular/core. + if (pkgJson && pkgJson['version']) { + const v = new Version(pkgJson['version']); + if (v.isLocal()) { + console.warn(yellow('Using a local version of angular. Proceeding with care...')); + } else { + if (v.major != 2 || ((v.minor == 3 && v.patch == 0) || v.minor < 3)) { + console.error(bold(red(stripIndents` + This version of CLI is only compatible with angular version 2.3.1 or better. Please + upgrade your angular version, e.g. by running: + + npm install @angular/core@latest + ` + '\n'))); + process.exit(3); + } + } + } else { + console.error(bold(red(stripIndents` + You seem to not be dependending on "@angular/core". This is an error. + `))); + process.exit(2); + } + } + static assertPostWebpackVersion() { if (this.isPreWebpack()) { console.error(bold(red('\n' + stripIndents` diff --git a/tests/e2e/assets/webpack/test-app-weird/not/so/source/tsconfig.json b/tests/e2e/assets/webpack/test-app-weird/not/so/source/tsconfig.json index 74a0d8f522a4..721113e471d8 100644 --- a/tests/e2e/assets/webpack/test-app-weird/not/so/source/tsconfig.json +++ b/tests/e2e/assets/webpack/test-app-weird/not/so/source/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "baseUrl": "", "module": "es2015", "moduleResolution": "node", "target": "es5", diff --git a/tests/e2e/assets/webpack/test-app-weird/package.json b/tests/e2e/assets/webpack/test-app-weird/package.json index 58992bd35b1c..8e70c25f017b 100644 --- a/tests/e2e/assets/webpack/test-app-weird/package.json +++ b/tests/e2e/assets/webpack/test-app-weird/package.json @@ -2,19 +2,19 @@ "name": "test", "license": "MIT", "dependencies": { - "@angular/common": "2.2.1", - "@angular/compiler": "2.2.1", - "@angular/compiler-cli": "2.2.1", - "@angular/core": "2.2.1", - "@angular/http": "2.2.1", - "@angular/platform-browser": "2.2.1", - "@angular/platform-browser-dynamic": "2.2.1", - "@angular/platform-server": "2.2.1", - "@angular/router": "3.2.1", + "@angular/common": "~2.3.1", + "@angular/compiler": "~2.3.1", + "@angular/compiler-cli": "~2.3.1", + "@angular/core": "~2.3.1", + "@angular/http": "~2.3.1", + "@angular/platform-browser": "~2.3.1", + "@angular/platform-browser-dynamic": "~2.3.1", + "@angular/platform-server": "~2.3.1", + "@angular/router": "~3.2.3", "@ngtools/webpack": "0.0.0", "core-js": "^2.4.1", - "rxjs": "^5.0.0-beta.12", - "zone.js": "^0.6.21" + "rxjs": "5.0.0-rc.4", + "zone.js": "^0.7.2" }, "devDependencies": { "node-sass": "^3.7.0", diff --git a/tests/e2e/assets/webpack/test-app/package.json b/tests/e2e/assets/webpack/test-app/package.json index 1cd7c2e4be78..97e03f5e8f6a 100644 --- a/tests/e2e/assets/webpack/test-app/package.json +++ b/tests/e2e/assets/webpack/test-app/package.json @@ -2,19 +2,19 @@ "name": "test", "license": "MIT", "dependencies": { - "@angular/common": "2.2.3", - "@angular/compiler": "2.2.3", - "@angular/compiler-cli": "2.2.3", - "@angular/core": "2.2.3", - "@angular/http": "2.2.3", - "@angular/platform-browser": "2.2.3", - "@angular/platform-browser-dynamic": "2.2.3", - "@angular/platform-server": "2.2.3", - "@angular/router": "3.2.3", + "@angular/common": "~2.3.1", + "@angular/compiler": "~2.3.1", + "@angular/compiler-cli": "~2.3.1", + "@angular/core": "~2.3.1", + "@angular/http": "~2.3.1", + "@angular/platform-browser": "~2.3.1", + "@angular/platform-browser-dynamic": "~2.3.1", + "@angular/platform-server": "~2.3.1", + "@angular/router": "~3.2.3", "@ngtools/webpack": "0.0.0", "core-js": "^2.4.1", - "rxjs": "^5.0.0-beta.12", - "zone.js": "^0.6.21" + "rxjs": "5.0.0-rc.4", + "zone.js": "^0.7.2" }, "devDependencies": { "node-sass": "^3.7.0", @@ -22,6 +22,6 @@ "raw-loader": "^0.5.1", "sass-loader": "^3.2.0", "typescript": "~2.0.3", - "webpack": "2.1.0-beta.22" + "webpack": "2.1.0-beta.25" } } diff --git a/tests/e2e/assets/webpack/test-app/tsconfig.json b/tests/e2e/assets/webpack/test-app/tsconfig.json index 585586e38d21..9f2725a20b0f 100644 --- a/tests/e2e/assets/webpack/test-app/tsconfig.json +++ b/tests/e2e/assets/webpack/test-app/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "baseUrl": "", "module": "es2015", "moduleResolution": "node", "target": "es5", diff --git a/tests/e2e/setup/010-build.ts b/tests/e2e/setup/010-build.ts index 230a2cb41ab8..70306b6ff811 100644 --- a/tests/e2e/setup/010-build.ts +++ b/tests/e2e/setup/010-build.ts @@ -1,10 +1,13 @@ +import {join} from 'path'; +import {getGlobalVariable} from '../utils/env'; import {npm} from '../utils/process'; import {updateJsonFile} from '../utils/project'; -import {join} from 'path'; const packages = require('../../../lib/packages'); export default function() { + const argv = getGlobalVariable('argv'); + return npm('run', 'build') .then(() => console.log('Updating package.json from dist...')) .then(() => Promise.all(Object.keys(packages).map(pkgName => { @@ -17,5 +20,33 @@ export default function() { } }); }); - }))); + }))) + .then(() => { + if (!argv.nightly && !argv['ng-sha']) { + return; + } + + console.log('Updating package.json from dist for nightly Angular packages...'); + const label = argv['ng-sha'] ? `#2.0.0-${argv['ng-sha']}` : ''; + + return Promise.all(Object.keys(packages).map(pkgName => { + return updateJsonFile(join(packages[pkgName].dist, 'package.json'), json => { + Object.keys(json['dependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['dependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); + + Object.keys(json['devDependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['devDependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); + }); + })); + }); } diff --git a/tests/e2e/setup/500-create-project.ts b/tests/e2e/setup/500-create-project.ts index 87e0555dcdb2..db7a6bd1bad1 100644 --- a/tests/e2e/setup/500-create-project.ts +++ b/tests/e2e/setup/500-create-project.ts @@ -38,22 +38,25 @@ export default function() { }); })) .then(() => { - if (argv.nightly) { + if (argv.nightly || argv['ng-sha']) { + const label = argv['ng-sha'] ? `#2.0.0-${argv['ng-sha']}` : ''; return updateJsonFile('package.json', json => { // Install over the project with nightly builds. - const angularPackages = [ - 'core', - 'common', - 'compiler', - 'forms', - 'http', - 'router', - 'platform-browser', - 'platform-browser-dynamic' - ]; - angularPackages.forEach(pkgName => { - json['dependencies'][`@angular/${pkgName}`] = `github:angular/${pkgName}-builds`; - }); + Object.keys(json['dependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['dependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); + + Object.keys(json['devDependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['devDependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); }); } }) diff --git a/tests/e2e/utils/project.ts b/tests/e2e/utils/project.ts index 45569278d1ad..5adb061ba38c 100644 --- a/tests/e2e/utils/project.ts +++ b/tests/e2e/utils/project.ts @@ -26,7 +26,7 @@ export function updateTsConfig(fn: (json: any) => any | void) { export function ngServe(...args: string[]) { return silentExecAndWaitForOutputToMatch('ng', - ['serve', ...args], /webpack: bundle is now VALID/); + ['serve', '--no-progress', ...args], /webpack: bundle is now VALID/); } @@ -42,22 +42,25 @@ export function createProject(name: string, ...args: string[]) { })) .then(() => { const argv: any = getGlobalVariable('argv'); - if (argv.nightly) { + if (argv.nightly || argv['ng-sha']) { + const label = argv['ng-sha'] ? `#2.0.0-${argv['ng-sha']}` : ''; return updateJsonFile('package.json', json => { // Install over the project with nightly builds. - const angularPackages = [ - 'core', - 'common', - 'compiler', - 'forms', - 'http', - 'router', - 'platform-browser', - 'platform-browser-dynamic' - ]; - angularPackages.forEach(pkgName => { - json['dependencies'][`@angular/${pkgName}`] = `github:angular/${pkgName}-builds`; - }); + Object.keys(json['dependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['dependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); + + Object.keys(json['devDependencies'] || {}) + .filter(name => name.match(/^@angular\//)) + .forEach(name => { + const pkgName = name.split(/\//)[1]; + json['devDependencies'][`@angular/${pkgName}`] + = `github:angular/${pkgName}-builds${label}`; + }); }); } }) diff --git a/tests/e2e_runner.js b/tests/e2e_runner.js index ba4d9882f656..5b869dd03517 100644 --- a/tests/e2e_runner.js +++ b/tests/e2e_runner.js @@ -26,6 +26,8 @@ const setGlobalVariable = require('./e2e/utils/env').setGlobalVariable; * --debug If a test fails, block the thread so the temporary directory isn't deleted. * --noproject Skip creating a project or using one. * --nolink Skip linking your local angular-cli directory. Can save a few seconds. + * --ng-sha=SHA Use a specific ng-sha. Similar to nightly but point to a master SHA instead + * of using the latest. * --nightly Install angular nightly builds over the test project. * --reuse=/path Use a path instead of create a new project. That project should have been * created, and npm installed. Ideally you want a project created by a previous @@ -34,7 +36,7 @@ const setGlobalVariable = require('./e2e/utils/env').setGlobalVariable; */ const argv = minimist(process.argv.slice(2), { 'boolean': ['debug', 'nolink', 'nightly', 'noproject'], - 'string': ['reuse'] + 'string': ['reuse', 'ng-sha'] });