From d45451b8bb70216baaebf0de049668c993a74d5a Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Tue, 8 Dec 2015 16:26:28 -0800 Subject: [PATCH 01/45] docs(contributing.md): add docs for "build" commit type Our build system is pretty complicated and we have many commits that touch it. For this reason these kids of changes warrant its own type. --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99ebe7ed45475..e22ad4831f336 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -175,9 +175,9 @@ Must be one of the following: semi-colons, etc) * **refactor**: A code change that neither fixes a bug nor adds a feature * **perf**: A code change that improves performance -* **test**: Adding missing tests -* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation - generation +* **test**: Adding missing tests or correcting existing tests +* **build** Changes that affect the build system, CI configuration or external dependencies (example scopes: gulp, broccoli, npm) +* **chore**: Other changes that don't modify `src` or `test` files ### Scope The scope could be anything specifying place of the commit change. For example From ad1cd79faecf8abbffa270beba522b1cfe06603a Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Mon, 14 Dec 2015 16:19:22 -0800 Subject: [PATCH 02/45] docs(contributing.md): improve submit issue instructions --- CONTRIBUTING.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e22ad4831f336..b8da1f04776b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,14 +48,18 @@ features, by not reporting duplicate issues. Providing the following informatio chances of your issue being dealt with quickly: * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps -* **Motivation for or Use Case** - explain why this is a bug for you +* **Angular Version** - what version of Angular is affected (e.g. 2.0.0-alpha.53) +* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you * **Browsers and Operating System** - is this a problem with all browsers? * **Reproduce the Error** - provide a live example (using [Plunker][plunker], - [JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps. + [JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps * **Related Issues** - has a similar issue been reported before? * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit) +You can file new issues by providing the above information [here](https://github.com/angular/angular/issues/new). + + ### Submitting a Pull Request (PR) Before you submit your Pull Request (PR) consider the following guidelines: From 9d28147acb4052c30cb11de08fd8b41ceb05f89d Mon Sep 17 00:00:00 2001 From: Hank Duan Date: Mon, 28 Dec 2015 17:47:49 -0800 Subject: [PATCH 03/45] fix(benchpress): fix flake memory was not allocated to be high enough, resulting in partial results to be clipped, and therefore failing the assertions Closes #6161 --- modules/benchpress/src/firefox_extension/lib/main.ts | 2 +- modules/benchpress/test/firefox_extension/spec.ts | 1 + scripts/ci/test_e2e_js.sh | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/benchpress/src/firefox_extension/lib/main.ts b/modules/benchpress/src/firefox_extension/lib/main.ts index f6214ea001f9f..b56dde8f238b4 100644 --- a/modules/benchpress/src/firefox_extension/lib/main.ts +++ b/modules/benchpress/src/firefox_extension/lib/main.ts @@ -54,7 +54,7 @@ mod.PageMod({ contentScriptFile: data.url('installed_script.js'), onAttach: worker => { worker.port.on('startProfiler', - (timeStarted) => profiler.start(/* = profiler memory */ 1000000, 0.1, + (timeStarted) => profiler.start(/* = profiler memory */ 3000000, 0.1, ['leaf', 'js', 'stackwalk', 'gc'], timeStarted)); worker.port.on('stopProfiler', () => profiler.stop()); worker.port.on('getProfile', diff --git a/modules/benchpress/test/firefox_extension/spec.ts b/modules/benchpress/test/firefox_extension/spec.ts index 454f7c1cb558f..9b9cf24bc2177 100644 --- a/modules/benchpress/test/firefox_extension/spec.ts +++ b/modules/benchpress/test/firefox_extension/spec.ts @@ -24,6 +24,7 @@ describe('firefox extension', function() { browser.executeScript('window.startProfiler()') .then(function() { console.log('started measuring perf'); }); + browser.executeAsyncScript('setTimeout(arguments[0], 1000);'); browser.executeScript('window.forceGC()'); browser.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);') diff --git a/scripts/ci/test_e2e_js.sh b/scripts/ci/test_e2e_js.sh index 6a4047076be8e..449a8a423f63c 100755 --- a/scripts/ci/test_e2e_js.sh +++ b/scripts/ci/test_e2e_js.sh @@ -30,8 +30,5 @@ fi ./node_modules/.bin/protractor protractor-js.conf.js $OPTIONS ./node_modules/.bin/protractor protractor-js.conf.js $OPTIONS --benchmark --dryrun -# TODO(tbosch): tests for benchpress on firefox are disabled -# as they are very flake. Enable once https://github.com/angular/angular/issues/5611 -# is resolved. -# ./node_modules/.bin/protractor dist/js/cjs/benchpress/test/firefox_extension/conf.js +./node_modules/.bin/protractor dist/js/cjs/benchpress/test/firefox_extension/conf.js From a038bb9ae3a3464ba1f46c1adaabdcdc774577a0 Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Tue, 15 Dec 2015 15:58:04 -0800 Subject: [PATCH 04/45] fix(router): preserve specificity for redirects Previously when comparing which of multiple possible routes to choose in an ambiguous case, we looked at the specificity of the target of redirect matches rather than the original match. This meant that if a redirect used a whilecard, but redirected to a target that was a static path, we'd cound the static path's specificity instead of the wildcard. This change stores the specificity of the redirect on the RedirectInstruction. Closes #5933 --- modules/angular2/src/router/instruction.ts | 4 +++- modules/angular2/src/router/route_registry.ts | 2 +- .../integration/impl/fixture_components.ts | 6 ++++++ .../router/integration/redirect_route_spec.ts | 21 ++++++++++++++++++- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/modules/angular2/src/router/instruction.ts b/modules/angular2/src/router/instruction.ts index 815745bd920d6..817e91a56da09 100644 --- a/modules/angular2/src/router/instruction.ts +++ b/modules/angular2/src/router/instruction.ts @@ -281,9 +281,11 @@ export class UnresolvedInstruction extends Instruction { export class RedirectInstruction extends ResolvedInstruction { constructor(component: ComponentInstruction, child: Instruction, - auxInstruction: {[key: string]: Instruction}) { + auxInstruction: {[key: string]: Instruction}, private _specificity: string) { super(component, child, auxInstruction); } + + get specificity(): string { return this._specificity; } } diff --git a/modules/angular2/src/router/route_registry.ts b/modules/angular2/src/router/route_registry.ts index dbf757f4a7794..5750396c29ed2 100644 --- a/modules/angular2/src/router/route_registry.ts +++ b/modules/angular2/src/router/route_registry.ts @@ -205,7 +205,7 @@ export class RouteRegistry { var instruction = this.generate(candidate.redirectTo, ancestorInstructions.concat([null])); return new RedirectInstruction(instruction.component, instruction.child, - instruction.auxInstruction); + instruction.auxInstruction, candidate.specificity); } })); diff --git a/modules/angular2/test/router/integration/impl/fixture_components.ts b/modules/angular2/test/router/integration/impl/fixture_components.ts index 075213bdf67b8..5777bf163bda1 100644 --- a/modules/angular2/test/router/integration/impl/fixture_components.ts +++ b/modules/angular2/test/router/integration/impl/fixture_components.ts @@ -10,6 +10,12 @@ import { } from 'angular2/router'; import {PromiseWrapper} from 'angular2/src/facade/async'; +@Component({selector: 'goodbye-cmp', template: `{{farewell}}`}) +export class GoodbyeCmp { + farewell: string; + constructor() { this.farewell = 'goodbye'; } +} + @Component({selector: 'hello-cmp', template: `{{greeting}}`}) export class HelloCmp { greeting: string; diff --git a/modules/angular2/test/router/integration/redirect_route_spec.ts b/modules/angular2/test/router/integration/redirect_route_spec.ts index 4c2f195b3dc46..963fc78e3067c 100644 --- a/modules/angular2/test/router/integration/redirect_route_spec.ts +++ b/modules/angular2/test/router/integration/redirect_route_spec.ts @@ -25,7 +25,7 @@ import { } from 'angular2/src/router/route_config_decorator'; import {TEST_ROUTER_PROVIDERS, RootCmp, compile} from './util'; -import {HelloCmp, RedirectToParentCmp} from './impl/fixture_components'; +import {HelloCmp, GoodbyeCmp, RedirectToParentCmp} from './impl/fixture_components'; var cmpInstanceCount; var childCmpInstanceCount; @@ -117,5 +117,24 @@ export function main() { async.done(); }); })); + + + it('should not redirect when redirect is less specific than other matching routes', + inject([AsyncTestCompleter, Location], (async, location) => { + compile(tcb) + .then((rtc) => {rootTC = rtc}) + .then((_) => rtr.config([ + new Route({path: '/foo', component: HelloCmp, name: 'Hello'}), + new Route({path: '/:param', component: GoodbyeCmp, name: 'Goodbye'}), + new Redirect({path: '/*rest', redirectTo: ['/Hello']}) + ])) + .then((_) => rtr.navigateByUrl('/bye')) + .then((_) => { + rootTC.detectChanges(); + expect(rootTC.debugElement.nativeElement).toHaveText('goodbye'); + expect(location.urlChanges).toEqual(['/bye']); + async.done(); + }); + })); }); } From b44d36cf955acd81a3e7285ab0e1acbffe8c8dcc Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 16 Dec 2015 15:30:29 -0800 Subject: [PATCH 05/45] fix(forms): fix SelectControlValueAccessor not to call onChange twice Closes #5969 --- .../forms/directives/select_control_value_accessor.ts | 6 +----- modules/angular2/test/common/forms/integration_spec.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts index 230631ddfd7e8..2fe527af139e3 100644 --- a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts +++ b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts @@ -36,11 +36,7 @@ export class NgSelectOption { */ @Directive({ selector: 'select[ngControl],select[ngFormControl],select[ngModel]', - host: { - '(change)': 'onChange($event.target.value)', - '(input)': 'onChange($event.target.value)', - '(blur)': 'onTouched()' - }, + host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'}, bindings: [SELECT_VALUE_ACCESSOR] }) export class SelectControlValueAccessor implements ControlValueAccessor { diff --git a/modules/angular2/test/common/forms/integration_spec.ts b/modules/angular2/test/common/forms/integration_spec.ts index 763532012f7c0..a2d66e5a08ff8 100644 --- a/modules/angular2/test/common/forms/integration_spec.ts +++ b/modules/angular2/test/common/forms/integration_spec.ts @@ -348,7 +348,7 @@ export function main() { expect(sfOption.nativeElement.selected).toBe(true); select.nativeElement.value = 'NYC'; - dispatchEvent(select.nativeElement, "change"); + dispatchEvent(select.nativeElement, "input"); expect(fixture.debugElement.componentInstance.form.value).toEqual({"city": 'NYC'}); expect(sfOption.nativeElement.selected).toBe(false); From 4291758079ca6b312ec8f5b274ead5a8c2f79494 Mon Sep 17 00:00:00 2001 From: mlaval Date: Thu, 10 Dec 2015 14:40:00 +0100 Subject: [PATCH 06/45] build(sauce/bs): make some browsers required in CI Closes #5795 --- .travis.yml | 10 +++--- browser-providers.conf.js | 62 ++++++++++++++++++++++++++------- gulpfile.js | 13 +++++-- karma-js.conf.js | 4 +-- scripts/ci/build_and_test.sh | 6 ++-- scripts/ci/test_browserstack.sh | 4 ++- scripts/ci/test_saucelabs.sh | 4 ++- 7 files changed, 78 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 80d9d7540a513..ec2f2e19121d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,8 +37,10 @@ env: # Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete. - MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION - MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - - MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - - MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION + - MODE=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION + - MODE=browserstack_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION + - MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION + - MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION @@ -48,8 +50,8 @@ env: matrix: allow_failures: - - env: "MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" - - env: "MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" + - env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" + - env: "MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" - env: "MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" # TODO(alxhub): remove when dartdoc #1039 is in dev channel - env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" diff --git a/browser-providers.conf.js b/browser-providers.conf.js index 5fb1028370fd4..37877ce5403fd 100644 --- a/browser-providers.conf.js +++ b/browser-providers.conf.js @@ -1,3 +1,32 @@ +// Unique place to configure the browsers which are used in the different CI jobs in Sauce Labs (SL) and BrowserStack (BS). +// If the target is set to null, then the browser is not run anywhere during CI. +// If a category becomes empty (e.g. BS and required), then the corresponding job must be commented out in Travis configuration. +var CIconfiguration = { + 'Chrome': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'Firefox': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'ChromeBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'FirefoxBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'ChromeDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}}, + 'FirefoxDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}}, + 'IE9': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'IE10': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'IE11': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'Edge': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + 'Android4.1': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'Android4.2': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'Android4.3': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'Android4.4': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'Android5': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, + 'Safari7': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}, + 'Safari8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}, + 'Safari9': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}, + 'iOS7': { unitTest: {target: 'BS', required: true}, e2e: {target: null, required: true}}, + 'iOS8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}, + // TODO(mlaval): iOS9 deactivated as not reliable, reactivate after https://github.com/angular/angular/issues/5408 + 'iOS9': { unitTest: {target: null, required: false}, e2e: {target: null, required: true}}, + 'WindowsPhone': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}} +}; + var customLaunchers = { 'DartiumWithWebPlatform': { base: 'Dartium', @@ -47,7 +76,7 @@ var customLaunchers = { platform: 'OS X 10.10', version: '8' }, - 'SL_SAFARI9.0': { + 'SL_SAFARI9': { base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', @@ -119,7 +148,7 @@ var customLaunchers = { platform: 'Linux', version: '4.4' }, - 'SL_ANDROID5.1': { + 'SL_ANDROID5': { base: 'SauceLabs', browserName: 'android', platform: 'Linux', @@ -239,21 +268,18 @@ var customLaunchers = { } }; -// iOS9 deactivated as not reliable in both providers -// TODO(mlaval): reactivate after https://github.com/angular/angular/issues/5408 - var sauceAliases = { 'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'SauceLabs';}), - 'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9.0'], - 'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'], - 'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1'], + 'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'], + 'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'], + 'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5'], 'IE': ['SL_IE9', 'SL_IE10', 'SL_IE11'], 'IOS': ['SL_IOS7', 'SL_IOS8', 'SL_IOS9'], - 'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9.0'], + 'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'], 'BETA': ['SL_CHROMEBETA', 'SL_FIREFOXBETA'], 'DEV': ['SL_CHROMEDEV', 'SL_FIREFOXDEV'], - 'CI': ['SL_CHROME',' SL_FIREFOX', 'SL_CHROMEDEV', 'SL_FIREFOXBETA', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', - 'SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1'] + 'CI_REQUIRED': buildConfiguration('unitTest', 'SL', true), + 'CI_OPTIONAL': buildConfiguration('unitTest', 'SL', false) }; var browserstackAliases = { @@ -264,7 +290,8 @@ var browserstackAliases = { 'IE': ['BS_IE9', 'BS_IE10', 'BS_IE11'], 'IOS': ['BS_IOS7', 'BS_IOS8', 'BS_IOS9'], 'SAFARI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9'], - 'CI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9', 'BS_IOS7', 'BS_IOS8', 'BS_WINDOWSPHONE'] + 'CI_REQUIRED': buildConfiguration('unitTest', 'BS', true), + 'CI_OPTIONAL': buildConfiguration('unitTest', 'BS', false) }; module.exports = { @@ -277,3 +304,14 @@ if (process.env.TRAVIS) { process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); process.env.BROWSER_STACK_ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY.split('').reverse().join(''); } + +function buildConfiguration(type, target, required) { + return Object.keys(CIconfiguration) + .filter((item) => { + var conf = CIconfiguration[item][type]; + return conf.required === required && conf.target === target; + }) + .map((item) => { + return target + '_' + item.toUpperCase(); + }); +} diff --git a/gulpfile.js b/gulpfile.js index fc8f207995f2f..6d2b0aaa0b6de 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -720,12 +720,19 @@ gulp.task('test.unit.js/ci', function(done) { }); gulp.task('test.unit.js.sauce/ci', function(done) { - launchKarmaWithExternalBrowsers(['dots', 'saucelabs'], browserProvidersConf.sauceAliases.CI, - done); + var browsers = browserProvidersConf.sauceAliases.CI_REQUIRED; + if (cliArgs.mode && cliArgs.mode == 'saucelabs_optional') { + browsers = browserProvidersConf.sauceAliases.CI_OPTIONAL; + } + launchKarmaWithExternalBrowsers(['dots', 'saucelabs'], browsers, done); }); gulp.task('test.unit.js.browserstack/ci', function(done) { - launchKarmaWithExternalBrowsers(['dots'], browserProvidersConf.browserstackAliases.CI, done); + var browsers = browserProvidersConf.browserstackAliases.CI_REQUIRED; + if (cliArgs.mode && cliArgs.mode == 'browserstack_optional') { + browsers = browserProvidersConf.browserstackAliases.CI_OPTIONAL; + } + launchKarmaWithExternalBrowsers(['dots'], browsers, done); }); gulp.task('test.unit.dart/ci', function(done) { diff --git a/karma-js.conf.js b/karma-js.conf.js index b407d1c120655..f2b1375d1b5df 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -79,7 +79,7 @@ module.exports = function(config) { if (process.env.TRAVIS) { var buildId = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; - if (process.env.MODE === 'saucelabs') { + if (process.env.MODE.startsWith('saucelabs')) { config.sauceLabs.build = buildId; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; @@ -89,7 +89,7 @@ module.exports = function(config) { config.transports = ['polling']; } - if (process.env.MODE === 'browserstack') { + if (process.env.MODE.startsWith('browserstack')) { config.browserStack.build = buildId; config.browserStack.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; } diff --git a/scripts/ci/build_and_test.sh b/scripts/ci/build_and_test.sh index 0d4c9ce449fe5..02ab2c8844c04 100755 --- a/scripts/ci/build_and_test.sh +++ b/scripts/ci/build_and_test.sh @@ -10,8 +10,10 @@ cd $SCRIPT_DIR/../.. if [ "$MODE" = "dart_experimental" ]; then ${SCRIPT_DIR}/build_$MODE.sh -elif [ "$MODE" = "saucelabs" ] || [ "$MODE" = "browserstack" ] ; then - ${SCRIPT_DIR}/test_$MODE.sh +elif [[ $MODE = saucelabs* ]] ; then + ${SCRIPT_DIR}/test_saucelabs.sh $MODE +elif [[ $MODE = browserstack* ]] ; then + ${SCRIPT_DIR}/test_browserstack.sh $MODE elif [ "$MODE" = "lint" ]; then ./node_modules/.bin/gulp static-checks elif [ "$MODE" = "build_only" ]; then diff --git a/scripts/ci/test_browserstack.sh b/scripts/ci/test_browserstack.sh index 9f6c3a834b41d..fe918f84dcf54 100755 --- a/scripts/ci/test_browserstack.sh +++ b/scripts/ci/test_browserstack.sh @@ -1,6 +1,8 @@ #!/bin/bash set -e +MODE=$1 + echo ============================================================================= # go to project dir SCRIPT_DIR=$(dirname $0) @@ -9,4 +11,4 @@ cd $SCRIPT_DIR/../.. ./scripts/browserstack/start_tunnel.sh ./scripts/browserstack/waitfor_tunnel.sh ./node_modules/.bin/gulp build.js.dev -./node_modules/.bin/gulp test.unit.js.browserstack/ci +./node_modules/.bin/gulp test.unit.js.browserstack/ci --mode=$MODE diff --git a/scripts/ci/test_saucelabs.sh b/scripts/ci/test_saucelabs.sh index e57c378209c80..8cb59495a990a 100755 --- a/scripts/ci/test_saucelabs.sh +++ b/scripts/ci/test_saucelabs.sh @@ -1,6 +1,8 @@ #!/bin/bash set -e +MODE=$1 + echo ============================================================================= # go to project dir SCRIPT_DIR=$(dirname $0) @@ -9,4 +11,4 @@ cd $SCRIPT_DIR/../.. ./scripts/sauce/sauce_connect_setup.sh ./scripts/sauce/sauce_connect_block.sh ./node_modules/.bin/gulp build.js.dev -./node_modules/.bin/gulp test.unit.js.sauce/ci \ No newline at end of file +./node_modules/.bin/gulp test.unit.js.sauce/ci --mode=$MODE From 0b6e75a85eb9b6c14eb0399dd19994d9088827c0 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sun, 3 Jan 2016 09:18:33 -0800 Subject: [PATCH 07/45] chore(ci): cleanup artifact upload This is no longer needed for g3sync. Closes #6232 --- .travis.yml | 21 --------------------- scripts/ci/build_and_test.sh | 1 - 2 files changed, 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index ec2f2e19121d0..4199ab17b6e4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -111,24 +111,3 @@ notifications: slack: secure: EP4MzZ8JMyNQJ4S3cd5LEPWSMjC7ZRdzt3veelDiOeorJ6GwZfCDHncR+4BahDzQAuqyE/yNpZqaLbwRWloDi15qIUsm09vgl/1IyNky1Sqc6lEknhzIXpWSalo4/T9ZP8w870EoDvM/UO+LCV99R3wS8Nm9o99eLoWVb2HIUu0= -deploy: - - provider: gcs - # This is for project angular-github-babysitter - access_key_id: GOOGIOQTDBEOPBUAWFZQ - secret_access_key: - secure: "MEDggllZ5fw4wI9CEUi8WR6jKsKXqdRF/DLxSNC2JpzM5RlVeBm0uqjntYT1Cf1dASvQ2/+vZCUikL/3A48NcoEYRHXGmxu8D6t/SvleQD8Xv434xFOdsa2QqP/HiCtqCLOI5jJz1JVoB5nNyKKZ33ogTUL1LV1TfcrAioyizW8=" - # this bucket has a lifecycle to delete after 90 days: - # $ echo '{"rule": [{"action": {"type": "Delete"}, "condition": {"age": 90}}]}' > lifecycle.json - # $ gsutil lifecycle set lifecycle.json gs://angular2-snapshots - bucket: angular2-snapshots - # don't delete generated files - skip_cleanup: true - # serve to public at https://storage.googleapis.com/angular2-snapshots/SHA/dist.tgz - acl: public-read - # upload the .tgz archive created in scripts/ci/build_and_test.sh - local-dir: deploy - # create a "subdirectory" for each commit - upload-dir: $TRAVIS_COMMIT - on: - repo: angular/angular - condition: "$MODE = build_only" diff --git a/scripts/ci/build_and_test.sh b/scripts/ci/build_and_test.sh index 02ab2c8844c04..35ffaf6483330 100755 --- a/scripts/ci/build_and_test.sh +++ b/scripts/ci/build_and_test.sh @@ -19,7 +19,6 @@ elif [ "$MODE" = "lint" ]; then elif [ "$MODE" = "build_only" ]; then ${SCRIPT_DIR}/build_js.sh ${SCRIPT_DIR}/build_dart.sh - mkdir deploy; tar -czpf deploy/dist.tgz -C dist . elif [ "$MODE" = "payload" ]; then source ${SCRIPT_DIR}/env_dart.sh ./node_modules/.bin/gulp test.payload.dart/ci From a08f50badd4397e897192e08909838dd6725fe32 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Tue, 29 Dec 2015 17:01:10 -0800 Subject: [PATCH 08/45] chore(build): allow to run examples and benchmarks without bundles The bundles will only be used if the flag `--useBundles` is passed to `gulp build.js`. --- gulpfile.js | 31 ++++++----- scripts/ci/build_js.sh | 2 +- tools/broccoli/angular_builder.ts | 7 ++- tools/broccoli/html-replace/SCRIPTS.html | 54 +++++++++++++------ .../html-replace/SCRIPTS_benchmarks.html | 52 +++++++++++++----- tools/broccoli/trees/browser_tree.ts | 15 ++++-- 6 files changed, 113 insertions(+), 48 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 6d2b0aaa0b6de..1415c67128df0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -369,7 +369,7 @@ function proxyServeDart() { // ------------------ // web servers -gulp.task('serve.js.dev', ['build.js'], function(neverDone) { +gulp.task('serve.js.dev', ['build.js.dev'], function(neverDone) { var watch = require('./tools/build/watch'); watch('modules/**', {ignoreInitial: true}, '!broccoli.js.dev'); @@ -980,15 +980,19 @@ gulp.task('!build.tools', function() { gulp.task('broccoli.js.dev', ['build.tools'], function(done) { runSequence('!broccoli.js.dev', sequenceComplete(done)); }); -gulp.task( - '!broccoli.js.dev', - () => angularBuilder.rebuildBrowserDevTree( - {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks})); +gulp.task('!broccoli.js.dev', () => angularBuilder.rebuildBrowserDevTree({ + generateEs6: generateEs6, + projects: cliArgsProjects, + noTypeChecks: cliArgs.noTypeChecks, + useBundles: cliArgs.useBundles +})); -gulp.task( - '!broccoli.js.prod', - () => angularBuilder.rebuildBrowserProdTree( - {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks})); +gulp.task('!broccoli.js.prod', () => angularBuilder.rebuildBrowserProdTree({ + generateEs6: generateEs6, + projects: cliArgsProjects, + noTypeChecks: cliArgs.noTypeChecks, + useBundles: cliArgs.useBundles +})); gulp.task('build.js.dev', ['build/clean.js'], function(done) { runSequence('broccoli.js.dev', 'build.css.material', sequenceComplete(done)); @@ -1011,9 +1015,12 @@ var firstBuildJsCjs = true; * private task */ gulp.task('!build.js.cjs', function() { - return angularBuilder - .rebuildNodeTree( - {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks}) + return angularBuilder.rebuildNodeTree({ + generateEs6: generateEs6, + projects: cliArgsProjects, + noTypeChecks: cliArgs.noTypeChecks, + useBundles: cliArgs.useBundles + }) .then(function() { if (firstBuildJsCjs) { firstBuildJsCjs = false; diff --git a/scripts/ci/build_js.sh b/scripts/ci/build_js.sh index 7e9d7ff7379c0..78d5b59393476 100755 --- a/scripts/ci/build_js.sh +++ b/scripts/ci/build_js.sh @@ -8,4 +8,4 @@ SCRIPT_DIR=$(dirname $0) source $SCRIPT_DIR/env_dart.sh cd $SCRIPT_DIR/../.. -node --max-old-space-size=2000 ./node_modules/.bin/gulp build.js \ No newline at end of file +node --max-old-space-size=2000 ./node_modules/.bin/gulp build.js --useBundles diff --git a/tools/broccoli/angular_builder.ts b/tools/broccoli/angular_builder.ts index 66a857b6d0ad5..032278a9d0481 100644 --- a/tools/broccoli/angular_builder.ts +++ b/tools/broccoli/angular_builder.ts @@ -15,6 +15,7 @@ type Options = { projects: ProjectMap; noTypeChecks: boolean; generateEs6: boolean; +useBundles: boolean; } ; @@ -73,7 +74,8 @@ export class AngularBuilder { sourceMaps: true, projects: opts.projects, noTypeChecks: opts.noTypeChecks, - generateEs6: opts.generateEs6 + generateEs6: opts.generateEs6, + useBundles: opts.useBundles }, path.join(this.outputPath, 'js', 'dev')); return new broccoli.Builder(tree); @@ -88,7 +90,8 @@ export class AngularBuilder { sourceMaps: false, projects: opts.projects, noTypeChecks: opts.noTypeChecks, - generateEs6: opts.generateEs6 + generateEs6: opts.generateEs6, + useBundles: opts.useBundles }, path.join(this.outputPath, 'js', 'prod')); return new broccoli.Builder(tree); diff --git a/tools/broccoli/html-replace/SCRIPTS.html b/tools/broccoli/html-replace/SCRIPTS.html index 6f7bea55fb975..2195c9ac9e495 100644 --- a/tools/broccoli/html-replace/SCRIPTS.html +++ b/tools/broccoli/html-replace/SCRIPTS.html @@ -1,26 +1,48 @@ - - - - - - - - + + diff --git a/modules/payload_tests/hello_world/ts/webpack/index.ts b/modules/payload_tests/hello_world/ts/webpack/index.ts new file mode 100644 index 0000000000000..a0cfbe9e03e79 --- /dev/null +++ b/modules/payload_tests/hello_world/ts/webpack/index.ts @@ -0,0 +1,15 @@ +import {Component} from 'angular2/core'; +import {bootstrap} from 'angular2/bootstrap'; + +@Component({ + selector: 'hello-app', + template: ` +

Hello, {{name}}!

+ +` +}) +export class HelloCmp { + name = 'World'; +} + +bootstrap(HelloCmp); diff --git a/scripts/ci/build_and_test.sh b/scripts/ci/build_and_test.sh index 35ffaf6483330..d13bfa0eb059a 100755 --- a/scripts/ci/build_and_test.sh +++ b/scripts/ci/build_and_test.sh @@ -22,6 +22,7 @@ elif [ "$MODE" = "build_only" ]; then elif [ "$MODE" = "payload" ]; then source ${SCRIPT_DIR}/env_dart.sh ./node_modules/.bin/gulp test.payload.dart/ci + ./node_modules/.bin/gulp test.payload.js/ci else ${SCRIPT_DIR}/build_$MODE.sh ${SCRIPT_DIR}/test_$MODE.sh diff --git a/tools/broccoli/trees/browser_tree.ts b/tools/broccoli/trees/browser_tree.ts index 6759a2b043259..5edd8777cb9aa 100644 --- a/tools/broccoli/trees/browser_tree.ts +++ b/tools/broccoli/trees/browser_tree.ts @@ -108,6 +108,12 @@ module.exports = function makeBrowserTree(options, destinationPath) { {include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchmarks_external/'}); } + if (modules.payload_tests) { + var payloadTestsTree = + new Funnel('modules/payload_tests', + {include: ['**/ts/**'], exclude: ['e2e_test/**'], destDir: '/payload_tests/'}); + } + if (modules.playground) { var playgroundTree = new Funnel('modules/playground', @@ -125,6 +131,7 @@ module.exports = function makeBrowserTree(options, destinationPath) { angular2MaterialTree, benchmarksTree, benchmarksExternalTree, + payloadTestsTree, playgroundTree, benchpressTree ]); @@ -215,8 +222,10 @@ module.exports = function makeBrowserTree(options, destinationPath) { modulesTree, {include: ['**/*'], exclude: ['**/*.{html,ts,dart}'], destDir: '/'}); } - var htmlTree = new Funnel( - modulesTree, {include: ['*/src/**/*.html', '**/playground/**/*.html'], destDir: '/'}); + var htmlTree = new Funnel(modulesTree, { + include: ['*/src/**/*.html', '**/playground/**/*.html', '**/payload_tests/**/ts/**/*.html'], + destDir: '/' + }); if (modules.benchmarks || modules.benchmarks_external || modules.playground) { htmlTree = replace(htmlTree, { diff --git a/tools/broccoli/trees/dart_tree.ts b/tools/broccoli/trees/dart_tree.ts index 06a713fc704f2..f94bf89eff55b 100644 --- a/tools/broccoli/trees/dart_tree.ts +++ b/tools/broccoli/trees/dart_tree.ts @@ -14,17 +14,18 @@ import dartfmt from '../broccoli-dartfmt'; import replace from '../broccoli-replace'; var global_excludes = [ - 'angular2/http*', - 'angular2/upgrade*', 'angular2/examples/**/ts/**/*', + 'angular2/http*', 'angular2/http/**/*', 'angular2/src/http/**/*', - 'angular2/test/http/**/*', 'angular2/src/upgrade/**/*', + 'angular2/test/http/**/*', 'angular2/test/upgrade/**/*', + 'angular2/upgrade*', + 'payload_tests/**/ts/**/*', 'playground/src/http/**/*', - 'playground/test/http/**/*', 'playground/src/jsonp/**/*', + 'playground/test/http/**/*', 'playground/test/jsonp/**/*' ]; @@ -145,7 +146,12 @@ function getDocsTree() { var licenses = new MultiCopy('', { srcPath: 'LICENSE', targetPatterns: ['modules/*'], - exclude: ['*/angular2/src/http', '*/upgrade', '*/angular1_router'] // Not in dart. + exclude: [ + '*/angular1_router', + '*/angular2/src/http', + '*/payload_tests', + '*/upgrade' + ] // Not in dart. }); licenses = stew.rename(licenses, stripModulePrefix); diff --git a/tools/broccoli/trees/node_tree.ts b/tools/broccoli/trees/node_tree.ts index 9b5c40e5d1bfc..69384fcbb9265 100644 --- a/tools/broccoli/trees/node_tree.ts +++ b/tools/broccoli/trees/node_tree.ts @@ -74,8 +74,8 @@ module.exports = function makeNodeTree(projects, destinationPath) { 'angular2/test/web_workers/worker/renderer_integration_spec.ts', 'angular2/test/upgrade/**/*.ts', - 'angular1_router/**', + 'payload_tests/**' ] }); From df3074fdfed0e2dbac5bf26138395b79fd14de2b Mon Sep 17 00:00:00 2001 From: Jason Teplitz Date: Sun, 20 Dec 2015 18:10:36 -0500 Subject: [PATCH 44/45] feat(core/application_ref): Allow asyncronous app initializers. closes #5929. Closes #6063 --- modules/angular2/src/core/application_ref.ts | 54 +++++++-- .../test/core/application_ref_spec.ts | 111 ++++++++++++++++-- 2 files changed, 143 insertions(+), 22 deletions(-) diff --git a/modules/angular2/src/core/application_ref.ts b/modules/angular2/src/core/application_ref.ts index d4d799bea023d..3dd2e35da30e9 100644 --- a/modules/angular2/src/core/application_ref.ts +++ b/modules/angular2/src/core/application_ref.ts @@ -217,25 +217,36 @@ export class PlatformRef_ extends PlatformRef { application(providers: Array): ApplicationRef { var app = this._initApp(createNgZone(), providers); - return app; + if (PromiseWrapper.isPromise(app)) { + throw new BaseException( + "Cannot use asyncronous app initializers with application. Use asyncApplication instead."); + } + return app; } asyncApplication(bindingFn: (zone: NgZone) => Promise>, additionalProviders?: Array): Promise { var zone = createNgZone(); var completer = PromiseWrapper.completer(); - zone.run(() => { - PromiseWrapper.then(bindingFn(zone), (providers: Array) => { - if (isPresent(additionalProviders)) { - providers = ListWrapper.concat(providers, additionalProviders); - } - completer.resolve(this._initApp(zone, providers)); + if (bindingFn === null) { + completer.resolve(this._initApp(zone, additionalProviders)); + } else { + zone.run(() => { + PromiseWrapper.then(bindingFn(zone), (providers: Array) => { + if (isPresent(additionalProviders)) { + providers = ListWrapper.concat(providers, additionalProviders); + } + let promise = this._initApp(zone, providers); + completer.resolve(promise); + }); }); - }); + } return completer.promise; } - private _initApp(zone: NgZone, providers: Array): ApplicationRef { + private _initApp(zone: NgZone, + providers: Array): Promise| + ApplicationRef { var injector: Injector; var app: ApplicationRef; zone.run(() => { @@ -259,8 +270,12 @@ export class PlatformRef_ extends PlatformRef { }); app = new ApplicationRef_(this, zone, injector); this._applications.push(app); - _runAppInitializers(injector); - return app; + var promise = _runAppInitializers(injector); + if (promise !== null) { + return PromiseWrapper.then(promise, (_) => app); + } else { + return app; + } } dispose(): void { @@ -273,9 +288,22 @@ export class PlatformRef_ extends PlatformRef { _applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); } } -function _runAppInitializers(injector: Injector): void { +function _runAppInitializers(injector: Injector): Promise { let inits: Function[] = injector.getOptional(APP_INITIALIZER); - if (isPresent(inits)) inits.forEach(init => init()); + let promises: Promise[] = []; + if (isPresent(inits)) { + inits.forEach(init => { + var retVal = init(); + if (PromiseWrapper.isPromise(retVal)) { + promises.push(retVal); + } + }); + } + if (promises.length > 0) { + return PromiseWrapper.all(promises); + } else { + return null; + } } /** diff --git a/modules/angular2/test/core/application_ref_spec.ts b/modules/angular2/test/core/application_ref_spec.ts index 0f54b9c80f055..0d24f350c9c8a 100644 --- a/modules/angular2/test/core/application_ref_spec.ts +++ b/modules/angular2/test/core/application_ref_spec.ts @@ -11,13 +11,14 @@ import { AsyncTestCompleter, fakeAsync, tick, - inject + inject, + SpyObject } from 'angular2/testing_internal'; import {SpyChangeDetector} from './spies'; -import {ApplicationRef_, PlatformRef_} from "angular2/src/core/application_ref"; -import {Injector, Provider} from "angular2/core"; +import {ApplicationRef_, ApplicationRef, PlatformRef_} from "angular2/src/core/application_ref"; +import {Injector, Provider, APP_INITIALIZER} from "angular2/core"; import {ChangeDetectorRef_} from "angular2/src/core/change_detection/change_detector_ref"; -import {PromiseWrapper} from "angular2/src/facade/async"; +import {PromiseWrapper, PromiseCompleter, TimerWrapper} from "angular2/src/facade/async"; import {ListWrapper} from "angular2/src/facade/collection"; export function main() { @@ -33,7 +34,14 @@ export function main() { describe("PlatformRef", () => { describe("asyncApplication", () => { - it("should merge synchronous and asynchronous providers", + function expectProviders(injector: Injector, providers: Array): void { + for (let i = 0; i < providers.length; i++) { + let provider = providers[i]; + expect(injector.get(provider.token)).toBe(provider.useValue); + } + } + + it("should merge syncronous and asyncronous providers", inject([AsyncTestCompleter, Injector], (async, injector) => { let ref = new PlatformRef_(injector, null); let ASYNC_PROVIDERS = [new Provider(Foo, {useValue: new Foo()})]; @@ -41,14 +49,99 @@ export function main() { ref.asyncApplication((zone) => PromiseWrapper.resolve(ASYNC_PROVIDERS), SYNC_PROVIDERS) .then((appRef) => { var providers = ListWrapper.concat(ASYNC_PROVIDERS, SYNC_PROVIDERS); - for (var i = 0; i < providers.length; i++) { - var provider = providers[i]; - expect(appRef.injector.get(provider.token)).toBe(provider.useValue); - } + expectProviders(appRef.injector, providers); + async.done(); + }); + })); + + it("should allow function to be null", + inject([AsyncTestCompleter, Injector], (async, injector) => { + let ref = new PlatformRef_(injector, null); + let SYNC_PROVIDERS = [new Provider(Bar, {useValue: new Bar()})]; + ref.asyncApplication(null, SYNC_PROVIDERS) + .then((appRef) => { + expectProviders(appRef.injector, SYNC_PROVIDERS); + async.done(); + }); + })); + + function mockAsyncAppInitializer(completer, providers: Array = null, + injector?: Injector) { + return () => { + if (providers != null) { + expectProviders(injector, providers); + } + TimerWrapper.setTimeout(() => completer.resolve(true), 1); + return completer.promise; + }; + } + + function createSpyPromiseCompleter(): SpyObject { + let completer = PromiseWrapper.completer(); + let completerSpy = new SpyObject(); + // Note that in TypeScript we need to provide a value for the promise attribute + // whereas in dart we need to override the promise getter + completerSpy.promise = completer.promise; + completerSpy.spy("get:promise").andReturn(completer.promise); + completerSpy.spy("resolve").andCallFake(completer.resolve); + completerSpy.spy("reject").andCallFake(completer.reject); + return completerSpy; + } + + it("should wait for asyncronous app initializers", + inject([AsyncTestCompleter, Injector], (async, injector) => { + let ref = new PlatformRef_(injector, null); + + let completer = createSpyPromiseCompleter(); + let SYNC_PROVIDERS = [ + new Provider(Bar, {useValue: new Bar()}), + new Provider(APP_INITIALIZER, + {useValue: mockAsyncAppInitializer(completer), multi: true}) + ]; + ref.asyncApplication(null, SYNC_PROVIDERS) + .then((appRef) => { + expectProviders(appRef.injector, + SYNC_PROVIDERS.slice(0, SYNC_PROVIDERS.length - 1)); + expect(completer.spy("resolve")).toHaveBeenCalled(); + async.done(); + }); + })); + + it("should wait for async providers and then async app initializers", + inject([AsyncTestCompleter, Injector], (async, injector) => { + let ref = new PlatformRef_(injector, null); + let ASYNC_PROVIDERS = [new Provider(Foo, {useValue: new Foo()})]; + let completer = createSpyPromiseCompleter(); + let SYNC_PROVIDERS = [ + new Provider(Bar, {useValue: new Bar()}), + new Provider(APP_INITIALIZER, + { + useFactory: (injector) => mockAsyncAppInitializer( + completer, ASYNC_PROVIDERS, injector), + multi: true, + deps: [Injector] + }) + ]; + ref.asyncApplication((zone) => PromiseWrapper.resolve(ASYNC_PROVIDERS), SYNC_PROVIDERS) + .then((appRef) => { + expectProviders(appRef.injector, + SYNC_PROVIDERS.slice(0, SYNC_PROVIDERS.length - 1)); + expect(completer.spy("resolve")).toHaveBeenCalled(); async.done(); }); })); }); + + describe("application", () => { + it("should throw if an APP_INITIIALIZER returns a promise", inject([Injector], (injector) => { + let ref = new PlatformRef_(injector, null); + let appInitializer = new Provider( + APP_INITIALIZER, {useValue: () => PromiseWrapper.resolve([]), multi: true}); + expect(() => ref.application([appInitializer])) + .toThrowError( + "Cannot use asyncronous app initializers with application. Use asyncApplication instead."); + })); + }); }); } From 7b66a0d53fd43e6666c736d2f37ffa0f562b6ccc Mon Sep 17 00:00:00 2001 From: usernamealreadyis Date: Thu, 21 Jan 2016 23:42:19 +0700 Subject: [PATCH 45/45] Create .cla%3A%20yes new(text, old_name, new_name, comment, singleton = false) Creates a new Alias with a token stream of text that aliases old_name to new_name, has comment and is a singleton context. --- labels/.cla%3A%20yes | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 labels/.cla%3A%20yes diff --git a/labels/.cla%3A%20yes b/labels/.cla%3A%20yes new file mode 100644 index 0000000000000..ce50a3c69b7b9 --- /dev/null +++ b/labels/.cla%3A%20yes @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# File lib/labels/.cla%3A%20yes, line 36 +def initialize(text, old_name, new_name, comment, anular = false) + super() + + @text = text + @angular = angular + @old_name = old_name + @new_name = new_name + self.comment = comment +end