build: remove "test.sh" script (#27937)
test.sh is no longer needed... all the tests should now be executed via bazel. if for whatever reason we need to run the legacy unit test setup, we should should follow the commands that we use to execute those tests in .circle/config.yaml PR Close #27937
This commit is contained in:
parent
0199e26167
commit
7ac8b02ec5
|
@ -5,55 +5,20 @@ The core packages are tested both in the browser (via Karma) and on the server (
|
|||
|
||||
## Debugging in Karma
|
||||
|
||||
Run the unit tests as normal using via the `./test.sh` script. For example:
|
||||
|
||||
```bash
|
||||
./test.sh browserNoRouter
|
||||
```
|
||||
|
||||
Once the initial build has completed and the Karma server has started up, you can go to the
|
||||
Chrome browser that is automatically opened, usually pointing to `http://localhost:9876`.
|
||||
The script will sit watching for code changes, recompiling the changed files and triggering
|
||||
further runs of the unit tests in the browser.
|
||||
|
||||
In this browser there is a "DEBUG" link (in the top right corner). Clicking this link will
|
||||
open up a new tab that will run the unit tests and will not timeout, giving you time to
|
||||
step through the code.
|
||||
|
||||
Open up this tab's developer console to access the source code viewer where you can set
|
||||
breakpoints and interrogate the current stack and variables.
|
||||
|
||||
It is useful to focus your debugging on one test at a time by changing that test to be
|
||||
defined using the `fit(...)` function, rather than `it(...)`. Moreover it can be helpful
|
||||
to place a `debugger` statement in this `fit` clause to cause the debugger to stop when
|
||||
it hits this test.
|
||||
|
||||
Read more about starting the debugger for Karma with Bazel in the [BAZEL.md](./BAZEL.md)
|
||||
document.
|
||||
|
||||
## Debugging in Node
|
||||
|
||||
Run the unit tests as normal using the `./test.sh` script, but add the `--debug` flag to
|
||||
the command. For example:
|
||||
|
||||
```bash
|
||||
./test.sh node --debug
|
||||
```
|
||||
|
||||
Once the initial building has completed, the script will watch for code changes, recompiling
|
||||
and running the unit tests via a tool call `cjs-jasmine`. Due to the `--debug` flag, each
|
||||
test run will create a debugging server listening on a port (such as 9229), which can be
|
||||
connected to by a debugger.
|
||||
|
||||
You can use Chrome as the debugger by navigating to `chrome://inspect` then clicking the
|
||||
"Open dedicated DevTools for Node" link. This will open up a Developer console, which will
|
||||
automatically connect to the debugging server.
|
||||
|
||||
It is useful to focus your debugging on one test at a time by changing that test to be
|
||||
defined using the `fit(...)` function, rather than `it(...)`. Moreover it can be helpful
|
||||
to place a `debugger` statement in this `fit` clause to cause the debugger to stop when
|
||||
it hits this test.
|
||||
|
||||
**Problem with node 6:** at the time of writing, the node process does not tell the Chrome
|
||||
debugger when it has completed, and so the debugger is not able to automatically disconnect
|
||||
from listening to the debugging server. To solve this, just close the developer tools window
|
||||
after each run of the unit tests, before making changes to the code. This is fixed in node 8
|
||||
and may be backported to node 6. This issue is tracked in
|
||||
https://github.com/nodejs/node/pull/12814#issuecomment-309908579.
|
||||
Read more about starting the debugger for NodeJS tests with Bazel in the [BAZEL.md](./BAZEL.md)
|
||||
document.
|
|
@ -82,33 +82,22 @@ Before submitting a PR, do not forget to remove them:
|
|||
To build Angular run:
|
||||
|
||||
```shell
|
||||
./build.sh
|
||||
./scripts/build-packages-dist.sh
|
||||
```
|
||||
|
||||
* Results are put in the dist folder.
|
||||
* Results are put in the `dist/packages-dist` folder.
|
||||
|
||||
## Running Tests Locally
|
||||
|
||||
To run tests:
|
||||
Bazel is used as the primary tool for building and testing Angular. Building and testing is
|
||||
incremental with Bazel, and it's possible to only run tests for an individual package instead
|
||||
of for all packages.
|
||||
|
||||
```shell
|
||||
$ ./test.sh node # Run all angular tests on node
|
||||
Read more about this in the [BAZEL.md](./BAZEL.md) document. You should execute all test suites
|
||||
before submitting a PR to Github.
|
||||
|
||||
$ ./test.sh browser # Run all angular tests in browser
|
||||
|
||||
$ ./test.sh browserNoRouter # Optionally run all angular tests without router in browser
|
||||
|
||||
$ ./test.sh router # Optionally run only the router tests in browser
|
||||
```
|
||||
|
||||
You should execute the 3 test suites before submitting a PR to github.
|
||||
|
||||
See [DEBUG.md](DEBUG.md) for information on debugging the code while running the unit tests.
|
||||
|
||||
All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass.
|
||||
|
||||
- CircleCI fails if your code is not formatted properly,
|
||||
- Travis CI fails if any of the test suites described above fails.
|
||||
All the tests are executed on our Continuous Integration infrastructure and a PR could only be
|
||||
merged if the code is formatted properly and all tests are passing.
|
||||
|
||||
## <a name="clang-format"></a> Formatting your source code
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig-build.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/tools/@angular/compiler-cli",
|
||||
"paths": {
|
||||
"@angular/compiler": ["../../dist/tools/@angular/compiler"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig-build.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"outDir": "../../dist/tools/@angular/compiler"
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@angular/*": ["./*"]
|
||||
}
|
||||
},
|
||||
|
||||
"exclude": [
|
||||
"bazel",
|
||||
"compiler/test",
|
||||
"compiler-cli/integrationtest",
|
||||
"platform-server/integrationtest",
|
||||
"router/test/aot_ngsummary_test",
|
||||
"common/locales",
|
||||
"examples",
|
||||
"**/*_spec.ts",
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
|
||||
"angularCompilerOptions": {
|
||||
"skipTemplateCodegen": true,
|
||||
"annotateForClosureCompiler": false,
|
||||
"annotationsAs": "decorators"
|
||||
}
|
||||
}
|
31
test.sh
31
test.sh
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "Angular test runner. (No platform specified)"
|
||||
echo
|
||||
echo "./test.sh [node|browser|browserNoRouter|router] [--debug]"
|
||||
echo "(--debug flag only relevant to 'node' testing - see https://github.com/angular/angular/blob/master/docs/DEBUG.md)"
|
||||
echo
|
||||
else
|
||||
cd `dirname $0`
|
||||
rm -rf dist/tools
|
||||
if [ -z ${NODE_PATH+x} ]; then
|
||||
export NODE_PATH=$(pwd)/dist/all:$(pwd)/dist/tools
|
||||
else
|
||||
export NODE_PATH=$NODE_PATH:$(pwd)/dist/all/:$(pwd)/dist/tools/
|
||||
fi
|
||||
echo "Compiling tools..."
|
||||
$(npm bin)/tsc -p tools
|
||||
if [[ $1 == 'node' ]]; then
|
||||
# Note: .metadata.json files are needed for the language service tests!
|
||||
echo "Building compiler..."
|
||||
$(npm bin)/tsc -p packages/compiler/tsconfig-tools.json
|
||||
$(npm bin)/tsc -p packages/compiler-cli/tsconfig-tools.json
|
||||
echo "Creating packages .metadata.json files..."
|
||||
node --max-old-space-size=3000 dist/tools/@angular/compiler-cli/src/main -p packages/tsconfig-metadata.json
|
||||
fi
|
||||
node --harmony dist/tools/tsc-watch/ $1 watch $2
|
||||
fi
|
|
@ -1,114 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. 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
|
||||
*/
|
||||
|
||||
/* tslint:disable:no-console */
|
||||
import {existsSync, mkdirSync} from 'fs';
|
||||
|
||||
import {TscWatch} from './tsc_watch';
|
||||
|
||||
export * from './tsc_watch';
|
||||
import 'reflect-metadata';
|
||||
|
||||
function md(dir: string, folders: string[]) {
|
||||
if (folders.length) {
|
||||
const next = folders.shift();
|
||||
const path = dir + '/' + next;
|
||||
if (!existsSync(path)) {
|
||||
mkdirSync(path);
|
||||
}
|
||||
md(path, folders);
|
||||
}
|
||||
}
|
||||
|
||||
let tscWatch: TscWatch = null;
|
||||
const platform = process.argv.length >= 3 ? process.argv[2] : null;
|
||||
const runMode: string = process.argv.length >= 4 ? process.argv[3] : null;
|
||||
const debugMode = process.argv.some(arg => arg === '--debug');
|
||||
const BaseConfig = {
|
||||
start: 'File change detected. Starting incremental compilation...',
|
||||
// This regex uses a negative lookbehind group (?<! 0 ), which causes it to not match a string
|
||||
// containing " 0 error" but to match anything else containing "error". It requires the --harmony
|
||||
// flag to run under node versions < 9.
|
||||
error: /(?<! 0 )error/,
|
||||
complete: 'Found 0 errors. Watching for file changes.',
|
||||
};
|
||||
|
||||
if (platform == 'node') {
|
||||
const specFiles = ['@angular/**/*_spec.js'];
|
||||
tscWatch = new TscWatch(Object.assign(
|
||||
{
|
||||
tsconfig: 'packages/tsconfig.json',
|
||||
onChangeCmds: [createNodeTestCommand(specFiles, debugMode)]
|
||||
},
|
||||
BaseConfig));
|
||||
} else if (platform == 'browser') {
|
||||
tscWatch = new TscWatch(Object.assign(
|
||||
{
|
||||
tsconfig: 'packages/tsconfig.json',
|
||||
onStartCmds: [
|
||||
[
|
||||
'node', 'node_modules/karma/bin/karma', 'start', '--no-auto-watch', '--port=9876',
|
||||
'karma-js.conf.js'
|
||||
],
|
||||
[
|
||||
'node', 'node_modules/karma/bin/karma', 'start', '--no-auto-watch', '--port=9877',
|
||||
'packages/router/karma.conf.js'
|
||||
],
|
||||
],
|
||||
onChangeCmds: [
|
||||
['node', 'node_modules/karma/bin/karma', 'run', 'karma-js.conf.js', '--port=9876'],
|
||||
['node', 'node_modules/karma/bin/karma', 'run', '--port=9877'],
|
||||
]
|
||||
},
|
||||
BaseConfig));
|
||||
} else if (platform == 'router') {
|
||||
tscWatch = new TscWatch(Object.assign(
|
||||
{
|
||||
tsconfig: 'packages/tsconfig.json',
|
||||
onStartCmds: [
|
||||
[
|
||||
'node', 'node_modules/karma/bin/karma', 'start', '--no-auto-watch', '--port=9877',
|
||||
'packages/router/karma.conf.js'
|
||||
],
|
||||
],
|
||||
onChangeCmds: [
|
||||
['node', 'node_modules/karma/bin/karma', 'run', '--port=9877'],
|
||||
]
|
||||
},
|
||||
BaseConfig));
|
||||
} else if (platform == 'browserNoRouter') {
|
||||
tscWatch = new TscWatch(Object.assign(
|
||||
{
|
||||
tsconfig: 'packages/tsconfig.json',
|
||||
onStartCmds: [[
|
||||
'node', 'node_modules/karma/bin/karma', 'start', '--no-auto-watch', '--port=9876',
|
||||
'karma-js.conf.js'
|
||||
]],
|
||||
onChangeCmds: [
|
||||
['node', 'node_modules/karma/bin/karma', 'run', 'karma-js.conf.js', '--port=9876'],
|
||||
]
|
||||
},
|
||||
BaseConfig));
|
||||
} else {
|
||||
throw new Error(`unknown platform: ${platform}`);
|
||||
}
|
||||
|
||||
if (runMode === 'watch') {
|
||||
tscWatch.watch();
|
||||
} else if (runMode === 'runCmdsOnly') {
|
||||
tscWatch.runCmdsOnly();
|
||||
} else {
|
||||
tscWatch.run();
|
||||
}
|
||||
|
||||
function createNodeTestCommand(specFiles: string[], debugMode: boolean) {
|
||||
return ['node']
|
||||
.concat(debugMode ? ['--inspect'] : [])
|
||||
.concat('dist/tools/cjs-jasmine', '--')
|
||||
.concat(specFiles);
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. 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
|
||||
*/
|
||||
|
||||
/* tslint:disable:no-console */
|
||||
import {spawn} from 'child_process';
|
||||
import {platform} from 'os';
|
||||
import {normalize} from 'path';
|
||||
|
||||
enum State {
|
||||
idle,
|
||||
waiting,
|
||||
error
|
||||
}
|
||||
|
||||
export const TSC = normalize('node_modules/.bin/tsc') + (/^win/.test(platform()) ? '.cmd' : '');
|
||||
export type Command = (stdIn: any, stdErr: any) => Promise<number>;
|
||||
|
||||
export class TscWatch {
|
||||
private tsconfig: string[];
|
||||
private start: string|RegExp;
|
||||
private error: string|RegExp;
|
||||
private complete: string|RegExp;
|
||||
private onStartCmds: Array<string[]|Command>;
|
||||
private onChangeCmds: Array<string[]|Command>;
|
||||
private state: State;
|
||||
private triggered: Promise<number> = null;
|
||||
private runOnce: boolean = false;
|
||||
|
||||
constructor({tsconfig, start, error, complete, onStartCmds = null, onChangeCmds = null}: {
|
||||
tsconfig: string | string[],
|
||||
error: string|RegExp,
|
||||
start: string,
|
||||
complete: string, onStartCmds?: Array<string[]|Command>, onChangeCmds?: Array<string[]|Command>
|
||||
}) {
|
||||
console.log('Watching:', tsconfig, 'in', process.cwd());
|
||||
this.tsconfig = Array.isArray(tsconfig) ? tsconfig : [tsconfig];
|
||||
this.start = start;
|
||||
this.error = error;
|
||||
this.complete = complete;
|
||||
this.onStartCmds = onStartCmds || [];
|
||||
this.onChangeCmds = onChangeCmds || [];
|
||||
}
|
||||
|
||||
watch() {
|
||||
const tsc =
|
||||
Promise
|
||||
.all(this.tsconfig.map(tsconfig => {
|
||||
const args = [TSC, '--emitDecoratorMetadata', '--project', tsconfig];
|
||||
if (!this.runOnce) args.push('--watch');
|
||||
return this.runCmd(
|
||||
args, {}, (d) => this.consumeLine(d, false), (d) => this.consumeLine(d, true));
|
||||
}))
|
||||
.then(
|
||||
exitCodes =>
|
||||
exitCodes.reduce((prevValue, currValue) => Math.max(prevValue, currValue), 0));
|
||||
if (this.runOnce) {
|
||||
tsc.then(() => this.triggerCmds(), code => process.exit(code));
|
||||
}
|
||||
this.state = State.waiting;
|
||||
this.onStartCmds.forEach((cmd) => this.runCmd(cmd, null, () => null, () => null));
|
||||
}
|
||||
|
||||
private runCmd(
|
||||
argsOrCmd: string[]|Command, env?: {[k: string]: string}, stdOut = pipeStdOut,
|
||||
stdErr = pipeStdErr): Promise<number> {
|
||||
if (typeof argsOrCmd == 'function') {
|
||||
return (argsOrCmd as Command)(stdErr, stdOut);
|
||||
} else if (argsOrCmd instanceof Array) {
|
||||
const args = argsOrCmd as Array<string>;
|
||||
return <any>new Promise((resolve, reject) => {
|
||||
const [cmd, ...options] = args;
|
||||
console.log('=====>', cmd, options.join(' '));
|
||||
const childProcess = spawn(cmd, options, {stdio: 'pipe'});
|
||||
childProcess.stdout.on('data', stdOut);
|
||||
childProcess.stderr.on('data', stdErr);
|
||||
const onExit = () => childProcess.kill();
|
||||
childProcess.on('close', (code: number) => {
|
||||
process.removeListener('exit', onExit);
|
||||
console.log('EXIT:', code, '<=====', args.join(' '));
|
||||
code ? reject(code) : resolve(code);
|
||||
});
|
||||
process.on('exit', onExit);
|
||||
})
|
||||
.catch(reportError);
|
||||
} else {
|
||||
throw new Error('Expecting function or an array of strings...');
|
||||
}
|
||||
}
|
||||
|
||||
run() {
|
||||
this.runOnce = true;
|
||||
this.watch();
|
||||
}
|
||||
|
||||
runCmdsOnly() {
|
||||
this.runOnce = true;
|
||||
this.triggerCmds();
|
||||
}
|
||||
|
||||
consumeLine(buffer: Buffer, isStdError: boolean) {
|
||||
const line = '' + buffer;
|
||||
if (contains(line, this.start)) {
|
||||
console.log('==============================================================================');
|
||||
stdOut(buffer, isStdError);
|
||||
this.state = State.waiting;
|
||||
} else if (contains(line, this.error)) {
|
||||
stdOut(buffer, isStdError);
|
||||
this.state = State.error;
|
||||
} else if (contains(line, this.complete)) {
|
||||
stdOut(buffer, isStdError);
|
||||
console.log('------------------------------------------------------------------------------');
|
||||
if (this.state == State.error) {
|
||||
console.log('Errors found.... (response not triggered)');
|
||||
if (this.runOnce) process.exit(1);
|
||||
this.state = State.idle;
|
||||
} else {
|
||||
if (this.triggered) {
|
||||
this.triggered.then(
|
||||
() => this.triggerCmds(), (e) => console.log('Error while running commands....', e));
|
||||
} else {
|
||||
this.triggerCmds();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stdOut(buffer, isStdError);
|
||||
}
|
||||
}
|
||||
|
||||
triggerCmds() {
|
||||
let cmdPromise: Promise<number> = Promise.resolve(0);
|
||||
this.onChangeCmds.forEach(
|
||||
(cmd: string[] | Command) => cmdPromise =
|
||||
cmdPromise.then(() => this.runCmd(<string[]>cmd)));
|
||||
cmdPromise.then(() => this.triggered = null, (code) => {
|
||||
if (this.runOnce) {
|
||||
if (typeof code != 'number') {
|
||||
console.error('Error occurred while executing commands', code);
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(code);
|
||||
} else {
|
||||
this.triggered = null;
|
||||
}
|
||||
});
|
||||
this.triggered = cmdPromise;
|
||||
}
|
||||
}
|
||||
|
||||
function stdOut(data: Buffer, isStdError: boolean) {
|
||||
if (isStdError) {
|
||||
process.stderr.write(data);
|
||||
} else {
|
||||
process.stdout.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
function contains(line: string, text: string | RegExp): boolean {
|
||||
if (typeof text == 'string') {
|
||||
return line.indexOf(text as string) != -1;
|
||||
} else if (text instanceof RegExp) {
|
||||
return (text as RegExp).test(line);
|
||||
} else {
|
||||
throw new Error('Unknown: ' + text);
|
||||
}
|
||||
}
|
||||
|
||||
export function reportError(e: any) {
|
||||
if (e.message && e.stack) {
|
||||
console.error(e.message);
|
||||
console.error(e.stack);
|
||||
} else {
|
||||
console.error(e);
|
||||
}
|
||||
// process.exit(1);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
|
||||
function pipeStdOut(d: any) {
|
||||
process.stdout.write(d);
|
||||
}
|
||||
function pipeStdErr(d: any) {
|
||||
process.stderr.write(d);
|
||||
}
|
Loading…
Reference in New Issue