diff --git a/karma-js.conf.js b/karma-js.conf.js index dcc82b06a7..0138efeb36 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -21,11 +21,13 @@ module.exports = function(config) { // Loaded through the System loader, in `test-main.js`. {pattern: 'dist/all/@angular/**/*.js', included: false, watched: true}, - 'node_modules/core-js/client/core.js', - // include Angular v1 for upgrade module testing - 'node_modules/angular/angular.js', - 'node_modules/angular-mocks/angular-mocks.js', + // Serve AngularJS for `ngUpgrade` testing. + {pattern: 'node_modules/angular-1.5/angular.js', included: false, watched: false}, + {pattern: 'node_modules/angular-mocks-1.5/angular-mocks.js', included: false, watched: false}, + {pattern: 'node_modules/angular/angular.js', included: false, watched: false}, + {pattern: 'node_modules/angular-mocks/angular-mocks.js', included: false, watched: false}, + 'node_modules/core-js/client/core.js', 'node_modules/zone.js/dist/zone.js', 'node_modules/zone.js/dist/long-stack-trace-zone.js', 'node_modules/zone.js/dist/proxy.js', diff --git a/package.json b/package.json index e6c522895e..9e3c3cace7 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,10 @@ "@types/shelljs": "^0.7.8", "@types/source-map": "^0.5.1", "@types/systemjs": "0.19.32", - "angular": "1.5.0", - "angular-animate": "1.5.0", - "angular-mocks": "1.5.0", + "angular": "npm:angular@1.6", + "angular-1.5": "npm:angular@1.5", + "angular-mocks": "npm:angular-mocks@1.6", + "angular-mocks-1.5": "npm:angular-mocks@1.5", "base64-js": "1.2.1", "bower": "1.8.2", "browserstacktunnel-wrapper": "2.0.1", diff --git a/packages/upgrade/src/common/angular1.ts b/packages/upgrade/src/common/angular1.ts index 6638cc898f..cfcfa9179e 100644 --- a/packages/upgrade/src/common/angular1.ts +++ b/packages/upgrade/src/common/angular1.ts @@ -128,6 +128,7 @@ export type IAugmentedJQuery = Node[] & { isolateScope?: () => IScope; injector?: () => IInjectorService; remove?: () => void; + removeData?: () => void; }; export interface IProvider { $get: IInjectable; } export interface IProvideService { @@ -229,7 +230,7 @@ let angular: { bootstrap: noNg, module: noNg, element: noNg, - version: noNg, + version: undefined, resumeBootstrap: noNg, getTestability: noNg }; @@ -265,6 +266,7 @@ export function getAngularLib(): any { */ export function setAngularJSGlobal(ng: any): void { angular = ng; + version = ng && ng.version; } /** @@ -289,4 +291,4 @@ export const resumeBootstrap = () => angular.resumeBootstrap(); export const getTestability = (e: Element) => angular.getTestability(e); -export const version = angular.version; +export let version = angular.version; diff --git a/packages/upgrade/test/BUILD.bazel b/packages/upgrade/test/BUILD.bazel index 458787367a..a286c118be 100644 --- a/packages/upgrade/test/BUILD.bazel +++ b/packages/upgrade/test/BUILD.bazel @@ -23,8 +23,12 @@ ts_web_test( name = "test_web", bootstrap = [ "//:web_test_bootstrap_scripts", - "//:angularjs", + # "//:angularjs", ], + # Disable since tests need to request different AngularJS versions at + # runtime, which is not yet supported. + # (Related issue: https://github.com/bazelbuild/rules_typescript/issues/131) + tags = ["manual"], # do not sort deps = [ "//tools/testing:browser", diff --git a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts index 88e80c0751..d7110815ba 100644 --- a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts +++ b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts @@ -10,9 +10,9 @@ import {TestBed, getTestBed, inject} from '@angular/core/testing'; import * as angular from '@angular/upgrade/src/common/angular1'; import {DowngradeComponentAdapter, groupNodesBySelector} from '@angular/upgrade/src/common/downgrade_component_adapter'; -import {nodes} from './test_helpers'; +import {nodes, withEachNg1Version} from './test_helpers'; -{ +withEachNg1Version(() => { describe('DowngradeComponentAdapter', () => { describe('groupNodesBySelector', () => { it('should return an array of node collections for each selector', () => { @@ -190,4 +190,4 @@ import {nodes} from './test_helpers'; }); }); -} +}); diff --git a/packages/upgrade/test/common/test_helpers.ts b/packages/upgrade/test/common/test_helpers.ts index 827998ca76..e03f243367 100644 --- a/packages/upgrade/test/common/test_helpers.ts +++ b/packages/upgrade/test/common/test_helpers.ts @@ -5,6 +5,57 @@ * 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 */ +import {setAngularJSGlobal} from '@angular/upgrade/src/common/angular1'; + + +const ng1Versions = [ + { + label: '1.5', + files: ['angular-1.5/angular.js', 'angular-mocks-1.5/angular-mocks.js'], + }, + { + label: '1.6', + files: ['angular/angular.js', 'angular-mocks/angular-mocks.js'], + }, +]; + +export function createWithEachNg1VersionFn(setNg1: typeof setAngularJSGlobal) { + return (specSuite: () => void) => ng1Versions.forEach(({label, files}) => { + describe(`[AngularJS v${label}]`, () => { + beforeAll(done => { + // Load AngularJS before running tests. + files + .reduce( + (prev, file) => prev.then(() => new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.src = `base/node_modules/${file}`; + script.onerror = reject; + script.onload = () => { + document.body.removeChild(script); + resolve(); + }; + document.body.appendChild(script); + })), + Promise.resolve()) + .then(() => setNg1((window as any).angular)) + .then(done, done.fail); + }); + + afterAll(() => { + // In these tests we are loading different versions of AngularJS on the same window. + // AngularJS leaves an "expandoId" property on `document`, which can trick subsequent + // `window.angular` instances into believing an app is already bootstrapped. + (window as any).angular.element(document).removeData(); + + // Remove AngularJS to leave a clean state for subsequent tests. + setNg1(undefined); + delete (window as any).angular; + }); + + specSuite(); + }); + }); +} export function html(html: string): Element { // Don't return `body` itself, because using it as a `$rootElement` for ng1 @@ -33,3 +84,5 @@ export function nodes(html: string) { div.innerHTML = html.trim(); return Array.prototype.slice.call(div.childNodes); } + +export const withEachNg1Version = createWithEachNg1VersionFn(setAngularJSGlobal); diff --git a/packages/upgrade/test/dynamic/upgrade_spec.ts b/packages/upgrade/test/dynamic/upgrade_spec.ts index 8d09901f48..ae3044b89a 100644 --- a/packages/upgrade/test/dynamic/upgrade_spec.ts +++ b/packages/upgrade/test/dynamic/upgrade_spec.ts @@ -12,13 +12,13 @@ import {BrowserModule} from '@angular/platform-browser'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import * as angular from '@angular/upgrade/src/common/angular1'; import {UpgradeAdapter, UpgradeAdapterRef} from '@angular/upgrade/src/dynamic/upgrade_adapter'; -import {$digest, html, multiTrim} from './test_helpers'; +import {$digest, html, multiTrim, withEachNg1Version} from './test_helpers'; declare global { export var inject: Function; } -{ +withEachNg1Version(() => { describe('adapter: ng1 to ng2', () => { beforeEach(() => destroyPlatform()); afterEach(() => destroyPlatform()); @@ -2909,11 +2909,12 @@ declare global { upgradeAdapterRef = upgradeAdapter.registerForNg1Tests(['ng1']); }); - beforeEach( - inject((_$compile_: angular.ICompileService, _$rootScope_: angular.IRootScopeService) => { - $compile = _$compile_; - $rootScope = _$rootScope_; - })); + beforeEach(() => { + inject((_$compile_: angular.ICompileService, _$rootScope_: angular.IRootScopeService) => { + $compile = _$compile_; + $rootScope = _$rootScope_; + }); + }); it('should be able to test ng1 components that use ng2 components', async(() => { upgradeAdapterRef.ready(() => { @@ -2924,4 +2925,4 @@ declare global { })); }); }); -} +}); diff --git a/packages/upgrade/test/static/integration/change_detection_spec.ts b/packages/upgrade/test/static/integration/change_detection_spec.ts index 280e9442b4..affa2cd02b 100644 --- a/packages/upgrade/test/static/integration/change_detection_spec.ts +++ b/packages/upgrade/test/static/integration/change_detection_spec.ts @@ -13,9 +13,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeComponent, UpgradeModule, downgradeComponent} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; -import {bootstrap, html} from '../test_helpers'; +import {bootstrap, html, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('scope/component change-detection', () => { beforeEach(() => destroyPlatform()); afterEach(() => destroyPlatform()); @@ -156,4 +156,4 @@ import {bootstrap, html} from '../test_helpers'; // }); // })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/content_projection_spec.ts b/packages/upgrade/test/static/integration/content_projection_spec.ts index 0f31b02be0..6eea5ceb64 100644 --- a/packages/upgrade/test/static/integration/content_projection_spec.ts +++ b/packages/upgrade/test/static/integration/content_projection_spec.ts @@ -13,9 +13,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeComponent, UpgradeModule, downgradeComponent} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; -import {bootstrap, html, multiTrim} from '../test_helpers'; +import {bootstrap, html, multiTrim, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('content projection', () => { beforeEach(() => destroyPlatform()); @@ -173,4 +173,4 @@ import {bootstrap, html, multiTrim} from '../test_helpers'; }); })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/downgrade_component_spec.ts b/packages/upgrade/test/static/integration/downgrade_component_spec.ts index c5c91dfaad..6a7b4affcc 100644 --- a/packages/upgrade/test/static/integration/downgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_component_spec.ts @@ -13,9 +13,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeModule, downgradeComponent} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; -import {$apply, bootstrap, html, multiTrim} from '../test_helpers'; +import {$apply, bootstrap, html, multiTrim, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('downgrade ng2 component', () => { beforeEach(() => destroyPlatform()); @@ -642,4 +642,4 @@ import {$apply, bootstrap, html, multiTrim} from '../test_helpers'; })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/downgrade_module_spec.ts b/packages/upgrade/test/static/integration/downgrade_module_spec.ts index 02cfc2400b..d751d9a06b 100644 --- a/packages/upgrade/test/static/integration/downgrade_module_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_module_spec.ts @@ -16,10 +16,10 @@ import * as angular from '@angular/upgrade/static/src/common/angular1'; import {$ROOT_SCOPE, INJECTOR_KEY, LAZY_MODULE_REF} from '@angular/upgrade/static/src/common/constants'; import {LazyModuleRef} from '@angular/upgrade/static/src/common/util'; -import {html, multiTrim} from '../test_helpers'; +import {html, multiTrim, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { [true, false].forEach(propagateDigest => { describe(`lazy-load ng2 module (propagateDigest: ${propagateDigest})`, () => { @@ -611,4 +611,4 @@ import {html, multiTrim} from '../test_helpers'; })); }); }); -} +}); diff --git a/packages/upgrade/test/static/integration/examples_spec.ts b/packages/upgrade/test/static/integration/examples_spec.ts index 4796059628..9266a8ced7 100644 --- a/packages/upgrade/test/static/integration/examples_spec.ts +++ b/packages/upgrade/test/static/integration/examples_spec.ts @@ -13,9 +13,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeComponent, UpgradeModule, downgradeComponent} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; -import {bootstrap, html, multiTrim} from '../test_helpers'; +import {bootstrap, html, multiTrim, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('examples', () => { beforeEach(() => destroyPlatform()); @@ -84,4 +84,4 @@ import {bootstrap, html, multiTrim} from '../test_helpers'; }); })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/injection_spec.ts b/packages/upgrade/test/static/integration/injection_spec.ts index 12944f2cfb..1a427570e9 100644 --- a/packages/upgrade/test/static/integration/injection_spec.ts +++ b/packages/upgrade/test/static/integration/injection_spec.ts @@ -14,9 +14,9 @@ import {UpgradeModule, downgradeInjectable, getAngularJSGlobal, setAngularJSGlob import * as angular from '@angular/upgrade/static/src/common/angular1'; import {$INJECTOR, INJECTOR_KEY} from '@angular/upgrade/static/src/common/constants'; -import {bootstrap, html} from '../test_helpers'; +import {bootstrap, html, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('injection', () => { beforeEach(() => destroyPlatform()); @@ -101,13 +101,13 @@ import {bootstrap, html} from '../test_helpers'; })); it('should allow resetting angular at runtime', async(() => { - let wrappedBootstrapepedCalled = false; + let wrappedBootstrapCalled = false; const n: any = getAngularJSGlobal(); setAngularJSGlobal({ bootstrap: (...args: any[]) => { - wrappedBootstrapepedCalled = true; + wrappedBootstrapCalled = true; n.bootstrap(...args); }, module: n.module, @@ -125,7 +125,8 @@ import {bootstrap, html} from '../test_helpers'; const ng1Module = angular.module('ng1Module', []); bootstrap(platformBrowserDynamic(), Ng2Module, html('
'), ng1Module) - .then((upgrade) => { expect(wrappedBootstrapepedCalled).toEqual(true); }); + .then(upgrade => expect(wrappedBootstrapCalled).toBe(true)) + .then(() => setAngularJSGlobal(n)); // Reset the AngularJS global. })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/testability_spec.ts b/packages/upgrade/test/static/integration/testability_spec.ts index ee374c6eb8..73d9712e54 100644 --- a/packages/upgrade/test/static/integration/testability_spec.ts +++ b/packages/upgrade/test/static/integration/testability_spec.ts @@ -14,9 +14,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeModule} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; -import {bootstrap, html} from '../test_helpers'; +import {bootstrap, html, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('testability', () => { beforeEach(() => destroyPlatform()); @@ -111,4 +111,4 @@ import {bootstrap, html} from '../test_helpers'; }); })); }); -} +}); diff --git a/packages/upgrade/test/static/integration/upgrade_component_spec.ts b/packages/upgrade/test/static/integration/upgrade_component_spec.ts index 61f5863ec7..58d07514bc 100644 --- a/packages/upgrade/test/static/integration/upgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/upgrade_component_spec.ts @@ -14,9 +14,9 @@ import {UpgradeComponent, UpgradeModule, downgradeComponent} from '@angular/upgr import * as angular from '@angular/upgrade/static/src/common/angular1'; import {$SCOPE} from '@angular/upgrade/static/src/common/constants'; -import {$digest, bootstrap, html, multiTrim} from '../test_helpers'; +import {$digest, bootstrap, html, multiTrim, withEachNg1Version} from '../test_helpers'; -{ +withEachNg1Version(() => { describe('upgrade ng1 component', () => { beforeEach(() => destroyPlatform()); @@ -3199,21 +3199,25 @@ import {$digest, bootstrap, html, multiTrim} from '../test_helpers'; const element = html(``); bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(adapter => { - // Initial change + // Get to a stable `$digest` state. + $digest(adapter); + + // Initial change. + // (Do not use a specific number due to differences between AngularJS 1.5/1.6.) + expect(controllerDoCheckA.calls.count()).toBeGreaterThan(0); + expect(controllerDoCheckB.calls.count()).toBeGreaterThan(0); + controllerDoCheckA.calls.reset(); + controllerDoCheckB.calls.reset(); + + // Run a `$digest` + $digest(adapter); expect(controllerDoCheckA.calls.count()).toBe(1); expect(controllerDoCheckB.calls.count()).toBe(1); - // Run a `$digest` - // (Since it's the first one since the `$doCheck` watcher was added, - // the `watchFn` will be run twice.) - $digest(adapter); - expect(controllerDoCheckA.calls.count()).toBe(3); - expect(controllerDoCheckB.calls.count()).toBe(3); - // Run another `$digest` $digest(adapter); - expect(controllerDoCheckA.calls.count()).toBe(4); - expect(controllerDoCheckB.calls.count()).toBe(4); + expect(controllerDoCheckA.calls.count()).toBe(2); + expect(controllerDoCheckB.calls.count()).toBe(2); }); })); @@ -3958,4 +3962,4 @@ import {$digest, bootstrap, html, multiTrim} from '../test_helpers'; }); })); }); -} +}); diff --git a/packages/upgrade/test/static/test_helpers.ts b/packages/upgrade/test/static/test_helpers.ts index 3afd946fe4..cb94b3bb52 100644 --- a/packages/upgrade/test/static/test_helpers.ts +++ b/packages/upgrade/test/static/test_helpers.ts @@ -11,6 +11,7 @@ import {UpgradeModule} from '@angular/upgrade/static'; import * as angular from '@angular/upgrade/static/src/common/angular1'; import {$ROOT_SCOPE} from '@angular/upgrade/static/src/common/constants'; +import {createWithEachNg1VersionFn} from '../common/test_helpers'; export * from '../common/test_helpers'; export function bootstrap( @@ -35,6 +36,8 @@ export function bootstrap( }); } +export const withEachNg1Version = createWithEachNg1VersionFn(angular.setAngularJSGlobal); + export function $apply(adapter: UpgradeModule, exp: angular.Ng1Expression) { const $rootScope = adapter.$injector.get($ROOT_SCOPE) as angular.IRootScopeService; $rootScope.$apply(exp); diff --git a/yarn.lock b/yarn.lock index 65feb7dacd..f376077df2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -250,17 +250,21 @@ amdetective@0.0.2: dependencies: esprima "~1.2.2" -angular-animate@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/angular-animate/-/angular-animate-1.5.0.tgz#0e31f31fa7ab2ddf5ea5787e476548644d62fb93" +"angular-1.5@npm:angular@1.5": + version "1.5.11" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.5.11.tgz#8c5ba7386f15965c9acf3429f6881553aada30d6" -angular-mocks@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.5.0.tgz#81b3e4b21098d7c545c6f0a0a97f897b26879dd9" +"angular-mocks-1.5@npm:angular-mocks@1.5": + version "1.5.11" + resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.5.11.tgz#a0e1dd0ea55fd77ee7a757d75536c5e964c86f81" -angular@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.5.0.tgz#d96ee97ab6df6cfd0915accbee484d098adb74ec" +"angular-mocks@npm:angular-mocks@1.6": + version "1.6.9" + resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.6.9.tgz#4fed8c8293a5080e0919a7ff0dcf0f704864b7ba" + +"angular@npm:angular@1.6": + version "1.6.9" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.9.tgz#bc812932e18909038412d594a5990f4bb66c0619" ansi-align@^1.1.0: version "1.1.0"