Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(@angular/cli): improve update package discovery #18610

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -115,6 +115,7 @@
"@types/pidusage": "^2.0.1",
"@types/progress": "^2.0.3",
"@types/request": "^2.47.1",
"@types/resolve": "^1.17.1",
"@types/rimraf": "^3.0.0",
"@types/semver": "^7.0.0",
"@types/universal-analytics": "^0.4.2",
1 change: 1 addition & 0 deletions packages/angular/cli/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@ ts_library(
"@npm//@types/debug",
"@npm//@types/inquirer",
"@npm//@types/node",
"@npm//@types/resolve",
"@npm//@types/rimraf",
"@npm//@types/semver",
"@npm//@types/universal-analytics",
48 changes: 27 additions & 21 deletions packages/angular/cli/commands/update-impl.ts
Original file line number Diff line number Diff line change
@@ -27,7 +27,12 @@ import {
fetchPackageManifest,
fetchPackageMetadata,
} from '../utilities/package-metadata';
import { PackageTreeNode, findNodeDependencies, readPackageTree } from '../utilities/package-tree';
import {
PackageTreeNode,
findPackageJson,
getProjectDependencies,
readPackageJson,
} from '../utilities/package-tree';
import { Schema as UpdateCommandSchema } from './update';

const npa = require('npm-package-arg') as (selector: string) => PackageIdentifier;
@@ -377,15 +382,14 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {

this.logger.info('Collecting installed dependencies...');

const packageTree = await readPackageTree(this.workspace.root);
const rootDependencies = findNodeDependencies(packageTree);
const rootDependencies = await getProjectDependencies(this.workspace.root);

this.logger.info(`Found ${Object.keys(rootDependencies).length} dependencies.`);
this.logger.info(`Found ${rootDependencies.size} dependencies.`);

if (options.all) {
// 'all' option and a zero length packages have already been checked.
// Add all direct dependencies to be updated
for (const dep of Object.keys(rootDependencies)) {
for (const dep of rootDependencies.keys()) {
const packageIdentifier = npa(dep);
if (options.next) {
packageIdentifier.fetchSpec = 'next';
@@ -400,7 +404,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
next: options.next || false,
verbose: options.verbose || false,
packageManager: this.packageManager,
packages: options.all ? Object.keys(rootDependencies) : [],
packages: options.all ? rootDependencies.keys() : [],
});

return success ? 0 : 1;
@@ -424,8 +428,9 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
}

const packageName = packages[0].name;
const packageDependency = rootDependencies[packageName];
let packageNode = packageDependency && packageDependency.node;
const packageDependency = rootDependencies.get(packageName);
let packagePath = packageDependency?.path;
let packageNode = packageDependency?.package;
if (packageDependency && !packageNode) {
this.logger.error('Package found in package.json but is not installed.');

@@ -434,20 +439,21 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
// Allow running migrations on transitively installed dependencies
// There can technically be nested multiple versions
// TODO: If multiple, this should find all versions and ask which one to use
const child = packageTree.children.find(c => c.name === packageName);
if (child) {
packageNode = child;
const packageJson = findPackageJson(this.workspace.root, packageName);
if (packageJson) {
packagePath = path.dirname(packageJson);
packageNode = await readPackageJson(packagePath);
}
}

if (!packageNode) {
if (!packageNode || !packagePath) {
this.logger.error('Package is not installed.');

return 1;
}

const updateMetadata = packageNode.package['ng-update'];
let migrations = updateMetadata && updateMetadata.migrations;
const updateMetadata = packageNode['ng-update'];
let migrations = updateMetadata?.migrations;
if (migrations === undefined) {
this.logger.error('Package does not provide migrations.');

@@ -477,14 +483,14 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
}

// Check if it is a package-local location
const localMigrations = path.join(packageNode.path, migrations);
const localMigrations = path.join(packagePath, migrations);
if (fs.existsSync(localMigrations)) {
migrations = localMigrations;
} else {
// Try to resolve from package location.
// This avoids issues with package hoisting.
try {
migrations = require.resolve(migrations, { paths: [packageNode.path] });
migrations = require.resolve(migrations, { paths: [packagePath] });
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
this.logger.error('Migrations for package were not found.');
@@ -513,7 +519,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
}

const migrationRange = new semver.Range(
'>' + from + ' <=' + (options.to || packageNode.package.version),
'>' + from + ' <=' + (options.to || packageNode.version),
);

success = await this.executeMigrations(
@@ -529,7 +535,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
packageName === '@angular/core'
&& options.from
&& +options.from.split('.')[0] < 9
&& (options.to || packageNode.package.version).split('.')[0] === '9'
&& (options.to || packageNode.version).split('.')[0] === '9'
) {
this.logger.info(NG_VERSION_9_POST_MSG);
}
@@ -547,8 +553,8 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {

// Validate packages actually are part of the workspace
for (const pkg of packages) {
const node = rootDependencies[pkg.name] && rootDependencies[pkg.name].node;
if (!node) {
const node = rootDependencies.get(pkg.name);
if (!node?.package) {
this.logger.error(`Package '${pkg.name}' is not a dependency.`);

return 1;
@@ -627,7 +633,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
return 1;
}

if (manifest.version === node.package.version) {
if (manifest.version === node.package?.version) {
this.logger.info(`Package '${packageName}' is already up to date.`);
continue;
}
4 changes: 2 additions & 2 deletions packages/angular/cli/package.json
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@
"npm-pick-manifest": "6.1.0",
"open": "7.2.0",
"pacote": "9.5.12",
"read-package-tree": "5.3.1",
"resolve": "1.17.0",
"rimraf": "3.0.2",
"semver": "7.3.2",
"symbol-observable": "1.2.0",
@@ -50,7 +50,7 @@
"migrations": "@schematics/angular/migrations/migration-collection.json",
"packageGroup": {
"@angular/cli": "0.0.0",
"@angular-devkit/build-angular": "0.0.0",
"@angular-devkit/build-angular": "0.0.0",
"@angular-devkit/build-ng-packagr": "0.0.0",
"@angular-devkit/build-webpack": "0.0.0",
"@angular-devkit/core": "0.0.0",
136 changes: 71 additions & 65 deletions packages/angular/cli/utilities/package-tree.ts
Original file line number Diff line number Diff line change
@@ -6,88 +6,94 @@
* found in the LICENSE file at https://angular.io/license
*/


import * as fs from 'fs';
import { dirname, join } from 'path';
import * as resolve from 'resolve';
import { promisify } from 'util';
import { NgAddSaveDepedency } from './package-metadata';

export interface PackageTreeNodeBase {
const readFile = promisify(fs.readFile);

interface PackageJson {
name: string;
path: string;
realpath: string;
error?: Error;
id: number;
isLink: boolean;
package: {
name: string;
version: string;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
peerDependencies?: Record<string, string>;
optionalDependencies?: Record<string, string>;
'ng-update'?: {
migrations?: string;
};
'ng-add'?: {
save?: NgAddSaveDepedency;
};
version: string;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
peerDependencies?: Record<string, string>;
optionalDependencies?: Record<string, string>;
'ng-update'?: {
migrations?: string;
};
'ng-add'?: {
save?: NgAddSaveDepedency;
};
parent?: PackageTreeNode;
children: PackageTreeNode[];
}

export interface PackageTreeActual extends PackageTreeNodeBase {
isLink: false;
}
async function readJSON(file: string) {
const buffer = await readFile(file);

export interface PackageTreeLink extends PackageTreeNodeBase {
isLink: true;
target: PackageTreeActual;
return JSON.parse(buffer.toString());
}

export type PackageTreeNode = PackageTreeActual | PackageTreeLink;
function getAllDependencies(pkg: PackageJson) {
return new Set([
...Object.entries(pkg.dependencies || []),
...Object.entries(pkg.devDependencies || []),
...Object.entries(pkg.peerDependencies || []),
...Object.entries(pkg.optionalDependencies || []),
]);
}

export function readPackageTree(path: string): Promise<PackageTreeNode> {
const rpt = require('read-package-tree');
export interface PackageTreeNode {
name: string;
version: string;
path: string;
package: PackageJson | undefined;
}

return new Promise((resolve, reject) => {
rpt(path, (e: Error | undefined, data: PackageTreeNode) => {
if (e) {
reject(e);
} else {
resolve(data);
}
});
});
export async function readPackageJson(packageJsonPath: string): Promise<PackageJson | undefined> {
try {
return await readJSON(packageJsonPath);
} catch (err) {
return undefined;
}
}

export interface NodeDependency {
version: string;
node?: PackageTreeNode;
export function findPackageJson(workspaceDir: string, packageName: string) {
try {
// avoid require.resolve here, see: https://github.com/angular/angular-cli/pull/18610#issuecomment-681980185
const packageJsonPath = resolve.sync(`${packageName}/package.json`, { paths: [workspaceDir] });

return packageJsonPath;
} catch (err) {
return undefined;
}
}

export function findNodeDependencies(node: PackageTreeNode) {
const rawDeps: Record<string, string> = {
...node.package.dependencies,
...node.package.devDependencies,
...node.package.peerDependencies,
...node.package.optionalDependencies,
};
export async function getProjectDependencies(dir: string) {
const pkgJsonPath = resolve.sync(join(dir, `package.json`));
if (!pkgJsonPath) {
throw new Error('Could not find package.json');
}

return Object.entries(rawDeps).reduce(
(deps, [name, version]) => {
let dependencyNode;
let parent: PackageTreeNode | undefined | null = node;
while (!dependencyNode && parent) {
dependencyNode = parent.children.find(child => child.name === name);
parent = parent.parent;
}
const pkg: PackageJson = await readJSON(pkgJsonPath);

deps[name] = {
node: dependencyNode,
version,
};
const results = new Map<string, PackageTreeNode>();
await Promise.all(
Array.from(getAllDependencies(pkg)).map(async ([name, version]) => {
const packageJsonPath = findPackageJson(dir, name);
if (packageJsonPath) {
const currentDependency = {
name,
version,
path: dirname(packageJsonPath),
package: await readPackageJson(packageJsonPath),
};

return deps;
},
Object.create(null) as Record<string, NodeDependency>,
results.set(currentDependency.name, currentDependency);
}
}),
);

return results;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/codelyzer",
"**/codelyzer/**",
"**/@angular*",
"**/@angular*/**"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "one-oh-project"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"component": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
/dist
/tmp
/out-tsc

# dependencies
/node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings

# e2e
/e2e/*.js
/e2e/*.map

# System Files
.DS_Store
Thumbs.db
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# OneOhProject

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Before running the tests make sure you are serving the app via `ng serve`.

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { OneOhProjectPage } from './app.po';

describe('one-oh-project App', () => {
let page: OneOhProjectPage;

beforeEach(() => {
page = new OneOhProjectPage();
});

it('should display message saying app works', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('app works!');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { browser, element, by } from 'protractor';

export class OneOhProjectPage {
navigateTo() {
return browser.get('/');
}

getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types":[
"jasmine",
"node"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*eslint-disable*/
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
files: [
{ pattern: './src/test.ts', watched: false }
],
preprocessors: {
'./src/test.ts': ['@angular/cli']
},
mime: {
'text/x-typescript': ['ts','tsx']
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['progress', 'coverage-istanbul']
: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "one-oh-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^5.2.0",
"@angular/common": "^5.2.0",
"@angular/compiler": "^5.2.0",
"@angular/core": "^5.2.0",
"@angular/forms": "^5.2.0",
"@angular/http": "^5.2.0",
"@angular/platform-browser": "^5.2.0",
"@angular/platform-browser-dynamic": "^5.2.0",
"@angular/router": "^5.2.0",
"core-js": "^2.4.1",
"rxjs": "^5.5.6",
"zone.js": "^0.8.19"
},
"devDependencies": {
"@angular/cli": "0.0.0",
"@angular/compiler-cli": "^5.2.0",
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.5.2",
"jasmine-spec-reporter": "~3.2.0",
"karma": "~1.4.1",
"karma-chrome-launcher": "~2.0.0",
"karma-cli": "~1.0.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-coverage-istanbul-reporter": "^0.2.0",
"protractor": "~5.1.0",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "~2.4.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*eslint-disable*/
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');

exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
},
onPrepare() {
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>
{{title}}
</h1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { TestBed } from '@angular/core/testing';

import { AppComponent } from './app.component';

describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
});

it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});

it(`should have as title 'app works!'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
});

it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app works!';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const environment = {
production: true
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.

export const environment = {
production: false
};
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>OneOhProject</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/

/***************************************************************************************************
* BROWSER POLYFILLS
*/

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.

/** IE10 and IE11 requires the following to support `@angular/animation`. */
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.


/** Evergreen browsers require these. **/
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';


/** ALL Firefox browsers require the following to support `@angular/animation`. **/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.



/***************************************************************************************************
* Zone JS is required by Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.



/***************************************************************************************************
* APPLICATION IMPORTS
*/

/**
* Date, currency, decimal and percent pipes.
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
*/
// import 'intl'; // Run `npm install --save intl`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files

import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';

// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare var __karma__: any;
declare var require: any;

// Prevent Karma from running prematurely.
__karma__.loaded = function () {};

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
// Finally, start Karma to run the tests.
__karma__.start();
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"baseUrl": "",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"module": "commonjs",
"target": "es5",
"baseUrl": "",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
id: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2016",
"dom"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"eofline": true,
"forin": true,
"import-blacklist": [true, "rxjs"],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
"static-before-instance",
"variables-before-functions"
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [true, "ignore-params"],
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"typeof-compare": true,
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],

"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "kebab-case"],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"no-access-missing-member": true,
"templates-use-public": true,
"invoke-injectable": true
}
}
34 changes: 34 additions & 0 deletions tests/legacy-cli/e2e/tests/update/update-1.0-yarn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createProjectFromAsset } from '../../utils/assets';
import { ng, silentYarn } from '../../utils/process';
import { isPrereleaseCli, useBuiltPackages, useCIChrome, useCIDefaults } from '../../utils/project';
import { expectToFail } from '../../utils/utils';

export default async function() {
const extraUpdateArgs = (await isPrereleaseCli()) ? ['--next', '--force'] : [];

const dir = await createProjectFromAsset('1.0-yarn-workspace-project', false, true);
process.chdir(`${dir}/packages/app`);
await useBuiltPackages();

process.chdir(dir);
await silentYarn('install');
process.chdir(`${dir}/packages/app`);

await useCIChrome('.');
await expectToFail(() => ng('build'));
await ng('update', '@angular/cli');
await useBuiltPackages();

process.chdir(dir);
await silentYarn('install');
process.chdir(`${dir}/packages/app`);

await ng('update', '@angular/core', ...extraUpdateArgs);
await useCIDefaults('one-oh-project');
await ng('generate', 'component', 'my-comp');
await ng('test', '--watch=false');
await ng('lint');
await ng('build');
await ng('build', '--prod');
await ng('e2e');
}
27 changes: 17 additions & 10 deletions tests/legacy-cli/e2e/utils/assets.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import {join} from 'path';
import { join } from 'path';
import * as glob from 'glob';
import {getGlobalVariable} from './env';
import {relative} from 'path';
import {copyFile, writeFile} from './fs';
import {useBuiltPackages} from './project';
import { git, silentNpm } from './process';

import { getGlobalVariable } from './env';
import { relative } from 'path';
import { copyFile, writeFile } from './fs';
import { useBuiltPackages } from './project';
import { silentNpm } from './process';

export function assetDir(assetName: string) {
return join(__dirname, '../assets', assetName);
@@ -38,13 +37,21 @@ export function copyAssets(assetName: string) {
.then(() => tempRoot);
}


export async function createProjectFromAsset(assetName: string, useNpmPackages = false) {
export async function createProjectFromAsset(
assetName: string,
useNpmPackages = false,
skipInstall = false,
) {
const dir = await copyAssets(assetName);
process.chdir(dir);
if (!useNpmPackages) {
await useBuiltPackages();
await writeFile('.npmrc', 'registry = http://localhost:4873', 'utf8');
}
await silentNpm('install');

if (!skipInstall) {
await silentNpm('install');
}

return dir;
}
4 changes: 4 additions & 0 deletions tests/legacy-cli/e2e/utils/process.ts
Original file line number Diff line number Diff line change
@@ -209,6 +209,10 @@ export function silentNpm(...args: string[]) {
return _exec({silent: true}, 'npm', args);
}

export function silentYarn(...args: string[]) {
return _exec({silent: true}, 'yarn', args);
}

export function npm(...args: string[]) {
return _exec({}, 'npm', args);
}
22 changes: 3 additions & 19 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -1660,7 +1660,7 @@
"@types/tough-cookie" "*"
form-data "^2.5.0"

"@types/resolve@1.17.1":
"@types/resolve@1.17.1", "@types/resolve@^1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
@@ -8692,7 +8692,7 @@ object.assign@^4.1.0:
has-symbols "^1.0.0"
object-keys "^1.0.11"

object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0:
object.getownpropertydescriptors@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649"
integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==
@@ -10112,15 +10112,6 @@ read-package-json@^2.0.0:
normalize-package-data "^2.0.0"
npm-normalize-package-bin "^1.0.0"

read-package-tree@5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636"
integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==
dependencies:
read-package-json "^2.0.0"
readdir-scoped-modules "^1.0.0"
util-promisify "^2.1.0"

read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -10510,7 +10501,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=

resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1:
resolve@1.17.0, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1:
version "1.17.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
@@ -12487,13 +12478,6 @@ util-extend@^1.0.1:
resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=

util-promisify@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53"
integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=
dependencies:
object.getownpropertydescriptors "^2.0.3"

util.promisify@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee"